diff options
Diffstat (limited to 'target/linux/mediatek/patches-5.4')
41 files changed, 0 insertions, 13622 deletions
diff --git a/target/linux/mediatek/patches-5.4/0001-v5.7-spi-make-spi-max-frequency-optional.patch b/target/linux/mediatek/patches-5.4/0001-v5.7-spi-make-spi-max-frequency-optional.patch deleted file mode 100644 index 79ce15c37b..0000000000 --- a/target/linux/mediatek/patches-5.4/0001-v5.7-spi-make-spi-max-frequency-optional.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 671c3bf50ae498dc12aef6c70abe5cfa066b1348 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo <gch981213@gmail.com> -Date: Fri, 6 Mar 2020 16:50:49 +0800 -Subject: [PATCH 1/2] spi: make spi-max-frequency optional - -We only need a spi-max-frequency when we specifically request a -spi frequency lower than the max speed of spi host. -This property is already documented as optional property and current -host drivers are implemented to operate at highest speed possible -when spi->max_speed_hz is 0. -This patch makes spi-max-frequency an optional property so that -we could just omit it to use max controller speed. - -Signed-off-by: Chuanhong Guo <gch981213@gmail.com> -Link: https://lore.kernel.org/r/20200306085052.28258-2-gch981213@gmail.com -Signed-off-by: Mark Brown <broonie@kernel.org> ---- - drivers/spi/spi.c | 9 ++------- - 1 file changed, 2 insertions(+), 7 deletions(-) - ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -1809,13 +1809,8 @@ static int of_spi_parse_dt(struct spi_co - spi->mode |= SPI_CS_HIGH; - - /* Device speed */ -- rc = of_property_read_u32(nc, "spi-max-frequency", &value); -- if (rc) { -- dev_err(&ctlr->dev, -- "%pOF has no valid 'spi-max-frequency' property (%d)\n", nc, rc); -- return rc; -- } -- spi->max_speed_hz = value; -+ if (!of_property_read_u32(nc, "spi-max-frequency", &value)) -+ spi->max_speed_hz = value; - - return 0; - } diff --git a/target/linux/mediatek/patches-5.4/0002-v5.7-spi-add-support-for-mediatek-spi-nor-controller.patch b/target/linux/mediatek/patches-5.4/0002-v5.7-spi-add-support-for-mediatek-spi-nor-controller.patch deleted file mode 100644 index 0a63bdddaf..0000000000 --- a/target/linux/mediatek/patches-5.4/0002-v5.7-spi-add-support-for-mediatek-spi-nor-controller.patch +++ /dev/null @@ -1,761 +0,0 @@ -From 881d1ee9fe81ff2be1b90809a07621be97404a57 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo <gch981213@gmail.com> -Date: Fri, 6 Mar 2020 16:50:50 +0800 -Subject: [PATCH 2/2] spi: add support for mediatek spi-nor controller - -This is a driver for mtk spi-nor controller using spi-mem interface. -The same controller already has limited support provided by mtk-quadspi -driver under spi-nor framework and this new driver is a replacement -for the old one. - -Comparing to the old driver, this driver has following advantages: -1. It can handle any full-duplex spi transfer up to 6 bytes, and - this is implemented using generic spi interface. -2. It take account into command opcode properly. The reading routine - in this controller can only use 0x03 or 0x0b as opcode on 1-1-1 - transfers, but old driver doesn't implement this properly. This - driver checks supported opcode explicitly and use (1) to perform - unmatched operations. -3. It properly handles SFDP reading. Old driver can't read SFDP - due to the bug mentioned in (2). -4. It can do 1-2-2 and 1-4-4 fast reading on spi-nor. These two ops - requires parsing SFDP, which isn't possible in old driver. And - the old driver is only flagged to support 1-1-2 mode. -5. It takes advantage of the DMA feature in this controller for - long reads and supports IRQ on DMA requests to free cpu cycles - from polling status registers on long DMA reading. It achieves - up to 17.5MB/s reading speed (1-4-4 mode) which is way faster - than the old one. IRQ is implemented as optional to maintain - backward compatibility. - -Signed-off-by: Chuanhong Guo <gch981213@gmail.com> -Link: https://lore.kernel.org/r/20200306085052.28258-3-gch981213@gmail.com -Signed-off-by: Mark Brown <broonie@kernel.org> ---- - drivers/spi/Kconfig | 10 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-mtk-nor.c | 689 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 700 insertions(+) - create mode 100644 drivers/spi/spi-mtk-nor.c - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -433,6 +433,16 @@ config SPI_MT7621 - help - This selects a driver for the MediaTek MT7621 SPI Controller. - -+config SPI_MTK_NOR -+ tristate "MediaTek SPI NOR controller" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ help -+ This enables support for SPI NOR controller found on MediaTek -+ ARM SoCs. This is a controller specifically for SPI-NOR flash. -+ It can perform generic SPI transfers up to 6 bytes via generic -+ SPI interface as well as several SPI-NOR specific instructions -+ via SPI MEM interface. -+ - config SPI_NPCM_FIU - tristate "Nuvoton NPCM FLASH Interface Unit" - depends on ARCH_NPCM || COMPILE_TEST ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -61,6 +61,7 @@ obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mp - obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o - obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o - obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o -+obj-$(CONFIG_SPI_MTK_NOR) += spi-mtk-nor.o - obj-$(CONFIG_SPI_MXIC) += spi-mxic.o - obj-$(CONFIG_SPI_MXS) += spi-mxs.o - obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o ---- /dev/null -+++ b/drivers/spi/spi-mtk-nor.c -@@ -0,0 +1,689 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// Mediatek SPI NOR controller driver -+// -+// Copyright (C) 2020 Chuanhong Guo <gch981213@gmail.com> -+ -+#include <linux/bits.h> -+#include <linux/clk.h> -+#include <linux/completion.h> -+#include <linux/dma-mapping.h> -+#include <linux/interrupt.h> -+#include <linux/io.h> -+#include <linux/iopoll.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/of_device.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/spi-mem.h> -+#include <linux/string.h> -+ -+#define DRIVER_NAME "mtk-spi-nor" -+ -+#define MTK_NOR_REG_CMD 0x00 -+#define MTK_NOR_CMD_WRITE BIT(4) -+#define MTK_NOR_CMD_PROGRAM BIT(2) -+#define MTK_NOR_CMD_READ BIT(0) -+#define MTK_NOR_CMD_MASK GENMASK(5, 0) -+ -+#define MTK_NOR_REG_PRG_CNT 0x04 -+#define MTK_NOR_REG_RDATA 0x0c -+ -+#define MTK_NOR_REG_RADR0 0x10 -+#define MTK_NOR_REG_RADR(n) (MTK_NOR_REG_RADR0 + 4 * (n)) -+#define MTK_NOR_REG_RADR3 0xc8 -+ -+#define MTK_NOR_REG_WDATA 0x1c -+ -+#define MTK_NOR_REG_PRGDATA0 0x20 -+#define MTK_NOR_REG_PRGDATA(n) (MTK_NOR_REG_PRGDATA0 + 4 * (n)) -+#define MTK_NOR_REG_PRGDATA_MAX 5 -+ -+#define MTK_NOR_REG_SHIFT0 0x38 -+#define MTK_NOR_REG_SHIFT(n) (MTK_NOR_REG_SHIFT0 + 4 * (n)) -+#define MTK_NOR_REG_SHIFT_MAX 9 -+ -+#define MTK_NOR_REG_CFG1 0x60 -+#define MTK_NOR_FAST_READ BIT(0) -+ -+#define MTK_NOR_REG_CFG2 0x64 -+#define MTK_NOR_WR_CUSTOM_OP_EN BIT(4) -+#define MTK_NOR_WR_BUF_EN BIT(0) -+ -+#define MTK_NOR_REG_PP_DATA 0x98 -+ -+#define MTK_NOR_REG_IRQ_STAT 0xa8 -+#define MTK_NOR_REG_IRQ_EN 0xac -+#define MTK_NOR_IRQ_DMA BIT(7) -+#define MTK_NOR_IRQ_MASK GENMASK(7, 0) -+ -+#define MTK_NOR_REG_CFG3 0xb4 -+#define MTK_NOR_DISABLE_WREN BIT(7) -+#define MTK_NOR_DISABLE_SR_POLL BIT(5) -+ -+#define MTK_NOR_REG_WP 0xc4 -+#define MTK_NOR_ENABLE_SF_CMD 0x30 -+ -+#define MTK_NOR_REG_BUSCFG 0xcc -+#define MTK_NOR_4B_ADDR BIT(4) -+#define MTK_NOR_QUAD_ADDR BIT(3) -+#define MTK_NOR_QUAD_READ BIT(2) -+#define MTK_NOR_DUAL_ADDR BIT(1) -+#define MTK_NOR_DUAL_READ BIT(0) -+#define MTK_NOR_BUS_MODE_MASK GENMASK(4, 0) -+ -+#define MTK_NOR_REG_DMA_CTL 0x718 -+#define MTK_NOR_DMA_START BIT(0) -+ -+#define MTK_NOR_REG_DMA_FADR 0x71c -+#define MTK_NOR_REG_DMA_DADR 0x720 -+#define MTK_NOR_REG_DMA_END_DADR 0x724 -+ -+#define MTK_NOR_PRG_MAX_SIZE 6 -+// Reading DMA src/dst addresses have to be 16-byte aligned -+#define MTK_NOR_DMA_ALIGN 16 -+#define MTK_NOR_DMA_ALIGN_MASK (MTK_NOR_DMA_ALIGN - 1) -+// and we allocate a bounce buffer if destination address isn't aligned. -+#define MTK_NOR_BOUNCE_BUF_SIZE PAGE_SIZE -+ -+// Buffered page program can do one 128-byte transfer -+#define MTK_NOR_PP_SIZE 128 -+ -+#define CLK_TO_US(sp, clkcnt) ((clkcnt) * 1000000 / sp->spi_freq) -+ -+struct mtk_nor { -+ struct spi_controller *ctlr; -+ struct device *dev; -+ void __iomem *base; -+ u8 *buffer; -+ struct clk *spi_clk; -+ struct clk *ctlr_clk; -+ unsigned int spi_freq; -+ bool wbuf_en; -+ bool has_irq; -+ struct completion op_done; -+}; -+ -+static inline void mtk_nor_rmw(struct mtk_nor *sp, u32 reg, u32 set, u32 clr) -+{ -+ u32 val = readl(sp->base + reg); -+ -+ val &= ~clr; -+ val |= set; -+ writel(val, sp->base + reg); -+} -+ -+static inline int mtk_nor_cmd_exec(struct mtk_nor *sp, u32 cmd, ulong clk) -+{ -+ ulong delay = CLK_TO_US(sp, clk); -+ u32 reg; -+ int ret; -+ -+ writel(cmd, sp->base + MTK_NOR_REG_CMD); -+ ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CMD, reg, !(reg & cmd), -+ delay / 3, (delay + 1) * 200); -+ if (ret < 0) -+ dev_err(sp->dev, "command %u timeout.\n", cmd); -+ return ret; -+} -+ -+static void mtk_nor_set_addr(struct mtk_nor *sp, const struct spi_mem_op *op) -+{ -+ u32 addr = op->addr.val; -+ int i; -+ -+ for (i = 0; i < 3; i++) { -+ writeb(addr & 0xff, sp->base + MTK_NOR_REG_RADR(i)); -+ addr >>= 8; -+ } -+ if (op->addr.nbytes == 4) { -+ writeb(addr & 0xff, sp->base + MTK_NOR_REG_RADR3); -+ mtk_nor_rmw(sp, MTK_NOR_REG_BUSCFG, MTK_NOR_4B_ADDR, 0); -+ } else { -+ mtk_nor_rmw(sp, MTK_NOR_REG_BUSCFG, 0, MTK_NOR_4B_ADDR); -+ } -+} -+ -+static bool mtk_nor_match_read(const struct spi_mem_op *op) -+{ -+ int dummy = 0; -+ -+ if (op->dummy.buswidth) -+ dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth; -+ -+ if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) { -+ if (op->addr.buswidth == 1) -+ return dummy == 8; -+ else if (op->addr.buswidth == 2) -+ return dummy == 4; -+ else if (op->addr.buswidth == 4) -+ return dummy == 6; -+ } else if ((op->addr.buswidth == 1) && (op->data.buswidth == 1)) { -+ if (op->cmd.opcode == 0x03) -+ return dummy == 0; -+ else if (op->cmd.opcode == 0x0b) -+ return dummy == 8; -+ } -+ return false; -+} -+ -+static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) -+{ -+ size_t len; -+ -+ if (!op->data.nbytes) -+ return 0; -+ -+ if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) { -+ if ((op->data.dir == SPI_MEM_DATA_IN) && -+ mtk_nor_match_read(op)) { -+ if ((op->addr.val & MTK_NOR_DMA_ALIGN_MASK) || -+ (op->data.nbytes < MTK_NOR_DMA_ALIGN)) -+ op->data.nbytes = 1; -+ else if (!((ulong)(op->data.buf.in) & -+ MTK_NOR_DMA_ALIGN_MASK)) -+ op->data.nbytes &= ~MTK_NOR_DMA_ALIGN_MASK; -+ else if (op->data.nbytes > MTK_NOR_BOUNCE_BUF_SIZE) -+ op->data.nbytes = MTK_NOR_BOUNCE_BUF_SIZE; -+ return 0; -+ } else if (op->data.dir == SPI_MEM_DATA_OUT) { -+ if (op->data.nbytes >= MTK_NOR_PP_SIZE) -+ op->data.nbytes = MTK_NOR_PP_SIZE; -+ else -+ op->data.nbytes = 1; -+ return 0; -+ } -+ } -+ -+ len = MTK_NOR_PRG_MAX_SIZE - sizeof(op->cmd.opcode) - op->addr.nbytes - -+ op->dummy.nbytes; -+ if (op->data.nbytes > len) -+ op->data.nbytes = len; -+ -+ return 0; -+} -+ -+static bool mtk_nor_supports_op(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ size_t len; -+ -+ if (op->cmd.buswidth != 1) -+ return false; -+ -+ if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) { -+ if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op)) -+ return true; -+ else if (op->data.dir == SPI_MEM_DATA_OUT) -+ return (op->addr.buswidth == 1) && -+ (op->dummy.buswidth == 0) && -+ (op->data.buswidth == 1); -+ } -+ len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; -+ if ((len > MTK_NOR_PRG_MAX_SIZE) || -+ ((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE))) -+ return false; -+ return true; -+} -+ -+static void mtk_nor_setup_bus(struct mtk_nor *sp, const struct spi_mem_op *op) -+{ -+ u32 reg = 0; -+ -+ if (op->addr.nbytes == 4) -+ reg |= MTK_NOR_4B_ADDR; -+ -+ if (op->data.buswidth == 4) { -+ reg |= MTK_NOR_QUAD_READ; -+ writeb(op->cmd.opcode, sp->base + MTK_NOR_REG_PRGDATA(4)); -+ if (op->addr.buswidth == 4) -+ reg |= MTK_NOR_QUAD_ADDR; -+ } else if (op->data.buswidth == 2) { -+ reg |= MTK_NOR_DUAL_READ; -+ writeb(op->cmd.opcode, sp->base + MTK_NOR_REG_PRGDATA(3)); -+ if (op->addr.buswidth == 2) -+ reg |= MTK_NOR_DUAL_ADDR; -+ } else { -+ if (op->cmd.opcode == 0x0b) -+ mtk_nor_rmw(sp, MTK_NOR_REG_CFG1, MTK_NOR_FAST_READ, 0); -+ else -+ mtk_nor_rmw(sp, MTK_NOR_REG_CFG1, 0, MTK_NOR_FAST_READ); -+ } -+ mtk_nor_rmw(sp, MTK_NOR_REG_BUSCFG, reg, MTK_NOR_BUS_MODE_MASK); -+} -+ -+static int mtk_nor_read_dma(struct mtk_nor *sp, u32 from, unsigned int length, -+ u8 *buffer) -+{ -+ int ret = 0; -+ ulong delay; -+ u32 reg; -+ dma_addr_t dma_addr; -+ -+ dma_addr = dma_map_single(sp->dev, buffer, length, DMA_FROM_DEVICE); -+ if (dma_mapping_error(sp->dev, dma_addr)) { -+ dev_err(sp->dev, "failed to map dma buffer.\n"); -+ return -EINVAL; -+ } -+ -+ writel(from, sp->base + MTK_NOR_REG_DMA_FADR); -+ writel(dma_addr, sp->base + MTK_NOR_REG_DMA_DADR); -+ writel(dma_addr + length, sp->base + MTK_NOR_REG_DMA_END_DADR); -+ -+ if (sp->has_irq) { -+ reinit_completion(&sp->op_done); -+ mtk_nor_rmw(sp, MTK_NOR_REG_IRQ_EN, MTK_NOR_IRQ_DMA, 0); -+ } -+ -+ mtk_nor_rmw(sp, MTK_NOR_REG_DMA_CTL, MTK_NOR_DMA_START, 0); -+ -+ delay = CLK_TO_US(sp, (length + 5) * BITS_PER_BYTE); -+ -+ if (sp->has_irq) { -+ if (!wait_for_completion_timeout(&sp->op_done, -+ (delay + 1) * 100)) -+ ret = -ETIMEDOUT; -+ } else { -+ ret = readl_poll_timeout(sp->base + MTK_NOR_REG_DMA_CTL, reg, -+ !(reg & MTK_NOR_DMA_START), delay / 3, -+ (delay + 1) * 100); -+ } -+ -+ dma_unmap_single(sp->dev, dma_addr, length, DMA_FROM_DEVICE); -+ if (ret < 0) -+ dev_err(sp->dev, "dma read timeout.\n"); -+ -+ return ret; -+} -+ -+static int mtk_nor_read_bounce(struct mtk_nor *sp, u32 from, -+ unsigned int length, u8 *buffer) -+{ -+ unsigned int rdlen; -+ int ret; -+ -+ if (length & MTK_NOR_DMA_ALIGN_MASK) -+ rdlen = (length + MTK_NOR_DMA_ALIGN) & ~MTK_NOR_DMA_ALIGN_MASK; -+ else -+ rdlen = length; -+ -+ ret = mtk_nor_read_dma(sp, from, rdlen, sp->buffer); -+ if (ret) -+ return ret; -+ -+ memcpy(buffer, sp->buffer, length); -+ return 0; -+} -+ -+static int mtk_nor_read_pio(struct mtk_nor *sp, const struct spi_mem_op *op) -+{ -+ u8 *buf = op->data.buf.in; -+ int ret; -+ -+ ret = mtk_nor_cmd_exec(sp, MTK_NOR_CMD_READ, 6 * BITS_PER_BYTE); -+ if (!ret) -+ buf[0] = readb(sp->base + MTK_NOR_REG_RDATA); -+ return ret; -+} -+ -+static int mtk_nor_write_buffer_enable(struct mtk_nor *sp) -+{ -+ int ret; -+ u32 val; -+ -+ if (sp->wbuf_en) -+ return 0; -+ -+ val = readl(sp->base + MTK_NOR_REG_CFG2); -+ writel(val | MTK_NOR_WR_BUF_EN, sp->base + MTK_NOR_REG_CFG2); -+ ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CFG2, val, -+ val & MTK_NOR_WR_BUF_EN, 0, 10000); -+ if (!ret) -+ sp->wbuf_en = true; -+ return ret; -+} -+ -+static int mtk_nor_write_buffer_disable(struct mtk_nor *sp) -+{ -+ int ret; -+ u32 val; -+ -+ if (!sp->wbuf_en) -+ return 0; -+ val = readl(sp->base + MTK_NOR_REG_CFG2); -+ writel(val & ~MTK_NOR_WR_BUF_EN, sp->base + MTK_NOR_REG_CFG2); -+ ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CFG2, val, -+ !(val & MTK_NOR_WR_BUF_EN), 0, 10000); -+ if (!ret) -+ sp->wbuf_en = false; -+ return ret; -+} -+ -+static int mtk_nor_pp_buffered(struct mtk_nor *sp, const struct spi_mem_op *op) -+{ -+ const u8 *buf = op->data.buf.out; -+ u32 val; -+ int ret, i; -+ -+ ret = mtk_nor_write_buffer_enable(sp); -+ if (ret < 0) -+ return ret; -+ -+ for (i = 0; i < op->data.nbytes; i += 4) { -+ val = buf[i + 3] << 24 | buf[i + 2] << 16 | buf[i + 1] << 8 | -+ buf[i]; -+ writel(val, sp->base + MTK_NOR_REG_PP_DATA); -+ } -+ return mtk_nor_cmd_exec(sp, MTK_NOR_CMD_WRITE, -+ (op->data.nbytes + 5) * BITS_PER_BYTE); -+} -+ -+static int mtk_nor_pp_unbuffered(struct mtk_nor *sp, -+ const struct spi_mem_op *op) -+{ -+ const u8 *buf = op->data.buf.out; -+ int ret; -+ -+ ret = mtk_nor_write_buffer_disable(sp); -+ if (ret < 0) -+ return ret; -+ writeb(buf[0], sp->base + MTK_NOR_REG_WDATA); -+ return mtk_nor_cmd_exec(sp, MTK_NOR_CMD_WRITE, 6 * BITS_PER_BYTE); -+} -+ -+int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) -+{ -+ struct mtk_nor *sp = spi_controller_get_devdata(mem->spi->master); -+ int ret; -+ -+ if ((op->data.nbytes == 0) || -+ ((op->addr.nbytes != 3) && (op->addr.nbytes != 4))) -+ return -ENOTSUPP; -+ -+ if (op->data.dir == SPI_MEM_DATA_OUT) { -+ mtk_nor_set_addr(sp, op); -+ writeb(op->cmd.opcode, sp->base + MTK_NOR_REG_PRGDATA0); -+ if (op->data.nbytes == MTK_NOR_PP_SIZE) -+ return mtk_nor_pp_buffered(sp, op); -+ return mtk_nor_pp_unbuffered(sp, op); -+ } -+ -+ if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op)) { -+ ret = mtk_nor_write_buffer_disable(sp); -+ if (ret < 0) -+ return ret; -+ mtk_nor_setup_bus(sp, op); -+ if (op->data.nbytes == 1) { -+ mtk_nor_set_addr(sp, op); -+ return mtk_nor_read_pio(sp, op); -+ } else if (((ulong)(op->data.buf.in) & -+ MTK_NOR_DMA_ALIGN_MASK)) { -+ return mtk_nor_read_bounce(sp, op->addr.val, -+ op->data.nbytes, -+ op->data.buf.in); -+ } else { -+ return mtk_nor_read_dma(sp, op->addr.val, -+ op->data.nbytes, -+ op->data.buf.in); -+ } -+ } -+ -+ return -ENOTSUPP; -+} -+ -+static int mtk_nor_setup(struct spi_device *spi) -+{ -+ struct mtk_nor *sp = spi_controller_get_devdata(spi->master); -+ -+ if (spi->max_speed_hz && (spi->max_speed_hz < sp->spi_freq)) { -+ dev_err(&spi->dev, "spi clock should be %u Hz.\n", -+ sp->spi_freq); -+ return -EINVAL; -+ } -+ spi->max_speed_hz = sp->spi_freq; -+ -+ return 0; -+} -+ -+static int mtk_nor_transfer_one_message(struct spi_controller *master, -+ struct spi_message *m) -+{ -+ struct mtk_nor *sp = spi_controller_get_devdata(master); -+ struct spi_transfer *t = NULL; -+ unsigned long trx_len = 0; -+ int stat = 0; -+ int reg_offset = MTK_NOR_REG_PRGDATA_MAX; -+ void __iomem *reg; -+ const u8 *txbuf; -+ u8 *rxbuf; -+ int i; -+ -+ list_for_each_entry(t, &m->transfers, transfer_list) { -+ txbuf = t->tx_buf; -+ for (i = 0; i < t->len; i++, reg_offset--) { -+ reg = sp->base + MTK_NOR_REG_PRGDATA(reg_offset); -+ if (txbuf) -+ writeb(txbuf[i], reg); -+ else -+ writeb(0, reg); -+ } -+ trx_len += t->len; -+ } -+ -+ writel(trx_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT); -+ -+ stat = mtk_nor_cmd_exec(sp, MTK_NOR_CMD_PROGRAM, -+ trx_len * BITS_PER_BYTE); -+ if (stat < 0) -+ goto msg_done; -+ -+ reg_offset = trx_len - 1; -+ list_for_each_entry(t, &m->transfers, transfer_list) { -+ rxbuf = t->rx_buf; -+ for (i = 0; i < t->len; i++, reg_offset--) { -+ reg = sp->base + MTK_NOR_REG_SHIFT(reg_offset); -+ if (rxbuf) -+ rxbuf[i] = readb(reg); -+ } -+ } -+ -+ m->actual_length = trx_len; -+msg_done: -+ m->status = stat; -+ spi_finalize_current_message(master); -+ -+ return 0; -+} -+ -+static void mtk_nor_disable_clk(struct mtk_nor *sp) -+{ -+ clk_disable_unprepare(sp->spi_clk); -+ clk_disable_unprepare(sp->ctlr_clk); -+} -+ -+static int mtk_nor_enable_clk(struct mtk_nor *sp) -+{ -+ int ret; -+ -+ ret = clk_prepare_enable(sp->spi_clk); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(sp->ctlr_clk); -+ if (ret) { -+ clk_disable_unprepare(sp->spi_clk); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int mtk_nor_init(struct mtk_nor *sp) -+{ -+ int ret; -+ -+ ret = mtk_nor_enable_clk(sp); -+ if (ret) -+ return ret; -+ -+ sp->spi_freq = clk_get_rate(sp->spi_clk); -+ -+ writel(MTK_NOR_ENABLE_SF_CMD, sp->base + MTK_NOR_REG_WP); -+ mtk_nor_rmw(sp, MTK_NOR_REG_CFG2, MTK_NOR_WR_CUSTOM_OP_EN, 0); -+ mtk_nor_rmw(sp, MTK_NOR_REG_CFG3, -+ MTK_NOR_DISABLE_WREN | MTK_NOR_DISABLE_SR_POLL, 0); -+ -+ return ret; -+} -+ -+static irqreturn_t mtk_nor_irq_handler(int irq, void *data) -+{ -+ struct mtk_nor *sp = data; -+ u32 irq_status, irq_enabled; -+ -+ irq_status = readl(sp->base + MTK_NOR_REG_IRQ_STAT); -+ irq_enabled = readl(sp->base + MTK_NOR_REG_IRQ_EN); -+ // write status back to clear interrupt -+ writel(irq_status, sp->base + MTK_NOR_REG_IRQ_STAT); -+ -+ if (!(irq_status & irq_enabled)) -+ return IRQ_NONE; -+ -+ if (irq_status & MTK_NOR_IRQ_DMA) { -+ complete(&sp->op_done); -+ writel(0, sp->base + MTK_NOR_REG_IRQ_EN); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static size_t mtk_max_msg_size(struct spi_device *spi) -+{ -+ return MTK_NOR_PRG_MAX_SIZE; -+} -+ -+static const struct spi_controller_mem_ops mtk_nor_mem_ops = { -+ .adjust_op_size = mtk_nor_adjust_op_size, -+ .supports_op = mtk_nor_supports_op, -+ .exec_op = mtk_nor_exec_op -+}; -+ -+static const struct of_device_id mtk_nor_match[] = { -+ { .compatible = "mediatek,mt8173-nor" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, mtk_nor_match); -+ -+static int mtk_nor_probe(struct platform_device *pdev) -+{ -+ struct spi_controller *ctlr; -+ struct mtk_nor *sp; -+ void __iomem *base; -+ u8 *buffer; -+ struct clk *spi_clk, *ctlr_clk; -+ int ret, irq; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ spi_clk = devm_clk_get(&pdev->dev, "spi"); -+ if (IS_ERR(spi_clk)) -+ return PTR_ERR(spi_clk); -+ -+ ctlr_clk = devm_clk_get(&pdev->dev, "sf"); -+ if (IS_ERR(ctlr_clk)) -+ return PTR_ERR(ctlr_clk); -+ -+ buffer = devm_kmalloc(&pdev->dev, -+ MTK_NOR_BOUNCE_BUF_SIZE + MTK_NOR_DMA_ALIGN, -+ GFP_KERNEL); -+ if (!buffer) -+ return -ENOMEM; -+ -+ if ((ulong)buffer & MTK_NOR_DMA_ALIGN_MASK) -+ buffer = (u8 *)(((ulong)buffer + MTK_NOR_DMA_ALIGN) & -+ ~MTK_NOR_DMA_ALIGN_MASK); -+ -+ ctlr = spi_alloc_master(&pdev->dev, sizeof(*sp)); -+ if (!ctlr) { -+ dev_err(&pdev->dev, "failed to allocate spi controller\n"); -+ return -ENOMEM; -+ } -+ -+ ctlr->bits_per_word_mask = SPI_BPW_MASK(8); -+ ctlr->dev.of_node = pdev->dev.of_node; -+ ctlr->max_message_size = mtk_max_msg_size; -+ ctlr->mem_ops = &mtk_nor_mem_ops; -+ ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; -+ ctlr->num_chipselect = 1; -+ ctlr->setup = mtk_nor_setup; -+ ctlr->transfer_one_message = mtk_nor_transfer_one_message; -+ -+ dev_set_drvdata(&pdev->dev, ctlr); -+ -+ sp = spi_controller_get_devdata(ctlr); -+ sp->base = base; -+ sp->buffer = buffer; -+ sp->has_irq = false; -+ sp->wbuf_en = false; -+ sp->ctlr = ctlr; -+ sp->dev = &pdev->dev; -+ sp->spi_clk = spi_clk; -+ sp->ctlr_clk = ctlr_clk; -+ -+ irq = platform_get_irq_optional(pdev, 0); -+ if (irq < 0) { -+ dev_warn(sp->dev, "IRQ not available."); -+ } else { -+ writel(MTK_NOR_IRQ_MASK, base + MTK_NOR_REG_IRQ_STAT); -+ writel(0, base + MTK_NOR_REG_IRQ_EN); -+ ret = devm_request_irq(sp->dev, irq, mtk_nor_irq_handler, 0, -+ pdev->name, sp); -+ if (ret < 0) { -+ dev_warn(sp->dev, "failed to request IRQ."); -+ } else { -+ init_completion(&sp->op_done); -+ sp->has_irq = true; -+ } -+ } -+ -+ ret = mtk_nor_init(sp); -+ if (ret < 0) { -+ kfree(ctlr); -+ return ret; -+ } -+ -+ dev_info(&pdev->dev, "spi frequency: %d Hz\n", sp->spi_freq); -+ -+ return devm_spi_register_controller(&pdev->dev, ctlr); -+} -+ -+static int mtk_nor_remove(struct platform_device *pdev) -+{ -+ struct spi_controller *ctlr; -+ struct mtk_nor *sp; -+ -+ ctlr = dev_get_drvdata(&pdev->dev); -+ sp = spi_controller_get_devdata(ctlr); -+ -+ mtk_nor_disable_clk(sp); -+ -+ return 0; -+} -+ -+static struct platform_driver mtk_nor_driver = { -+ .driver = { -+ .name = DRIVER_NAME, -+ .of_match_table = mtk_nor_match, -+ }, -+ .probe = mtk_nor_probe, -+ .remove = mtk_nor_remove, -+}; -+ -+module_platform_driver(mtk_nor_driver); -+ -+MODULE_DESCRIPTION("Mediatek SPI NOR controller driver"); -+MODULE_AUTHOR("Chuanhong Guo <gch981213@gmail.com>"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/target/linux/mediatek/patches-5.4/0003-switch-add-mt7531.patch b/target/linux/mediatek/patches-5.4/0003-switch-add-mt7531.patch deleted file mode 100644 index 6fae99c1f4..0000000000 --- a/target/linux/mediatek/patches-5.4/0003-switch-add-mt7531.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -329,6 +329,8 @@ config RTL8367B_PHY - - endif # RTL8366_SMI - -+source "drivers/net/phy/mtk/mt753x/Kconfig" -+ - comment "MII PHY device drivers" - - config SFP ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -109,3 +109,5 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o - obj-$(CONFIG_TERANETICS_PHY) += teranetics.o - obj-$(CONFIG_VITESSE_PHY) += vitesse.o - obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o -+obj-$(CONFIG_MT753X_GSW) += mtk/mt753x/ -+ diff --git a/target/linux/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch b/target/linux/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch deleted file mode 100644 index d40cbfb853..0000000000 --- a/target/linux/mediatek/patches-5.4/0005-dts-mt7622-add-gsw.patch +++ /dev/null @@ -1,258 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -53,6 +53,13 @@ - }; - }; - -+ gsw: gsw@0 { -+ compatible = "mediatek,mt753x"; -+ mediatek,ethsys = <ðsys>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ - leds { - compatible = "gpio-leds"; - -@@ -146,6 +153,36 @@ - }; - }; - -+&gsw { -+ mediatek,mdio = <&mdio>; -+ mediatek,portmap = "wllll"; -+ mediatek,mdio_master_pinmux = <0>; -+ reset-gpios = <&pio 54 0>; -+ interrupt-parent = <&pio>; -+ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; -+ status = "okay"; -+ -+ port5: port@5 { -+ compatible = "mediatek,mt753x-port"; -+ reg = <5>; -+ phy-mode = "rgmii"; -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ -+ port6: port@6 { -+ compatible = "mediatek,mt753x-port"; -+ reg = <6>; -+ phy-mode = "sgmii"; -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ }; -+ }; -+}; -+ - &i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -1,7 +1,6 @@ - /* -- * Copyright (c) 2017 MediaTek Inc. -- * Author: Ming Huang <ming.huang@mediatek.com> -- * Sean Wang <sean.wang@mediatek.com> -+ * Copyright (c) 2018 MediaTek Inc. -+ * Author: Ryder Lee <ryder.lee@mediatek.com> - * - * SPDX-License-Identifier: (GPL-2.0 OR MIT) - */ -@@ -14,7 +13,7 @@ - #include "mt6380.dtsi" - - / { -- model = "MediaTek MT7622 RFB1 board"; -+ model = "MT7622_MT7531 RFB"; - compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622"; - - aliases { -@@ -23,7 +22,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { -@@ -40,23 +39,36 @@ - - gpio-keys { - compatible = "gpio-keys"; -- poll-interval = <100>; - - factory { - label = "factory"; - linux,code = <BTN_0>; -- gpios = <&pio 0 0>; -+ gpios = <&pio 0 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = <KEY_WPS_BUTTON>; -- gpios = <&pio 102 0>; -+ gpios = <&pio 102 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ green { -+ label = "bpi-r64:pio:green"; -+ gpios = <&pio 89 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ red { -+ label = "bpi-r64:pio:red"; -+ gpios = <&pio 88 GPIO_ACTIVE_HIGH>; - }; - }; - - memory { -- reg = <0 0x40000000 0 0x20000000>; -+ reg = <0 0x40000000 0 0x40000000>; - }; - - reg_1p8v: regulator-1p8v { -@@ -101,23 +113,82 @@ - }; - - ð { -- pinctrl-names = "default"; -- pinctrl-0 = <ð_pins>; - status = "okay"; -+ gmac0: mac@0 { -+ compatible = "mediatek,eth-mac"; -+ reg = <0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; -- phy-handle = <&phy5>; -+ phy-mode = "rgmii"; -+ -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ pause; -+ }; - }; - -- mdio-bus { -+ mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - -- phy5: ethernet-phy@5 { -- reg = <5>; -- phy-mode = "sgmii"; -+ switch@0 { -+ compatible = "mediatek,mt7531"; -+ reg = <0>; -+ reset-gpios = <&pio 54 0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan4"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "wan"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ }; - }; - }; - }; -@@ -185,15 +256,28 @@ - - &pcie { - pinctrl-names = "default"; -- pinctrl-0 = <&pcie0_pins>; -+ pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; - status = "okay"; - - pcie@0,0 { - status = "okay"; - }; -+ -+ pcie@1,0 { -+ status = "okay"; -+ }; - }; - - &pio { -+ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and -+ * SATA functions. i.e. output-high: PCIe, output-low: SATA -+ */ -+ asm_sel { -+ gpio-hog; -+ gpios = <90 GPIO_ACTIVE_HIGH>; -+ output-high; -+ }; -+ - /* eMMC is shared pin with parallel NAND */ - emmc_pins_default: emmc-pins-default { - mux { -@@ -460,11 +544,11 @@ - }; - - &sata { -- status = "okay"; -+ status = "disable"; - }; - - &sata_phy { -- status = "okay"; -+ status = "disable"; - }; - - &spi0 { diff --git a/target/linux/mediatek/patches-5.4/0005-dts-mt7629-add-gsw.patch b/target/linux/mediatek/patches-5.4/0005-dts-mt7629-add-gsw.patch deleted file mode 100644 index 4028bad4df..0000000000 --- a/target/linux/mediatek/patches-5.4/0005-dts-mt7629-add-gsw.patch +++ /dev/null @@ -1,90 +0,0 @@ ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -18,6 +18,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8"; - }; - - gpio-keys { -@@ -36,6 +37,13 @@ - }; - }; - -+ gsw: gsw@0 { -+ compatible = "mediatek,mt753x"; -+ mediatek,ethsys = <ðsys>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ - memory@40000000 { - device_type = "memory"; - reg = <0x40000000 0x10000000>; -@@ -70,6 +78,10 @@ - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; -+ -+ nvmem-cells = <&macaddr_factory_2a>; -+ nvmem-cell-names = "mac-address"; -+ - fixed-link { - speed = <2500>; - full-duplex; -@@ -82,6 +94,9 @@ - reg = <1>; - phy-mode = "gmii"; - phy-handle = <&phy0>; -+ -+ nvmem-cells = <&macaddr_factory_24>; -+ nvmem-cell-names = "mac-address"; - }; - - mdio: mdio-bus { -@@ -94,6 +109,26 @@ - }; - }; - -+&gsw { -+ mediatek,mdio = <&mdio>; -+ mediatek,portmap = "llllw"; -+ mediatek,mdio_master_pinmux = <0>; -+ reset-gpios = <&pio 28 0>; -+ interrupt-parent = <&pio>; -+ interrupts = <6 IRQ_TYPE_LEVEL_HIGH>; -+ status = "okay"; -+ -+ port6: port@6 { -+ compatible = "mediatek,mt753x-port"; -+ reg = <6>; -+ phy-mode = "sgmii"; -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ }; -+ }; -+}; -+ - &i2c { - pinctrl-names = "default"; - pinctrl-0 = <&i2c_pins>; -@@ -272,3 +307,17 @@ - pinctrl-0 = <&watchdog_pins>; - status = "okay"; - }; -+ -+&factory { -+ compatible = "nvmem-cells"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ macaddr_factory_24: macaddr@24 { -+ reg = <0x24 0x6>; -+ }; -+ -+ macaddr_factory_2a: macaddr@2a { -+ reg = <0x2a 0x6>; -+ }; -+}; diff --git a/target/linux/mediatek/patches-5.4/0006-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-5.4/0006-dts-fix-bpi2-console.patch deleted file mode 100644 index b7251177f2..0000000000 --- a/target/linux/mediatek/patches-5.4/0006-dts-fix-bpi2-console.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -19,6 +19,7 @@ - - chosen { - stdout-path = "serial2:115200n8"; -+ bootargs = "console=ttyS2,115200n8"; - }; - - cpus { diff --git a/target/linux/mediatek/patches-5.4/0006-dts-fix-bpi64-console.patch b/target/linux/mediatek/patches-5.4/0006-dts-fix-bpi64-console.patch deleted file mode 100644 index 07a2eae245..0000000000 --- a/target/linux/mediatek/patches-5.4/0006-dts-fix-bpi64-console.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -22,7 +22,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { diff --git a/target/linux/mediatek/patches-5.4/0010-dts-mt7629-rfb-fix-firmware-partition.patch b/target/linux/mediatek/patches-5.4/0010-dts-mt7629-rfb-fix-firmware-partition.patch deleted file mode 100644 index 2c48e5706f..0000000000 --- a/target/linux/mediatek/patches-5.4/0010-dts-mt7629-rfb-fix-firmware-partition.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -168,8 +168,9 @@ - }; - - partition@b0000 { -- label = "kernel"; -+ label = "firmware"; - reg = <0xb0000 0xb50000>; -+ compatible = "denx,fit"; - }; - }; - }; diff --git a/target/linux/mediatek/patches-5.4/0226-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-5.4/0226-phy-phy-mtk-tphy-Add-hifsys-support.patch deleted file mode 100644 index f2647e8ffe..0000000000 --- a/target/linux/mediatek/patches-5.4/0226-phy-phy-mtk-tphy-Add-hifsys-support.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 28f9a5e2a3f5441ab5594669ed82da11e32277a9 Mon Sep 17 00:00:00 2001 -From: Kristian Evensen <kristian.evensen@gmail.com> -Date: Mon, 30 Apr 2018 14:38:01 +0200 -Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support - ---- - drivers/phy/mediatek/phy-mtk-tphy.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/drivers/phy/mediatek/phy-mtk-tphy.c -+++ b/drivers/phy/mediatek/phy-mtk-tphy.c -@@ -15,6 +15,8 @@ - #include <linux/of_device.h> - #include <linux/phy/phy.h> - #include <linux/platform_device.h> -+#include <linux/mfd/syscon.h> -+#include <linux/regmap.h> - - /* version V1 sub-banks offset base address */ - /* banks shared by multiple phys */ -@@ -263,6 +265,9 @@ - #define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0) - #define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x)) - -+#define HIF_SYSCFG1 0x14 -+#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20) -+ - enum mtk_phy_version { - MTK_PHY_V1 = 1, - MTK_PHY_V2, -@@ -310,6 +315,7 @@ struct mtk_tphy { - struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ - const struct mtk_phy_pdata *pdata; - struct mtk_phy_instance **phys; -+ struct regmap *hif; - int nphys; - int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ - int src_coef; /* coefficient for slew rate calibrate */ -@@ -629,6 +635,10 @@ static void pcie_phy_instance_init(struc - if (tphy->pdata->version != MTK_PHY_V1) - return; - -+ if (tphy->hif) -+ regmap_update_bits(tphy->hif, HIF_SYSCFG1, -+ HIF_SYSCFG1_PHY2_MASK, 0); -+ - tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0); - tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H); - tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2); -@@ -1114,6 +1124,16 @@ static int mtk_tphy_probe(struct platfor - &tphy->src_ref_clk); - device_property_read_u32(dev, "mediatek,src-coef", &tphy->src_coef); - -+ if (of_find_property(np, "mediatek,phy-switch", NULL)) { -+ tphy->hif = syscon_regmap_lookup_by_phandle(np, -+ "mediatek,phy-switch"); -+ if (IS_ERR(tphy->hif)) { -+ dev_err(&pdev->dev, -+ "missing \"mediatek,phy-switch\" phandle\n"); -+ return PTR_ERR(tphy->hif); -+ } -+ } -+ - port = 0; - for_each_child_of_node(np, child_np) { - struct mtk_phy_instance *instance; diff --git a/target/linux/mediatek/patches-5.4/0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch b/target/linux/mediatek/patches-5.4/0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch deleted file mode 100644 index d9ab339fa8..0000000000 --- a/target/linux/mediatek/patches-5.4/0301-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch +++ /dev/null @@ -1,139 +0,0 @@ -From a2479dc254ebe31c84fbcfda73f35e2321576494 Mon Sep 17 00:00:00 2001 -From: Xiangsheng Hou <xiangsheng.hou@mediatek.com> -Date: Tue, 19 Mar 2019 13:57:38 +0800 -Subject: [PATCH 1/6] mtd: mtk ecc: move mtk ecc header file to include/mtd - -Change-Id: I8dc1d30e21b40d68ef5efd9587012f82970156a5 -Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com> ---- - drivers/mtd/nand/raw/mtk_ecc.c | 3 +-- - drivers/mtd/nand/raw/mtk_nand.c | 2 +- - {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h | 0 - 3 files changed, 2 insertions(+), 3 deletions(-) - rename {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h (100%) - ---- a/drivers/mtd/nand/raw/mtk_ecc.c -+++ b/drivers/mtd/nand/raw/mtk_ecc.c -@@ -15,8 +15,7 @@ - #include <linux/of.h> - #include <linux/of_platform.h> - #include <linux/mutex.h> -- --#include "mtk_ecc.h" -+#include <linux/mtd/mtk_ecc.h> - - #define ECC_IDLE_MASK BIT(0) - #define ECC_IRQ_EN BIT(0) ---- a/drivers/mtd/nand/raw/mtk_nand.c -+++ b/drivers/mtd/nand/raw/mtk_nand.c -@@ -17,7 +17,7 @@ - #include <linux/iopoll.h> - #include <linux/of.h> - #include <linux/of_device.h> --#include "mtk_ecc.h" -+#include <linux/mtd/mtk_ecc.h> - - /* NAND controller register definition */ - #define NFI_CNFG (0x00) ---- /dev/null -+++ b/include/linux/mtd/mtk_ecc.h -@@ -0,0 +1,49 @@ -+/* -+ * MTK SDG1 ECC controller -+ * -+ * Copyright (c) 2016 Mediatek -+ * Authors: Xiaolei Li <xiaolei.li@mediatek.com> -+ * Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org> -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__ -+#define __DRIVERS_MTD_NAND_MTK_ECC_H__ -+ -+#include <linux/types.h> -+ -+enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1}; -+enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE}; -+ -+struct device_node; -+struct mtk_ecc; -+ -+struct mtk_ecc_stats { -+ u32 corrected; -+ u32 bitflips; -+ u32 failed; -+}; -+ -+struct mtk_ecc_config { -+ enum mtk_ecc_operation op; -+ enum mtk_ecc_mode mode; -+ dma_addr_t addr; -+ u32 strength; -+ u32 sectors; -+ u32 len; -+}; -+ -+int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32); -+void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int); -+int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation); -+int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *); -+void mtk_ecc_disable(struct mtk_ecc *); -+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p); -+unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc); -+ -+struct mtk_ecc *of_mtk_ecc_get(struct device_node *); -+void mtk_ecc_release(struct mtk_ecc *); -+ -+#endif ---- a/drivers/mtd/nand/raw/mtk_ecc.h -+++ /dev/null -@@ -1,47 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0 OR MIT */ --/* -- * MTK SDG1 ECC controller -- * -- * Copyright (c) 2016 Mediatek -- * Authors: Xiaolei Li <xiaolei.li@mediatek.com> -- * Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org> -- */ -- --#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__ --#define __DRIVERS_MTD_NAND_MTK_ECC_H__ -- --#include <linux/types.h> -- --enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1}; --enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE}; -- --struct device_node; --struct mtk_ecc; -- --struct mtk_ecc_stats { -- u32 corrected; -- u32 bitflips; -- u32 failed; --}; -- --struct mtk_ecc_config { -- enum mtk_ecc_operation op; -- enum mtk_ecc_mode mode; -- dma_addr_t addr; -- u32 strength; -- u32 sectors; -- u32 len; --}; -- --int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32); --void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int); --int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation); --int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *); --void mtk_ecc_disable(struct mtk_ecc *); --void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p); --unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc); -- --struct mtk_ecc *of_mtk_ecc_get(struct device_node *); --void mtk_ecc_release(struct mtk_ecc *); -- --#endif diff --git a/target/linux/mediatek/patches-5.4/0303-mtd-spinand-disable-on-die-ECC.patch b/target/linux/mediatek/patches-5.4/0303-mtd-spinand-disable-on-die-ECC.patch deleted file mode 100644 index 5c18ea0f74..0000000000 --- a/target/linux/mediatek/patches-5.4/0303-mtd-spinand-disable-on-die-ECC.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b341f120cfc9ca1dfd48364b7f36ac2c1fbdea43 Mon Sep 17 00:00:00 2001 -From: Xiangsheng Hou <xiangsheng.hou@mediatek.com> -Date: Wed, 3 Apr 2019 16:30:01 +0800 -Subject: [PATCH 3/6] mtd: spinand: disable on-die ECC - -Change-Id: I9745adaed5295202fabbe8ab8947885c57a5b847 -Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com> ---- - drivers/mtd/nand/spi/core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -491,7 +491,7 @@ static int spinand_mtd_read(struct mtd_i - int ret = 0; - - if (ops->mode != MTD_OPS_RAW && spinand->eccinfo.ooblayout) -- enable_ecc = true; -+ enable_ecc = false; - - mutex_lock(&spinand->lock); - -@@ -539,7 +539,7 @@ static int spinand_mtd_write(struct mtd_ - int ret = 0; - - if (ops->mode != MTD_OPS_RAW && mtd->ooblayout) -- enable_ecc = true; -+ enable_ecc = false; - - mutex_lock(&spinand->lock); - diff --git a/target/linux/mediatek/patches-5.4/0306-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch b/target/linux/mediatek/patches-5.4/0306-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch deleted file mode 100644 index b3672e5b15..0000000000 --- a/target/linux/mediatek/patches-5.4/0306-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch +++ /dev/null @@ -1,1246 +0,0 @@ -From 1ecb38eabd90efe93957d0a822a167560c39308a Mon Sep 17 00:00:00 2001 -From: Xiangsheng Hou <xiangsheng.hou@mediatek.com> -Date: Wed, 20 Mar 2019 16:19:51 +0800 -Subject: [PATCH 6/6] spi: spi-mem: MediaTek: Add SPI NAND Flash interface - driver for MediaTek MT7622 - -Change-Id: I3e78406bb9b46b0049d3988a5c71c7069e4f809c -Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com> ---- - drivers/spi/Kconfig | 9 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-mtk-snfi.c | 1183 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 1193 insertions(+) - create mode 100644 drivers/spi/spi-mtk-snfi.c - ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -60,6 +60,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mp - obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o - obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o - obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o -+obj-$(CONFIG_SPI_MTK_SNFI) += spi-mtk-snfi.o - obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o - obj-$(CONFIG_SPI_MTK_NOR) += spi-mtk-nor.o - obj-$(CONFIG_SPI_MXIC) += spi-mxic.o ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -427,6 +427,15 @@ config SPI_MT65XX - say Y or M here.If you are not sure, say N. - SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. - -+config SPI_MTK_SNFI -+ tristate "MediaTek SPI NAND interface" -+ select MTD_SPI_NAND -+ help -+ This selects the SPI NAND FLASH interface(SNFI), -+ which could be found on MediaTek Soc. -+ Say Y or M here.If you are not sure, say N. -+ Note Parallel Nand and SPI NAND is alternative on MediaTek SoCs. -+ - config SPI_MT7621 - tristate "MediaTek MT7621 SPI Controller" - depends on RALINK || COMPILE_TEST ---- /dev/null -+++ b/drivers/spi/spi-mtk-snfi.c -@@ -0,0 +1,1200 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Driver for MediaTek SPI Nand interface -+ * -+ * Copyright (C) 2018 MediaTek Inc. -+ * Authors: Xiangsheng Hou <xiangsheng.hou@mediatek.com> -+ * -+ */ -+ -+#include <linux/clk.h> -+#include <linux/delay.h> -+#include <linux/dma-mapping.h> -+#include <linux/interrupt.h> -+#include <linux/iopoll.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/mtk_ecc.h> -+#include <linux/mtd/spinand.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_device.h> -+#include <linux/platform_device.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/spi-mem.h> -+ -+/* NAND controller register definition */ -+/* NFI control */ -+#define NFI_CNFG 0x00 -+#define CNFG_DMA BIT(0) -+#define CNFG_READ_EN BIT(1) -+#define CNFG_DMA_BURST_EN BIT(2) -+#define CNFG_BYTE_RW BIT(6) -+#define CNFG_HW_ECC_EN BIT(8) -+#define CNFG_AUTO_FMT_EN BIT(9) -+#define CNFG_OP_PROGRAM (3UL << 12) -+#define CNFG_OP_CUST (6UL << 12) -+#define NFI_PAGEFMT 0x04 -+#define PAGEFMT_512 0 -+#define PAGEFMT_2K 1 -+#define PAGEFMT_4K 2 -+#define PAGEFMT_FDM_SHIFT 8 -+#define PAGEFMT_FDM_ECC_SHIFT 12 -+#define NFI_CON 0x08 -+#define CON_FIFO_FLUSH BIT(0) -+#define CON_NFI_RST BIT(1) -+#define CON_BRD BIT(8) -+#define CON_BWR BIT(9) -+#define CON_SEC_SHIFT 12 -+#define NFI_INTR_EN 0x10 -+#define INTR_AHB_DONE_EN BIT(6) -+#define NFI_INTR_STA 0x14 -+#define NFI_CMD 0x20 -+#define NFI_STA 0x60 -+#define STA_EMP_PAGE BIT(12) -+#define NAND_FSM_MASK (0x1f << 24) -+#define NFI_FSM_MASK (0xf << 16) -+#define NFI_ADDRCNTR 0x70 -+#define CNTR_MASK GENMASK(16, 12) -+#define ADDRCNTR_SEC_SHIFT 12 -+#define ADDRCNTR_SEC(val) \ -+ (((val) & CNTR_MASK) >> ADDRCNTR_SEC_SHIFT) -+#define NFI_STRADDR 0x80 -+#define NFI_BYTELEN 0x84 -+#define NFI_CSEL 0x90 -+#define NFI_FDML(x) (0xa0 + (x) * sizeof(u32) * 2) -+#define NFI_FDMM(x) (0xa4 + (x) * sizeof(u32) * 2) -+#define NFI_MASTER_STA 0x224 -+#define MASTER_STA_MASK 0x0fff -+/* NFI_SPI control */ -+#define SNFI_MAC_OUTL 0x504 -+#define SNFI_MAC_INL 0x508 -+#define SNFI_RD_CTL2 0x510 -+#define RD_CMD_MASK 0x00ff -+#define RD_DUMMY_SHIFT 8 -+#define SNFI_RD_CTL3 0x514 -+#define RD_ADDR_MASK 0xffff -+#define SNFI_MISC_CTL 0x538 -+#define RD_MODE_X2 BIT(16) -+#define RD_MODE_X4 (2UL << 16) -+#define RD_QDUAL_IO (4UL << 16) -+#define RD_MODE_MASK (7UL << 16) -+#define RD_CUSTOM_EN BIT(6) -+#define WR_CUSTOM_EN BIT(7) -+#define WR_X4_EN BIT(20) -+#define SW_RST BIT(28) -+#define SNFI_MISC_CTL2 0x53c -+#define WR_LEN_SHIFT 16 -+#define SNFI_PG_CTL1 0x524 -+#define WR_LOAD_CMD_SHIFT 8 -+#define SNFI_PG_CTL2 0x528 -+#define WR_LOAD_ADDR_MASK 0xffff -+#define SNFI_MAC_CTL 0x500 -+#define MAC_WIP BIT(0) -+#define MAC_WIP_READY BIT(1) -+#define MAC_TRIG BIT(2) -+#define MAC_EN BIT(3) -+#define MAC_SIO_SEL BIT(4) -+#define SNFI_STA_CTL1 0x550 -+#define SPI_STATE_IDLE 0xf -+#define SNFI_CNFG 0x55c -+#define SNFI_MODE_EN BIT(0) -+#define SNFI_GPRAM_DATA 0x800 -+#define SNFI_GPRAM_MAX_LEN 16 -+ -+/* Dummy command trigger NFI to spi mode */ -+#define NAND_CMD_DUMMYREAD 0x00 -+#define NAND_CMD_DUMMYPROG 0x80 -+ -+#define MTK_TIMEOUT 500000 -+#define MTK_RESET_TIMEOUT 1000000 -+#define MTK_SNFC_MIN_SPARE 16 -+#define KB(x) ((x) * 1024UL) -+ -+/* -+ * supported spare size of each IP. -+ * order should be the same with the spare size bitfiled defination of -+ * register NFI_PAGEFMT. -+ */ -+static const u8 spare_size_mt7622[] = { -+ 16, 26, 27, 28 -+}; -+ -+struct mtk_snfi_caps { -+ const u8 *spare_size; -+ u8 num_spare_size; -+ u32 nand_sec_size; -+ u8 nand_fdm_size; -+ u8 nand_fdm_ecc_size; -+ u8 ecc_parity_bits; -+ u8 pageformat_spare_shift; -+ u8 bad_mark_swap; -+}; -+ -+struct mtk_snfi_bad_mark_ctl { -+ void (*bm_swap)(struct spi_mem *mem, u8 *buf, int raw); -+ u32 sec; -+ u32 pos; -+}; -+ -+struct mtk_snfi_nand_chip { -+ struct mtk_snfi_bad_mark_ctl bad_mark; -+ u32 spare_per_sector; -+}; -+ -+struct mtk_snfi_clk { -+ struct clk *nfi_clk; -+ struct clk *spi_clk; -+}; -+ -+struct mtk_snfi { -+ const struct mtk_snfi_caps *caps; -+ struct mtk_snfi_nand_chip snfi_nand; -+ struct mtk_snfi_clk clk; -+ struct mtk_ecc_config ecc_cfg; -+ struct mtk_ecc *ecc; -+ struct completion done; -+ struct device *dev; -+ -+ void __iomem *regs; -+ -+ u8 *buffer; -+}; -+ -+static inline u8 *oob_ptr(struct spi_mem *mem, int i) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u8 *poi; -+ -+ /* map the sector's FDM data to free oob: -+ * the beginning of the oob area stores the FDM data of bad mark -+ */ -+ -+ if (i < snfi_nand->bad_mark.sec) -+ poi = spinand->oobbuf + (i + 1) * snfi->caps->nand_fdm_size; -+ else if (i == snfi_nand->bad_mark.sec) -+ poi = spinand->oobbuf; -+ else -+ poi = spinand->oobbuf + i * snfi->caps->nand_fdm_size; -+ -+ return poi; -+} -+ -+static inline int mtk_data_len(struct spi_mem *mem) -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ -+ return snfi->caps->nand_sec_size + snfi_nand->spare_per_sector; -+} -+ -+static inline u8 *mtk_oob_ptr(struct spi_mem *mem, -+ const u8 *p, int i) -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ -+ return (u8 *)p + i * mtk_data_len(mem) + snfi->caps->nand_sec_size; -+} -+ -+static void mtk_snfi_bad_mark_swap(struct spi_mem *mem, -+ u8 *buf, int raw) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u32 bad_pos = snfi_nand->bad_mark.pos; -+ -+ if (raw) -+ bad_pos += snfi_nand->bad_mark.sec * mtk_data_len(mem); -+ else -+ bad_pos += snfi_nand->bad_mark.sec * snfi->caps->nand_sec_size; -+ -+ swap(spinand->oobbuf[0], buf[bad_pos]); -+} -+ -+static void mtk_snfi_set_bad_mark_ctl(struct mtk_snfi_bad_mark_ctl *bm_ctl, -+ struct spi_mem *mem) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ -+ bm_ctl->bm_swap = mtk_snfi_bad_mark_swap; -+ bm_ctl->sec = mtd->writesize / mtk_data_len(mem); -+ bm_ctl->pos = mtd->writesize % mtk_data_len(mem); -+} -+ -+static void mtk_snfi_mac_enable(struct mtk_snfi *snfi) -+{ -+ u32 mac; -+ -+ mac = readl(snfi->regs + SNFI_MAC_CTL); -+ mac &= ~MAC_SIO_SEL; -+ mac |= MAC_EN; -+ -+ writel(mac, snfi->regs + SNFI_MAC_CTL); -+} -+ -+static int mtk_snfi_mac_trigger(struct mtk_snfi *snfi) -+{ -+ u32 mac, reg; -+ int ret = 0; -+ -+ mac = readl(snfi->regs + SNFI_MAC_CTL); -+ mac |= MAC_TRIG; -+ writel(mac, snfi->regs + SNFI_MAC_CTL); -+ -+ ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, reg, -+ reg & MAC_WIP_READY, 10, -+ MTK_TIMEOUT); -+ if (ret < 0) { -+ dev_err(snfi->dev, "polling wip ready for read timeout\n"); -+ return -EIO; -+ } -+ -+ ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, reg, -+ !(reg & MAC_WIP), 10, -+ MTK_TIMEOUT); -+ if (ret < 0) { -+ dev_err(snfi->dev, "polling flash update timeout\n"); -+ return -EIO; -+ } -+ -+ return ret; -+} -+ -+static void mtk_snfi_mac_leave(struct mtk_snfi *snfi) -+{ -+ u32 mac; -+ -+ mac = readl(snfi->regs + SNFI_MAC_CTL); -+ mac &= ~(MAC_TRIG | MAC_EN | MAC_SIO_SEL); -+ writel(mac, snfi->regs + SNFI_MAC_CTL); -+} -+ -+static int mtk_snfi_mac_op(struct mtk_snfi *snfi) -+{ -+ int ret = 0; -+ -+ mtk_snfi_mac_enable(snfi); -+ -+ ret = mtk_snfi_mac_trigger(snfi); -+ if (ret) -+ return ret; -+ -+ mtk_snfi_mac_leave(snfi); -+ -+ return ret; -+} -+ -+static irqreturn_t mtk_snfi_irq(int irq, void *id) -+{ -+ struct mtk_snfi *snfi = id; -+ u16 sta, ien; -+ -+ sta = readw(snfi->regs + NFI_INTR_STA); -+ ien = readw(snfi->regs + NFI_INTR_EN); -+ -+ if (!(sta & ien)) -+ return IRQ_NONE; -+ -+ writew(~sta & ien, snfi->regs + NFI_INTR_EN); -+ complete(&snfi->done); -+ -+ return IRQ_HANDLED; -+} -+ -+static int mtk_snfi_enable_clk(struct device *dev, struct mtk_snfi_clk *clk) -+{ -+ int ret; -+ -+ ret = clk_prepare_enable(clk->nfi_clk); -+ if (ret) { -+ dev_err(dev, "failed to enable nfi clk\n"); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clk->spi_clk); -+ if (ret) { -+ dev_err(dev, "failed to enable spi clk\n"); -+ clk_disable_unprepare(clk->nfi_clk); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void mtk_snfi_disable_clk(struct mtk_snfi_clk *clk) -+{ -+ clk_disable_unprepare(clk->nfi_clk); -+ clk_disable_unprepare(clk->spi_clk); -+} -+ -+static int mtk_snfi_reset(struct mtk_snfi *snfi) -+{ -+ u32 val; -+ int ret; -+ -+ /* SW reset controller */ -+ val = readl(snfi->regs + SNFI_MISC_CTL) | SW_RST; -+ writel(val, snfi->regs + SNFI_MISC_CTL); -+ -+ ret = readw_poll_timeout(snfi->regs + SNFI_STA_CTL1, val, -+ !(val & SPI_STATE_IDLE), 50, -+ MTK_RESET_TIMEOUT); -+ if (ret) { -+ dev_warn(snfi->dev, "spi state active in reset [0x%x] = 0x%x\n", -+ SNFI_STA_CTL1, val); -+ return ret; -+ } -+ -+ val = readl(snfi->regs + SNFI_MISC_CTL); -+ val &= ~SW_RST; -+ writel(val, snfi->regs + SNFI_MISC_CTL); -+ -+ /* reset all registers and force the NFI master to terminate */ -+ writew(CON_FIFO_FLUSH | CON_NFI_RST, snfi->regs + NFI_CON); -+ ret = readw_poll_timeout(snfi->regs + NFI_STA, val, -+ !(val & (NFI_FSM_MASK | NAND_FSM_MASK)), 50, -+ MTK_RESET_TIMEOUT); -+ if (ret) { -+ dev_warn(snfi->dev, "nfi active in reset [0x%x] = 0x%x\n", -+ NFI_STA, val); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int mtk_snfi_set_spare_per_sector(struct spinand_device *spinand, -+ const struct mtk_snfi_caps *caps, -+ u32 *sps) -+{ -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ const u8 *spare = caps->spare_size; -+ u32 sectors, i, closest_spare = 0; -+ -+ sectors = mtd->writesize / caps->nand_sec_size; -+ *sps = mtd->oobsize / sectors; -+ -+ if (*sps < MTK_SNFC_MIN_SPARE) -+ return -EINVAL; -+ -+ for (i = 0; i < caps->num_spare_size; i++) { -+ if (*sps >= spare[i] && spare[i] >= spare[closest_spare]) { -+ closest_spare = i; -+ if (*sps == spare[i]) -+ break; -+ } -+ } -+ -+ *sps = spare[closest_spare]; -+ -+ return 0; -+} -+ -+static void mtk_snfi_read_fdm_data(struct spi_mem *mem, -+ u32 sectors) -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ const struct mtk_snfi_caps *caps = snfi->caps; -+ u32 vall, valm; -+ int i, j; -+ u8 *oobptr; -+ -+ for (i = 0; i < sectors; i++) { -+ oobptr = oob_ptr(mem, i); -+ vall = readl(snfi->regs + NFI_FDML(i)); -+ valm = readl(snfi->regs + NFI_FDMM(i)); -+ -+ for (j = 0; j < caps->nand_fdm_size; j++) -+ oobptr[j] = (j >= 4 ? valm : vall) >> ((j % 4) * 8); -+ } -+} -+ -+static void mtk_snfi_write_fdm_data(struct spi_mem *mem, -+ u32 sectors) -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ const struct mtk_snfi_caps *caps = snfi->caps; -+ u32 vall, valm; -+ int i, j; -+ u8 *oobptr; -+ -+ for (i = 0; i < sectors; i++) { -+ oobptr = oob_ptr(mem, i); -+ vall = 0; -+ valm = 0; -+ for (j = 0; j < 8; j++) { -+ if (j < 4) -+ vall |= (j < caps->nand_fdm_size ? oobptr[j] : -+ 0xff) << (j * 8); -+ else -+ valm |= (j < caps->nand_fdm_size ? oobptr[j] : -+ 0xff) << ((j - 4) * 8); -+ } -+ writel(vall, snfi->regs + NFI_FDML(i)); -+ writel(valm, snfi->regs + NFI_FDMM(i)); -+ } -+} -+ -+static int mtk_snfi_update_ecc_stats(struct spi_mem *mem, -+ u8 *buf, u32 sectors) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct mtk_ecc_stats stats; -+ int rc, i; -+ -+ rc = readl(snfi->regs + NFI_STA) & STA_EMP_PAGE; -+ if (rc) { -+ memset(buf, 0xff, sectors * snfi->caps->nand_sec_size); -+ for (i = 0; i < sectors; i++) -+ memset(spinand->oobbuf, 0xff, -+ snfi->caps->nand_fdm_size); -+ return 0; -+ } -+ -+ mtk_ecc_get_stats(snfi->ecc, &stats, sectors); -+ mtd->ecc_stats.corrected += stats.corrected; -+ mtd->ecc_stats.failed += stats.failed; -+ -+ return 0; -+} -+ -+static int mtk_snfi_hw_runtime_config(struct spi_mem *mem) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ const struct mtk_snfi_caps *caps = snfi->caps; -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u32 fmt, spare, i = 0; -+ int ret; -+ -+ ret = mtk_snfi_set_spare_per_sector(spinand, caps, &spare); -+ if (ret) -+ return ret; -+ -+ /* calculate usable oob bytes for ecc parity data */ -+ snfi_nand->spare_per_sector = spare; -+ spare -= caps->nand_fdm_size; -+ -+ nand->memorg.oobsize = snfi_nand->spare_per_sector -+ * (mtd->writesize / caps->nand_sec_size); -+ mtd->oobsize = nanddev_per_page_oobsize(nand); -+ -+ snfi->ecc_cfg.strength = (spare << 3) / caps->ecc_parity_bits; -+ mtk_ecc_adjust_strength(snfi->ecc, &snfi->ecc_cfg.strength); -+ -+ switch (mtd->writesize) { -+ case 512: -+ fmt = PAGEFMT_512; -+ break; -+ case KB(2): -+ fmt = PAGEFMT_2K; -+ break; -+ case KB(4): -+ fmt = PAGEFMT_4K; -+ break; -+ default: -+ dev_err(snfi->dev, "invalid page len: %d\n", mtd->writesize); -+ return -EINVAL; -+ } -+ -+ /* Setup PageFormat */ -+ while (caps->spare_size[i] != snfi_nand->spare_per_sector) { -+ i++; -+ if (i == (caps->num_spare_size - 1)) { -+ dev_err(snfi->dev, "invalid spare size %d\n", -+ snfi_nand->spare_per_sector); -+ return -EINVAL; -+ } -+ } -+ -+ fmt |= i << caps->pageformat_spare_shift; -+ fmt |= caps->nand_fdm_size << PAGEFMT_FDM_SHIFT; -+ fmt |= caps->nand_fdm_ecc_size << PAGEFMT_FDM_ECC_SHIFT; -+ writel(fmt, snfi->regs + NFI_PAGEFMT); -+ -+ snfi->ecc_cfg.len = caps->nand_sec_size + caps->nand_fdm_ecc_size; -+ -+ mtk_snfi_set_bad_mark_ctl(&snfi_nand->bad_mark, mem); -+ -+ return 0; -+} -+ -+static int mtk_snfi_read_from_cache(struct spi_mem *mem, -+ const struct spi_mem_op *op, int oob_on) -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ u32 sectors = mtd->writesize / snfi->caps->nand_sec_size; -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u32 reg, len, col_addr = 0; -+ int dummy_cycle, ret; -+ dma_addr_t dma_addr; -+ -+ len = sectors * (snfi->caps->nand_sec_size -+ + snfi_nand->spare_per_sector); -+ -+ dma_addr = dma_map_single(snfi->dev, snfi->buffer, -+ len, DMA_FROM_DEVICE); -+ ret = dma_mapping_error(snfi->dev, dma_addr); -+ if (ret) { -+ dev_err(snfi->dev, "dma mapping error\n"); -+ return -EINVAL; -+ } -+ -+ /* set Read cache command and dummy cycle */ -+ dummy_cycle = (op->dummy.nbytes << 3) >> (ffs(op->dummy.buswidth) - 1); -+ reg = ((op->cmd.opcode & RD_CMD_MASK) | -+ (dummy_cycle << RD_DUMMY_SHIFT)); -+ writel(reg, snfi->regs + SNFI_RD_CTL2); -+ -+ writel((col_addr & RD_ADDR_MASK), snfi->regs + SNFI_RD_CTL3); -+ -+ reg = readl(snfi->regs + SNFI_MISC_CTL); -+ reg |= RD_CUSTOM_EN; -+ reg &= ~(RD_MODE_MASK | WR_X4_EN); -+ -+ /* set data and addr buswidth */ -+ if (op->data.buswidth == 4) -+ reg |= RD_MODE_X4; -+ else if (op->data.buswidth == 2) -+ reg |= RD_MODE_X2; -+ -+ if (op->addr.buswidth == 4 || op->addr.buswidth == 2) -+ reg |= RD_QDUAL_IO; -+ writel(reg, snfi->regs + SNFI_MISC_CTL); -+ -+ writel(len, snfi->regs + SNFI_MISC_CTL2); -+ writew(sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON); -+ reg = readw(snfi->regs + NFI_CNFG); -+ reg |= CNFG_READ_EN | CNFG_DMA_BURST_EN | CNFG_DMA | CNFG_OP_CUST; -+ -+ if (!oob_on) { -+ reg |= CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN; -+ writew(reg, snfi->regs + NFI_CNFG); -+ -+ snfi->ecc_cfg.mode = ECC_NFI_MODE; -+ snfi->ecc_cfg.sectors = sectors; -+ snfi->ecc_cfg.op = ECC_DECODE; -+ ret = mtk_ecc_enable(snfi->ecc, &snfi->ecc_cfg); -+ if (ret) { -+ dev_err(snfi->dev, "ecc enable failed\n"); -+ /* clear NFI_CNFG */ -+ reg &= ~(CNFG_READ_EN | CNFG_DMA_BURST_EN | CNFG_DMA | -+ CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN); -+ writew(reg, snfi->regs + NFI_CNFG); -+ goto out; -+ } -+ } else { -+ writew(reg, snfi->regs + NFI_CNFG); -+ } -+ -+ writel(lower_32_bits(dma_addr), snfi->regs + NFI_STRADDR); -+ readw(snfi->regs + NFI_INTR_STA); -+ writew(INTR_AHB_DONE_EN, snfi->regs + NFI_INTR_EN); -+ -+ init_completion(&snfi->done); -+ -+ /* set dummy command to trigger NFI enter SPI mode */ -+ writew(NAND_CMD_DUMMYREAD, snfi->regs + NFI_CMD); -+ reg = readl(snfi->regs + NFI_CON) | CON_BRD; -+ writew(reg, snfi->regs + NFI_CON); -+ -+ ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500)); -+ if (!ret) { -+ dev_err(snfi->dev, "read ahb done timeout\n"); -+ writew(0, snfi->regs + NFI_INTR_EN); -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ ret = readl_poll_timeout_atomic(snfi->regs + NFI_BYTELEN, reg, -+ ADDRCNTR_SEC(reg) >= sectors, 10, -+ MTK_TIMEOUT); -+ if (ret < 0) { -+ dev_err(snfi->dev, "polling read byte len timeout\n"); -+ ret = -EIO; -+ } else { -+ if (!oob_on) { -+ ret = mtk_ecc_wait_done(snfi->ecc, ECC_DECODE); -+ if (ret) { -+ dev_warn(snfi->dev, "wait ecc done timeout\n"); -+ } else { -+ mtk_snfi_update_ecc_stats(mem, snfi->buffer, -+ sectors); -+ mtk_snfi_read_fdm_data(mem, sectors); -+ } -+ } -+ } -+ -+ if (oob_on) -+ goto out; -+ -+ mtk_ecc_disable(snfi->ecc); -+out: -+ dma_unmap_single(snfi->dev, dma_addr, len, DMA_FROM_DEVICE); -+ writel(0, snfi->regs + NFI_CON); -+ writel(0, snfi->regs + NFI_CNFG); -+ reg = readl(snfi->regs + SNFI_MISC_CTL); -+ reg &= ~RD_CUSTOM_EN; -+ writel(reg, snfi->regs + SNFI_MISC_CTL); -+ -+ return ret; -+} -+ -+static int mtk_snfi_write_to_cache(struct spi_mem *mem, -+ const struct spi_mem_op *op, -+ int oob_on) -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ u32 sectors = mtd->writesize / snfi->caps->nand_sec_size; -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u32 reg, len, col_addr = 0; -+ dma_addr_t dma_addr; -+ int ret; -+ -+ len = sectors * (snfi->caps->nand_sec_size -+ + snfi_nand->spare_per_sector); -+ -+ dma_addr = dma_map_single(snfi->dev, snfi->buffer, len, -+ DMA_TO_DEVICE); -+ ret = dma_mapping_error(snfi->dev, dma_addr); -+ if (ret) { -+ dev_err(snfi->dev, "dma mapping error\n"); -+ return -EINVAL; -+ } -+ -+ /* set program load cmd and address */ -+ reg = (op->cmd.opcode << WR_LOAD_CMD_SHIFT); -+ writel(reg, snfi->regs + SNFI_PG_CTL1); -+ writel(col_addr & WR_LOAD_ADDR_MASK, snfi->regs + SNFI_PG_CTL2); -+ -+ reg = readl(snfi->regs + SNFI_MISC_CTL); -+ reg |= WR_CUSTOM_EN; -+ reg &= ~(RD_MODE_MASK | WR_X4_EN); -+ -+ if (op->data.buswidth == 4) -+ reg |= WR_X4_EN; -+ writel(reg, snfi->regs + SNFI_MISC_CTL); -+ -+ writel(len << WR_LEN_SHIFT, snfi->regs + SNFI_MISC_CTL2); -+ writew(sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON); -+ -+ reg = readw(snfi->regs + NFI_CNFG); -+ reg &= ~(CNFG_READ_EN | CNFG_BYTE_RW); -+ reg |= CNFG_DMA | CNFG_DMA_BURST_EN | CNFG_OP_PROGRAM; -+ -+ if (!oob_on) { -+ reg |= CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN; -+ writew(reg, snfi->regs + NFI_CNFG); -+ -+ snfi->ecc_cfg.mode = ECC_NFI_MODE; -+ snfi->ecc_cfg.op = ECC_ENCODE; -+ ret = mtk_ecc_enable(snfi->ecc, &snfi->ecc_cfg); -+ if (ret) { -+ dev_err(snfi->dev, "ecc enable failed\n"); -+ /* clear NFI_CNFG */ -+ reg &= ~(CNFG_DMA_BURST_EN | CNFG_DMA | -+ CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN); -+ writew(reg, snfi->regs + NFI_CNFG); -+ dma_unmap_single(snfi->dev, dma_addr, len, -+ DMA_FROM_DEVICE); -+ goto out; -+ } -+ /* write OOB into the FDM registers (OOB area in MTK NAND) */ -+ mtk_snfi_write_fdm_data(mem, sectors); -+ } else { -+ writew(reg, snfi->regs + NFI_CNFG); -+ } -+ writel(lower_32_bits(dma_addr), snfi->regs + NFI_STRADDR); -+ readw(snfi->regs + NFI_INTR_STA); -+ writew(INTR_AHB_DONE_EN, snfi->regs + NFI_INTR_EN); -+ -+ init_completion(&snfi->done); -+ -+ /* set dummy command to trigger NFI enter SPI mode */ -+ writew(NAND_CMD_DUMMYPROG, snfi->regs + NFI_CMD); -+ reg = readl(snfi->regs + NFI_CON) | CON_BWR; -+ writew(reg, snfi->regs + NFI_CON); -+ -+ ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500)); -+ if (!ret) { -+ dev_err(snfi->dev, "custom program done timeout\n"); -+ writew(0, snfi->regs + NFI_INTR_EN); -+ ret = -ETIMEDOUT; -+ goto ecc_disable; -+ } -+ -+ ret = readl_poll_timeout_atomic(snfi->regs + NFI_ADDRCNTR, reg, -+ ADDRCNTR_SEC(reg) >= sectors, -+ 10, MTK_TIMEOUT); -+ if (ret) -+ dev_err(snfi->dev, "hwecc write timeout\n"); -+ -+ecc_disable: -+ mtk_ecc_disable(snfi->ecc); -+ -+out: -+ dma_unmap_single(snfi->dev, dma_addr, len, DMA_TO_DEVICE); -+ writel(0, snfi->regs + NFI_CON); -+ writel(0, snfi->regs + NFI_CNFG); -+ reg = readl(snfi->regs + SNFI_MISC_CTL); -+ reg &= ~WR_CUSTOM_EN; -+ writel(reg, snfi->regs + SNFI_MISC_CTL); -+ -+ return ret; -+} -+ -+static int mtk_snfi_read(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u32 col_addr = op->addr.val; -+ int i, ret, sectors, oob_on = false; -+ -+ if (col_addr == mtd->writesize) -+ oob_on = true; -+ -+ ret = mtk_snfi_read_from_cache(mem, op, oob_on); -+ if (ret) { -+ dev_warn(snfi->dev, "read from cache fail\n"); -+ return ret; -+ } -+ -+ sectors = mtd->writesize / snfi->caps->nand_sec_size; -+ for (i = 0; i < sectors; i++) { -+ if (oob_on) -+ memcpy(oob_ptr(mem, i), -+ mtk_oob_ptr(mem, snfi->buffer, i), -+ snfi->caps->nand_fdm_size); -+ -+ if (i == snfi_nand->bad_mark.sec && snfi->caps->bad_mark_swap) -+ snfi_nand->bad_mark.bm_swap(mem, snfi->buffer, -+ oob_on); -+ } -+ -+ if (!oob_on) -+ memcpy(spinand->databuf, snfi->buffer, mtd->writesize); -+ -+ return ret; -+} -+ -+static int mtk_snfi_write(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand; -+ u32 ret, i, sectors, col_addr = op->addr.val; -+ int oob_on = false; -+ -+ if (col_addr == mtd->writesize) -+ oob_on = true; -+ -+ sectors = mtd->writesize / snfi->caps->nand_sec_size; -+ memset(snfi->buffer, 0xff, mtd->writesize + mtd->oobsize); -+ -+ if (!oob_on) -+ memcpy(snfi->buffer, spinand->databuf, mtd->writesize); -+ -+ for (i = 0; i < sectors; i++) { -+ if (i == snfi_nand->bad_mark.sec && snfi->caps->bad_mark_swap) -+ snfi_nand->bad_mark.bm_swap(mem, snfi->buffer, oob_on); -+ -+ if (oob_on) -+ memcpy(mtk_oob_ptr(mem, snfi->buffer, i), -+ oob_ptr(mem, i), -+ snfi->caps->nand_fdm_size); -+ } -+ -+ ret = mtk_snfi_write_to_cache(mem, op, oob_on); -+ if (ret) -+ dev_warn(snfi->dev, "write to cache fail\n"); -+ -+ return ret; -+} -+ -+static int mtk_snfi_command_exec(struct mtk_snfi *snfi, -+ const u8 *txbuf, u8 *rxbuf, -+ const u32 txlen, const u32 rxlen) -+{ -+ u32 tmp, i, j, reg, m; -+ u8 *p_tmp = (u8 *)(&tmp); -+ int ret = 0; -+ -+ /* Moving tx data to NFI_SPI GPRAM */ -+ for (i = 0, m = 0; i < txlen; ) { -+ for (j = 0, tmp = 0; i < txlen && j < 4; i++, j++) -+ p_tmp[j] = txbuf[i]; -+ -+ writel(tmp, snfi->regs + SNFI_GPRAM_DATA + m); -+ m += 4; -+ } -+ -+ writel(txlen, snfi->regs + SNFI_MAC_OUTL); -+ writel(rxlen, snfi->regs + SNFI_MAC_INL); -+ ret = mtk_snfi_mac_op(snfi); -+ if (ret) -+ return ret; -+ -+ /* For NULL input data, this loop will be skipped */ -+ if (rxlen) -+ for (i = 0, m = 0; i < rxlen; ) { -+ reg = readl(snfi->regs + -+ SNFI_GPRAM_DATA + m); -+ for (j = 0; i < rxlen && j < 4; i++, j++, rxbuf++) { -+ if (m == 0 && i == 0) -+ j = i + txlen; -+ *rxbuf = (reg >> (j * 8)) & 0xFF; -+ } -+ m += 4; -+ } -+ -+ return ret; -+} -+ -+/* -+ * mtk_snfi_exec_op - to process command/data to send to the -+ * SPI NAND by mtk controller -+ */ -+static int mtk_snfi_exec_op(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+ -+{ -+ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master); -+ struct spinand_device *spinand = spi_mem_get_drvdata(mem); -+ struct mtd_info *mtd = spinand_to_mtd(spinand); -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ const struct spi_mem_op *read_cache; -+ const struct spi_mem_op *write_cache; -+ const struct spi_mem_op *update_cache; -+ u32 tmpbufsize, txlen = 0, rxlen = 0; -+ u8 *txbuf, *rxbuf = NULL, *buf; -+ int i, ret = 0; -+ -+ ret = mtk_snfi_reset(snfi); -+ if (ret) { -+ dev_warn(snfi->dev, "reset spi memory controller fail\n"); -+ return ret; -+ } -+ -+ /*if bbt initial, framework have detect nand information */ -+ if (nand->bbt.cache) { -+ read_cache = spinand->op_templates.read_cache; -+ write_cache = spinand->op_templates.write_cache; -+ update_cache = spinand->op_templates.update_cache; -+ -+ ret = mtk_snfi_hw_runtime_config(mem); -+ if (ret) -+ return ret; -+ -+ /* For Read/Write with cache, Erase use framework flow */ -+ if (op->cmd.opcode == read_cache->cmd.opcode) { -+ ret = mtk_snfi_read(mem, op); -+ if (ret) -+ dev_warn(snfi->dev, "snfi read fail\n"); -+ -+ return ret; -+ } else if ((op->cmd.opcode == write_cache->cmd.opcode) -+ || (op->cmd.opcode == update_cache->cmd.opcode)) { -+ ret = mtk_snfi_write(mem, op); -+ if (ret) -+ dev_warn(snfi->dev, "snfi write fail\n"); -+ -+ return ret; -+ } -+ } -+ -+ tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes + -+ op->dummy.nbytes + op->data.nbytes; -+ -+ txbuf = kzalloc(tmpbufsize, GFP_KERNEL); -+ if (!txbuf) -+ return -ENOMEM; -+ -+ txbuf[txlen++] = op->cmd.opcode; -+ -+ if (op->addr.nbytes) -+ for (i = 0; i < op->addr.nbytes; i++) -+ txbuf[txlen++] = op->addr.val >> -+ (8 * (op->addr.nbytes - i - 1)); -+ -+ txlen += op->dummy.nbytes; -+ -+ if (op->data.dir == SPI_MEM_DATA_OUT) -+ for (i = 0; i < op->data.nbytes; i++) { -+ buf = (u8 *)op->data.buf.out; -+ txbuf[txlen++] = buf[i]; -+ } -+ -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ rxbuf = (u8 *)op->data.buf.in; -+ rxlen += op->data.nbytes; -+ } -+ -+ ret = mtk_snfi_command_exec(snfi, txbuf, rxbuf, txlen, rxlen); -+ kfree(txbuf); -+ -+ return ret; -+} -+ -+static int mtk_snfi_init(struct mtk_snfi *snfi) -+{ -+ int ret; -+ -+ /* Reset the state machine and data FIFO */ -+ ret = mtk_snfi_reset(snfi); -+ if (ret) { -+ dev_warn(snfi->dev, "MTK reset controller fail\n"); -+ return ret; -+ } -+ -+ snfi->buffer = devm_kzalloc(snfi->dev, 4096 + 256, GFP_KERNEL); -+ if (!snfi->buffer) -+ return -ENOMEM; -+ -+ /* Clear interrupt, read clear. */ -+ readw(snfi->regs + NFI_INTR_STA); -+ writew(0, snfi->regs + NFI_INTR_EN); -+ -+ writel(0, snfi->regs + NFI_CON); -+ writel(0, snfi->regs + NFI_CNFG); -+ -+ /* Change to NFI_SPI mode. */ -+ writel(SNFI_MODE_EN, snfi->regs + SNFI_CNFG); -+ -+ return 0; -+} -+ -+static int mtk_snfi_check_buswidth(u8 width) -+{ -+ switch (width) { -+ case 1: -+ case 2: -+ case 4: -+ return 0; -+ -+ default: -+ break; -+ } -+ -+ return -ENOTSUPP; -+} -+ -+static bool mtk_snfi_supports_op(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ int ret = 0; -+ -+ /* For MTK Spi Nand controller, cmd buswidth just support 1 bit*/ -+ if (op->cmd.buswidth != 1) -+ ret = -ENOTSUPP; -+ -+ if (op->addr.nbytes) -+ ret |= mtk_snfi_check_buswidth(op->addr.buswidth); -+ -+ if (op->dummy.nbytes) -+ ret |= mtk_snfi_check_buswidth(op->dummy.buswidth); -+ -+ if (op->data.nbytes) -+ ret |= mtk_snfi_check_buswidth(op->data.buswidth); -+ -+ if (ret) -+ return false; -+ -+ return true; -+} -+ -+static const struct spi_controller_mem_ops mtk_snfi_ops = { -+ .supports_op = mtk_snfi_supports_op, -+ .exec_op = mtk_snfi_exec_op, -+}; -+ -+static const struct mtk_snfi_caps snfi_mt7622 = { -+ .spare_size = spare_size_mt7622, -+ .num_spare_size = 4, -+ .nand_sec_size = 512, -+ .nand_fdm_size = 8, -+ .nand_fdm_ecc_size = 1, -+ .ecc_parity_bits = 13, -+ .pageformat_spare_shift = 4, -+ .bad_mark_swap = 0, -+}; -+ -+static const struct mtk_snfi_caps snfi_mt7629 = { -+ .spare_size = spare_size_mt7622, -+ .num_spare_size = 4, -+ .nand_sec_size = 512, -+ .nand_fdm_size = 8, -+ .nand_fdm_ecc_size = 1, -+ .ecc_parity_bits = 13, -+ .pageformat_spare_shift = 4, -+ .bad_mark_swap = 1, -+}; -+ -+static const struct of_device_id mtk_snfi_id_table[] = { -+ { .compatible = "mediatek,mt7622-snfi", .data = &snfi_mt7622, }, -+ { .compatible = "mediatek,mt7629-snfi", .data = &snfi_mt7629, }, -+ { /* sentinel */ } -+}; -+ -+static int mtk_snfi_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct spi_controller *ctlr; -+ struct mtk_snfi *snfi; -+ struct resource *res; -+ int ret = 0, irq; -+ -+ ctlr = spi_alloc_master(&pdev->dev, sizeof(*snfi)); -+ if (!ctlr) -+ return -ENOMEM; -+ -+ snfi = spi_controller_get_devdata(ctlr); -+ snfi->caps = of_device_get_match_data(dev); -+ snfi->dev = dev; -+ -+ snfi->ecc = of_mtk_ecc_get(np); -+ if (IS_ERR_OR_NULL(snfi->ecc)) -+ goto err_put_master; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ snfi->regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(snfi->regs)) { -+ ret = PTR_ERR(snfi->regs); -+ goto release_ecc; -+ } -+ -+ /* find the clocks */ -+ snfi->clk.nfi_clk = devm_clk_get(dev, "nfi_clk"); -+ if (IS_ERR(snfi->clk.nfi_clk)) { -+ dev_err(dev, "no nfi clk\n"); -+ ret = PTR_ERR(snfi->clk.nfi_clk); -+ goto release_ecc; -+ } -+ -+ snfi->clk.spi_clk = devm_clk_get(dev, "spi_clk"); -+ if (IS_ERR(snfi->clk.spi_clk)) { -+ dev_err(dev, "no spi clk\n"); -+ ret = PTR_ERR(snfi->clk.spi_clk); -+ goto release_ecc; -+ } -+ -+ ret = mtk_snfi_enable_clk(dev, &snfi->clk); -+ if (ret) -+ goto release_ecc; -+ -+ /* find the irq */ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(dev, "no snfi irq resource\n"); -+ ret = -EINVAL; -+ goto clk_disable; -+ } -+ -+ ret = devm_request_irq(dev, irq, mtk_snfi_irq, 0, "mtk-snfi", snfi); -+ if (ret) { -+ dev_err(dev, "failed to request snfi irq\n"); -+ goto clk_disable; -+ } -+ -+ ret = dma_set_mask(dev, DMA_BIT_MASK(32)); -+ if (ret) { -+ dev_err(dev, "failed to set dma mask\n"); -+ goto clk_disable; -+ } -+ -+ ctlr->dev.of_node = np; -+ ctlr->mem_ops = &mtk_snfi_ops; -+ -+ platform_set_drvdata(pdev, snfi); -+ ret = mtk_snfi_init(snfi); -+ if (ret) { -+ dev_err(dev, "failed to init snfi\n"); -+ goto clk_disable; -+ } -+ -+ ret = devm_spi_register_master(dev, ctlr); -+ if (ret) -+ goto clk_disable; -+ -+ return 0; -+ -+clk_disable: -+ mtk_snfi_disable_clk(&snfi->clk); -+ -+release_ecc: -+ mtk_ecc_release(snfi->ecc); -+ -+err_put_master: -+ spi_master_put(ctlr); -+ -+ dev_err(dev, "MediaTek SPI NAND interface probe failed %d\n", ret); -+ return ret; -+} -+ -+static int mtk_snfi_remove(struct platform_device *pdev) -+{ -+ struct mtk_snfi *snfi = platform_get_drvdata(pdev); -+ -+ mtk_snfi_disable_clk(&snfi->clk); -+ -+ return 0; -+} -+ -+static int mtk_snfi_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct mtk_snfi *snfi = platform_get_drvdata(pdev); -+ -+ mtk_snfi_disable_clk(&snfi->clk); -+ -+ return 0; -+} -+ -+static int mtk_snfi_resume(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct mtk_snfi *snfi = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = mtk_snfi_enable_clk(dev, &snfi->clk); -+ if (ret) -+ return ret; -+ -+ ret = mtk_snfi_init(snfi); -+ if (ret) -+ dev_err(dev, "failed to init snfi controller\n"); -+ -+ return ret; -+} -+ -+static struct platform_driver mtk_snfi_driver = { -+ .driver = { -+ .name = "mtk-snfi", -+ .of_match_table = mtk_snfi_id_table, -+ }, -+ .probe = mtk_snfi_probe, -+ .remove = mtk_snfi_remove, -+ .suspend = mtk_snfi_suspend, -+ .resume = mtk_snfi_resume, -+}; -+ -+module_platform_driver(mtk_snfi_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou@mediatek.com>"); -+MODULE_DESCRIPTION("Mediatek SPI Memory Interface Driver"); diff --git a/target/linux/mediatek/patches-5.4/0307-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-5.4/0307-dts-mt7629-add-snand-support.patch deleted file mode 100644 index 233face4c5..0000000000 --- a/target/linux/mediatek/patches-5.4/0307-dts-mt7629-add-snand-support.patch +++ /dev/null @@ -1,97 +0,0 @@ -From c813fbe806257c574240770ef716fbee19f7dbfa Mon Sep 17 00:00:00 2001 -From: Xiangsheng Hou <xiangsheng.hou@mediatek.com> -Date: Thu, 6 Jun 2019 16:29:04 +0800 -Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629 - -Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com> ---- - arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++ - 3 files changed, 79 insertions(+) - ---- a/arch/arm/boot/dts/mt7629.dtsi -+++ b/arch/arm/boot/dts/mt7629.dtsi -@@ -258,6 +258,28 @@ - status = "disabled"; - }; - -+ bch: ecc@1100e000 { -+ compatible = "mediatek,mt7622-ecc"; -+ reg = <0x1100e000 0x1000>; -+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_LOW>; -+ clocks = <&pericfg CLK_PERI_NFIECC_PD>; -+ clock-names = "nfiecc_clk"; -+ status = "disabled"; -+ }; -+ -+ snfi: spi@1100d000 { -+ compatible = "mediatek,mt7629-snfi"; -+ reg = <0x1100d000 0x1000>; -+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>; -+ clocks = <&pericfg CLK_PERI_NFI_PD>, -+ <&pericfg CLK_PERI_SNFI_PD>; -+ clock-names = "nfi_clk", "spi_clk"; -+ ecc-engine = <&bch>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - spi: spi@1100a000 { - compatible = "mediatek,mt7629-spi", - "mediatek,mt7622-spi"; ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -281,6 +281,52 @@ - }; - }; - -+&bch { -+ status = "okay"; -+}; -+ -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; -+ -+ spi_nand@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "spi-nand"; -+ spi-max-frequency = <104000000>; -+ reg = <0>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "Bootloader"; -+ reg = <0x00000 0x0100000>; -+ read-only; -+ }; -+ -+ partition@100000 { -+ label = "Config"; -+ reg = <0x100000 0x0040000>; -+ }; -+ -+ partition@140000 { -+ label = "factory"; -+ reg = <0x140000 0x0080000>; -+ }; -+ -+ partition@1c0000 { -+ label = "firmware"; -+ reg = <0x1c0000 0x1000000>; -+ }; -+ -+ }; -+ }; -+}; -+ - &spi { - pinctrl-names = "default"; - pinctrl-0 = <&spi_pins>; diff --git a/target/linux/mediatek/patches-5.4/0308-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-5.4/0308-dts-mt7622-add-snand-support.patch deleted file mode 100644 index b287780d6c..0000000000 --- a/target/linux/mediatek/patches-5.4/0308-dts-mt7622-add-snand-support.patch +++ /dev/null @@ -1,96 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -554,6 +554,19 @@ - status = "disabled"; - }; - -+ snfi: spi@1100d000 { -+ compatible = "mediatek,mt7622-snfi"; -+ reg = <0 0x1100d000 0 0x1000>; -+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>; -+ clocks = <&pericfg CLK_PERI_NFI_PD>, -+ <&pericfg CLK_PERI_SNFI_PD>; -+ clock-names = "nfi_clk", "spi_clk"; -+ ecc-engine = <&bch>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - nor_flash: spi@11014000 { - compatible = "mediatek,mt7622-nor", - "mediatek,mt8173-nor"; ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -99,7 +99,7 @@ - }; - - &bch { -- status = "disabled"; -+ status = "okay"; - }; - - &btif { -@@ -551,6 +551,62 @@ - status = "disable"; - }; - -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; -+ -+ spi_nand@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "spi-nand"; -+ spi-max-frequency = <104000000>; -+ reg = <0>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "Preloader"; -+ reg = <0x00000 0x0080000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "ATF"; -+ reg = <0x80000 0x0040000>; -+ }; -+ -+ partition@c0000 { -+ label = "Bootloader"; -+ reg = <0xc0000 0x0080000>; -+ }; -+ -+ partition@140000 { -+ label = "Config"; -+ reg = <0x140000 0x0080000>; -+ }; -+ -+ partition@1c0000 { -+ label = "Factory"; -+ reg = <0x1c0000 0x0040000>; -+ }; -+ -+ partition@200000 { -+ label = "firmware"; -+ reg = <0x200000 0x2000000>; -+ }; -+ -+ partition@2200000 { -+ label = "User_data"; -+ reg = <0x2200000 0x4000000>; -+ }; -+ }; -+ }; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spic0_pins>; diff --git a/target/linux/mediatek/patches-5.4/0310-dts-add-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.4/0310-dts-add-wmac-support-for-mt7622-rfb1.patch deleted file mode 100644 index 84aed89752..0000000000 --- a/target/linux/mediatek/patches-5.4/0310-dts-add-wmac-support-for-mt7622-rfb1.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -716,6 +716,17 @@ - status = "disabled"; - }; - -+ wmac: wmac@18000000 { -+ compatible = "mediatek,mt7622-wmac"; -+ reg = <0 0x18000000 0 0x100000>; -+ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_LOW>; -+ -+ mediatek,infracfg = <&infracfg>; -+ status = "disabled"; -+ -+ power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>; -+ }; -+ - ssusbsys: ssusbsys@1a000000 { - compatible = "mediatek,mt7622-ssusbsys", - "syscon"; ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -589,7 +589,7 @@ - reg = <0x140000 0x0080000>; - }; - -- partition@1c0000 { -+ factory: partition@1c0000 { - label = "Factory"; - reg = <0x1c0000 0x0040000>; - }; -@@ -646,3 +646,8 @@ - pinctrl-0 = <&watchdog_pins>; - status = "okay"; - }; -+ -+&wmac { -+ mediatek,mtd-eeprom = <&factory 0x0000>; -+ status = "okay"; -+}; diff --git a/target/linux/mediatek/patches-5.4/0310-mtk-bmt-support.patch b/target/linux/mediatek/patches-5.4/0310-mtk-bmt-support.patch deleted file mode 100644 index 4cef9f9d5e..0000000000 --- a/target/linux/mediatek/patches-5.4/0310-mtk-bmt-support.patch +++ /dev/null @@ -1,837 +0,0 @@ ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -5,3 +5,7 @@ config MTD_NAND_CORE - source "drivers/mtd/nand/onenand/Kconfig" - source "drivers/mtd/nand/raw/Kconfig" - source "drivers/mtd/nand/spi/Kconfig" -+ -+config MTD_NAND_MTK_BMT -+ bool "Support MediaTek NAND Bad-block Management Table" -+ default n ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -2,6 +2,7 @@ - - nandcore-objs := core.o bbt.o - obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o -+obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o - - obj-y += onenand/ - obj-y += raw/ ---- /dev/null -+++ b/drivers/mtd/nand/mtk_bmt.c -@@ -0,0 +1,766 @@ -+/* -+ * Copyright (c) 2017 MediaTek Inc. -+ * Author: Xiangsheng Hou <xiangsheng.hou@mediatek.com> -+ * Copyright (c) 2020 Felix Fietkau <nbd@nbd.name> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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. -+ */ -+ -+#include <linux/slab.h> -+#include <linux/gfp.h> -+#include <linux/kernel.h> -+#include <linux/of.h> -+#include <linux/mtd/nand.h> -+#include <linux/mtd/partitions.h> -+#include <linux/mtd/mtk_bmt.h> -+#include <linux/module.h> -+#include <linux/debugfs.h> -+ -+#define MAIN_SIGNATURE_OFFSET 0 -+#define OOB_SIGNATURE_OFFSET 1 -+#define BBPOOL_RATIO 2 -+ -+#define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__) -+ -+/* Maximum 8k blocks */ -+#define BB_TABLE_MAX 0x2000U -+#define BMT_TABLE_MAX (BB_TABLE_MAX * BBPOOL_RATIO / 100) -+#define BMT_TBL_DEF_VAL 0x0 -+ -+/* -+ * Burner Bad Block Table -+ * --------- Only support SLC Nand Chips!!!!!!!!!!! ---------- -+ */ -+ -+struct bbbt { -+ char signature[3]; -+ /* This version is used to distinguish the legacy and new algorithm */ -+#define BBMT_VERSION 2 -+ unsigned char version; -+ /* Below 2 tables will be written in SLC */ -+ u16 bb_tbl[BB_TABLE_MAX]; -+ struct bbmt { -+ u16 block; -+#define NO_MAPPED 0 -+#define NORMAL_MAPPED 1 -+#define BMT_MAPPED 2 -+ u16 mapped; -+ } bmt_tbl[BMT_TABLE_MAX]; -+}; -+ -+static struct bmt_desc { -+ struct mtd_info *mtd; -+ -+ int (*_read_oob) (struct mtd_info *mtd, loff_t from, -+ struct mtd_oob_ops *ops); -+ int (*_write_oob) (struct mtd_info *mtd, loff_t to, -+ struct mtd_oob_ops *ops); -+ const struct nand_ops *nand_ops; -+ -+ struct bbbt *bbt; -+ -+ struct dentry *debugfs_dir; -+ -+ u32 pg_size; -+ u32 blk_size; -+ u16 pg_shift; -+ u16 blk_shift; -+ /* bbt logical address */ -+ u16 pool_lba; -+ /* bbt physical address */ -+ u16 pool_pba; -+ /* Maximum count of bad blocks that the vendor guaranteed */ -+ u16 bb_max; -+ /* Total blocks of the Nand Chip */ -+ u16 total_blks; -+ /* The block(n) BMT is located at (bmt_tbl[n]) */ -+ u16 bmt_blk_idx; -+ /* How many pages needs to store 'struct bbbt' */ -+ u32 bmt_pgs; -+ -+ /* to compensate for driver level remapping */ -+ u8 oob_offset; -+} bmtd = {0}; -+ -+static unsigned char *nand_bbt_buf; -+static unsigned char *nand_data_buf; -+ -+/* -------- Unit conversions -------- */ -+static inline u32 blk_pg(u16 block) -+{ -+ return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift)); -+} -+ -+/* -------- Nand operations wrapper -------- */ -+static inline int -+bbt_nand_read(u32 page, unsigned char *dat, int dat_len, -+ unsigned char *fdm, int fdm_len) -+{ -+ struct mtd_oob_ops ops = { -+ .mode = MTD_OPS_PLACE_OOB, -+ .ooboffs = bmtd.oob_offset, -+ .oobbuf = fdm, -+ .ooblen = fdm_len, -+ .datbuf = dat, -+ .len = dat_len, -+ }; -+ -+ return bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops); -+} -+ -+static inline int bbt_nand_erase(u16 block) -+{ -+ struct nand_device *nand = mtd_to_nanddev(bmtd.mtd); -+ loff_t addr = (loff_t)block << bmtd.blk_shift; -+ struct nand_pos pos; -+ -+ nanddev_offs_to_pos(nand, addr, &pos); -+ return bmtd.nand_ops->erase(nand, &pos); -+} -+ -+/* -------- Bad Blocks Management -------- */ -+static int -+read_bmt(u16 block, unsigned char *dat, unsigned char *fdm, int fdm_len) -+{ -+ u32 len = bmtd.bmt_pgs << bmtd.pg_shift; -+ -+ return bbt_nand_read(blk_pg(block), dat, len, fdm, fdm_len); -+} -+ -+static int write_bmt(u16 block, unsigned char *dat) -+{ -+ struct mtd_oob_ops ops = { -+ .mode = MTD_OPS_PLACE_OOB, -+ .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset, -+ .oobbuf = "bmt", -+ .ooblen = 3, -+ .datbuf = dat, -+ .len = bmtd.bmt_pgs << bmtd.pg_shift, -+ }; -+ loff_t addr = (loff_t)block << bmtd.blk_shift; -+ -+ return bmtd._write_oob(bmtd.mtd, addr, &ops); -+} -+ -+static u16 find_valid_block(u16 block) -+{ -+ u8 fdm[4]; -+ int ret; -+ int loop = 0; -+ -+retry: -+ if (block >= bmtd.total_blks) -+ return 0; -+ -+ ret = bbt_nand_read(blk_pg(block), nand_data_buf, bmtd.pg_size, -+ fdm, sizeof(fdm)); -+ /* Read the 1st byte of FDM to judge whether it's a bad -+ * or not -+ */ -+ if (ret || fdm[0] != 0xff) { -+ pr_info("nand: found bad block 0x%x\n", block); -+ if (loop >= bmtd.bb_max) { -+ pr_info("nand: FATAL ERR: too many bad blocks!!\n"); -+ return 0; -+ } -+ -+ loop++; -+ block++; -+ goto retry; -+ } -+ -+ return block; -+} -+ -+/* Find out all bad blocks, and fill in the mapping table */ -+static int scan_bad_blocks(struct bbbt *bbt) -+{ -+ int i; -+ u16 block = 0; -+ -+ /* First time download, the block0 MUST NOT be a bad block, -+ * this is guaranteed by vendor -+ */ -+ bbt->bb_tbl[0] = 0; -+ -+ /* -+ * Construct the mapping table of Normal data area(non-PMT/BMTPOOL) -+ * G - Good block; B - Bad block -+ * --------------------------- -+ * physical |G|G|B|G|B|B|G|G|G|G|B|G|B| -+ * --------------------------- -+ * What bb_tbl[i] looks like: -+ * physical block(i): -+ * 0 1 2 3 4 5 6 7 8 9 a b c -+ * mapped block(bb_tbl[i]): -+ * 0 1 3 6 7 8 9 b ...... -+ * ATTENTION: -+ * If new bad block ocurred(n), search bmt_tbl to find -+ * a available block(x), and fill in the bb_tbl[n] = x; -+ */ -+ for (i = 1; i < bmtd.pool_lba; i++) { -+ bbt->bb_tbl[i] = find_valid_block(bbt->bb_tbl[i - 1] + 1); -+ BBT_LOG("bb_tbl[0x%x] = 0x%x", i, bbt->bb_tbl[i]); -+ if (bbt->bb_tbl[i] == 0) -+ return -1; -+ } -+ -+ /* Physical Block start Address of BMT pool */ -+ bmtd.pool_pba = bbt->bb_tbl[i - 1] + 1; -+ if (bmtd.pool_pba >= bmtd.total_blks - 2) { -+ pr_info("nand: FATAL ERR: Too many bad blocks!!\n"); -+ return -1; -+ } -+ -+ BBT_LOG("pool_pba=0x%x", bmtd.pool_pba); -+ i = 0; -+ block = bmtd.pool_pba; -+ /* -+ * The bmt table is used for runtime bad block mapping -+ * G - Good block; B - Bad block -+ * --------------------------- -+ * physical |G|G|B|G|B|B|G|G|G|G|B|G|B| -+ * --------------------------- -+ * block: 0 1 2 3 4 5 6 7 8 9 a b c -+ * What bmt_tbl[i] looks like in initial state: -+ * i: -+ * 0 1 2 3 4 5 6 7 -+ * bmt_tbl[i].block: -+ * 0 1 3 6 7 8 9 b -+ * bmt_tbl[i].mapped: -+ * N N N N N N N B -+ * N - Not mapped(Available) -+ * M - Mapped -+ * B - BMT -+ * ATTENTION: -+ * BMT always in the last valid block in pool -+ */ -+ while ((block = find_valid_block(block)) != 0) { -+ bbt->bmt_tbl[i].block = block; -+ bbt->bmt_tbl[i].mapped = NO_MAPPED; -+ BBT_LOG("bmt_tbl[%d].block = 0x%x", i, block); -+ block++; -+ i++; -+ } -+ -+ /* i - How many available blocks in pool, which is the length of bmt_tbl[] -+ * bmtd.bmt_blk_idx - bmt_tbl[bmtd.bmt_blk_idx].block => the BMT block -+ */ -+ bmtd.bmt_blk_idx = i - 1; -+ bbt->bmt_tbl[bmtd.bmt_blk_idx].mapped = BMT_MAPPED; -+ -+ if (i < 1) { -+ pr_info("nand: FATAL ERR: no space to store BMT!!\n"); -+ return -1; -+ } -+ -+ pr_info("[BBT] %d available blocks in BMT pool\n", i); -+ -+ return 0; -+} -+ -+static bool is_valid_bmt(unsigned char *buf, unsigned char *fdm) -+{ -+ struct bbbt *bbt = (struct bbbt *)buf; -+ u8 *sig = (u8*)bbt->signature + MAIN_SIGNATURE_OFFSET; -+ -+ -+ if (memcmp(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3) == 0 && -+ memcmp(fdm + OOB_SIGNATURE_OFFSET, "bmt", 3) == 0) { -+ if (bbt->version == BBMT_VERSION) -+ return true; -+ } -+ BBT_LOG("[BBT] BMT Version not match,upgrage preloader and uboot please! sig=%02x%02x%02x, fdm=%02x%02x%02x", -+ sig[0], sig[1], sig[2], -+ fdm[1], fdm[2], fdm[3]); -+ return false; -+} -+ -+static u16 get_bmt_index(struct bbmt *bmt) -+{ -+ int i = 0; -+ -+ while (bmt[i].block != BMT_TBL_DEF_VAL) { -+ if (bmt[i].mapped == BMT_MAPPED) -+ return i; -+ i++; -+ } -+ return 0; -+} -+ -+static struct bbbt *scan_bmt(u16 block) -+{ -+ u8 fdm[4]; -+ -+ if (block < bmtd.pool_lba) -+ return NULL; -+ -+ if (read_bmt(block, nand_bbt_buf, fdm, sizeof(fdm))) -+ return scan_bmt(block - 1); -+ -+ if (is_valid_bmt(nand_bbt_buf, fdm)) { -+ bmtd.bmt_blk_idx = get_bmt_index(((struct bbbt *)nand_bbt_buf)->bmt_tbl); -+ if (bmtd.bmt_blk_idx == 0) { -+ pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n"); -+ return NULL; -+ } -+ pr_info("[BBT] BMT.v2 is found at 0x%x\n", block); -+ return (struct bbbt *)nand_bbt_buf; -+ } else -+ return scan_bmt(block - 1); -+} -+ -+/* Write the Burner Bad Block Table to Nand Flash -+ * n - write BMT to bmt_tbl[n] -+ */ -+static u16 upload_bmt(struct bbbt *bbt, int n) -+{ -+ u16 block; -+ -+retry: -+ if (n < 0 || bbt->bmt_tbl[n].mapped == NORMAL_MAPPED) { -+ pr_info("nand: FATAL ERR: no space to store BMT!\n"); -+ return (u16)-1; -+ } -+ -+ block = bbt->bmt_tbl[n].block; -+ BBT_LOG("n = 0x%x, block = 0x%x", n, block); -+ if (bbt_nand_erase(block)) { -+ bbt->bmt_tbl[n].block = 0; -+ /* erase failed, try the previous block: bmt_tbl[n - 1].block */ -+ n--; -+ goto retry; -+ } -+ -+ /* The signature offset is fixed set to 0, -+ * oob signature offset is fixed set to 1 -+ */ -+ memcpy(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3); -+ bbt->version = BBMT_VERSION; -+ -+ if (write_bmt(block, (unsigned char *)bbt)) { -+ bbt->bmt_tbl[n].block = 0; -+ -+ /* write failed, try the previous block in bmt_tbl[n - 1] */ -+ n--; -+ goto retry; -+ } -+ -+ /* Return the current index(n) of BMT pool (bmt_tbl[n]) */ -+ return n; -+} -+ -+static u16 find_valid_block_in_pool(struct bbbt *bbt) -+{ -+ int i; -+ -+ if (bmtd.bmt_blk_idx == 0) -+ goto error; -+ -+ for (i = 0; i < bmtd.bmt_blk_idx; i++) { -+ if (bbt->bmt_tbl[i].block != 0 && bbt->bmt_tbl[i].mapped == NO_MAPPED) { -+ bbt->bmt_tbl[i].mapped = NORMAL_MAPPED; -+ return bbt->bmt_tbl[i].block; -+ } -+ } -+ -+error: -+ pr_info("nand: FATAL ERR: BMT pool is run out!\n"); -+ return 0; -+} -+ -+/* We met a bad block, mark it as bad and map it to a valid block in pool, -+ * if it's a write failure, we need to write the data to mapped block -+ */ -+static bool update_bmt(u16 block) -+{ -+ u16 mapped_blk; -+ struct bbbt *bbt; -+ -+ bbt = bmtd.bbt; -+ mapped_blk = find_valid_block_in_pool(bbt); -+ if (mapped_blk == 0) -+ return false; -+ -+ /* Map new bad block to available block in pool */ -+ bbt->bb_tbl[block] = mapped_blk; -+ bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx); -+ -+ return true; -+} -+ -+u16 get_mapping_block_index(int block) -+{ -+ int mapping_block; -+ -+ if (block < bmtd.pool_lba) -+ mapping_block = bmtd.bbt->bb_tbl[block]; -+ else -+ mapping_block = block; -+ BBT_LOG("0x%x mapped to 0x%x", block, mapping_block); -+ -+ return mapping_block; -+} -+ -+static int -+mtk_bmt_read(struct mtd_info *mtd, loff_t from, -+ struct mtd_oob_ops *ops) -+{ -+ struct mtd_oob_ops cur_ops = *ops; -+ int retry_count = 0; -+ loff_t cur_from; -+ int ret; -+ -+ ops->retlen = 0; -+ ops->oobretlen = 0; -+ -+ while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { -+ u32 offset = from & (bmtd.blk_size - 1); -+ u32 block = from >> bmtd.blk_shift; -+ u32 cur_block; -+ -+ cur_block = get_mapping_block_index(block); -+ cur_from = ((loff_t)cur_block << bmtd.blk_shift) + offset; -+ -+ cur_ops.oobretlen = 0; -+ cur_ops.retlen = 0; -+ cur_ops.len = min_t(u32, mtd->erasesize - offset, -+ ops->len - ops->retlen); -+ ret = bmtd._read_oob(mtd, cur_from, &cur_ops); -+ if (ret < 0) { -+ update_bmt(block); -+ if (retry_count++ < 10) -+ continue; -+ -+ return ret; -+ } -+ -+ ops->retlen += cur_ops.retlen; -+ ops->oobretlen += cur_ops.oobretlen; -+ -+ cur_ops.datbuf += cur_ops.retlen; -+ cur_ops.oobbuf += cur_ops.oobretlen; -+ cur_ops.ooblen -= cur_ops.oobretlen; -+ -+ if (!cur_ops.len) -+ cur_ops.len = mtd->erasesize - offset; -+ -+ from += cur_ops.len; -+ retry_count = 0; -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_bmt_write(struct mtd_info *mtd, loff_t to, -+ struct mtd_oob_ops *ops) -+{ -+ struct mtd_oob_ops cur_ops = *ops; -+ int retry_count = 0; -+ loff_t cur_to; -+ int ret; -+ -+ ops->retlen = 0; -+ ops->oobretlen = 0; -+ -+ while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { -+ u32 offset = to & (bmtd.blk_size - 1); -+ u32 block = to >> bmtd.blk_shift; -+ u32 cur_block; -+ -+ cur_block = get_mapping_block_index(block); -+ cur_to = ((loff_t)cur_block << bmtd.blk_shift) + offset; -+ -+ cur_ops.oobretlen = 0; -+ cur_ops.retlen = 0; -+ cur_ops.len = min_t(u32, bmtd.blk_size - offset, -+ ops->len - ops->retlen); -+ ret = bmtd._write_oob(mtd, cur_to, &cur_ops); -+ if (ret < 0) { -+ update_bmt(block); -+ if (retry_count++ < 10) -+ continue; -+ -+ return ret; -+ } -+ -+ ops->retlen += cur_ops.retlen; -+ ops->oobretlen += cur_ops.oobretlen; -+ -+ cur_ops.datbuf += cur_ops.retlen; -+ cur_ops.oobbuf += cur_ops.oobretlen; -+ cur_ops.ooblen -= cur_ops.oobretlen; -+ -+ if (!cur_ops.len) -+ cur_ops.len = mtd->erasesize - offset; -+ -+ to += cur_ops.len; -+ retry_count = 0; -+ } -+ -+ return 0; -+} -+ -+ -+ -+static int -+mtk_bmt_erase(struct nand_device *nand, const struct nand_pos *pos) -+{ -+ struct nand_pos new_pos = *pos; -+ int retry_count = 0; -+ int ret; -+ -+retry: -+ new_pos.eraseblock = get_mapping_block_index(pos->eraseblock); -+ -+ ret = bmtd.nand_ops->erase(nand, &new_pos); -+ if (ret) { -+ update_bmt(pos->eraseblock); -+ if (retry_count++ < 10) -+ goto retry; -+ } -+ -+ return ret; -+} -+ -+static bool -+mtk_bmt_isbad(struct nand_device *nand, const struct nand_pos *pos) -+{ -+ struct nand_pos new_pos = *pos; -+ int retry_count = 0; -+ bool ret; -+ -+retry: -+ new_pos.eraseblock = get_mapping_block_index(pos->eraseblock); -+ -+ ret = bmtd.nand_ops->isbad(nand, &new_pos); -+ if (ret) { -+ update_bmt(pos->eraseblock); -+ if (retry_count++ < 10) -+ goto retry; -+ } -+ -+ return ret; -+} -+ -+static int -+mtk_bmt_markbad(struct nand_device *nand, const struct nand_pos *pos) -+{ -+ struct nand_pos new_pos = *pos; -+ -+ new_pos.eraseblock = get_mapping_block_index(new_pos.eraseblock); -+ update_bmt(pos->eraseblock); -+ -+ return bmtd.nand_ops->markbad(nand, &new_pos); -+} -+ -+static void -+mtk_bmt_replace_ops(struct mtd_info *mtd) -+{ -+ static const struct nand_ops mtk_bmt_nand_ops = { -+ .erase = mtk_bmt_erase, -+ .isbad = mtk_bmt_isbad, -+ .markbad = mtk_bmt_markbad, -+ }; -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ -+ bmtd.nand_ops = nand->ops; -+ bmtd._read_oob = mtd->_read_oob; -+ bmtd._write_oob = mtd->_write_oob; -+ -+ mtd->_read_oob = mtk_bmt_read; -+ mtd->_write_oob = mtk_bmt_write; -+ nand->ops = &mtk_bmt_nand_ops; -+} -+ -+static int mtk_bmt_debug_mark_good(void *data, u64 val) -+{ -+ u32 block = val >> bmtd.blk_shift; -+ -+ bmtd.bbt->bb_tbl[block] = block; -+ bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); -+ -+ return 0; -+} -+ -+static int mtk_bmt_debug_mark_bad(void *data, u64 val) -+{ -+ u32 block = val >> bmtd.blk_shift; -+ -+ update_bmt(block); -+ -+ return 0; -+} -+ -+DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n"); -+DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n"); -+ -+static void -+mtk_bmt_add_debugfs(void) -+{ -+ struct dentry *dir; -+ -+ dir = bmtd.debugfs_dir = debugfs_create_dir("mtk-bmt", NULL); -+ if (!dir) -+ return; -+ -+ debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good); -+ debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad); -+} -+ -+void mtk_bmt_detach(struct mtd_info *mtd) -+{ -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ -+ if (bmtd.mtd != mtd) -+ return; -+ -+ if (bmtd.debugfs_dir) -+ debugfs_remove_recursive(bmtd.debugfs_dir); -+ bmtd.debugfs_dir = NULL; -+ -+ kfree(nand_bbt_buf); -+ kfree(nand_data_buf); -+ -+ mtd->_read_oob = bmtd._read_oob; -+ mtd->_write_oob = bmtd._write_oob; -+ mtd->size = bmtd.total_blks << bmtd.blk_shift; -+ nand->ops = bmtd.nand_ops; -+ -+ memset(&bmtd, 0, sizeof(bmtd)); -+} -+ -+/* total_blocks - The total count of blocks that the Nand Chip has */ -+int mtk_bmt_attach(struct mtd_info *mtd) -+{ -+ struct device_node *np; -+ struct bbbt *bbt; -+ u32 bufsz; -+ u32 block; -+ u16 total_blocks, pmt_block; -+ int ret = 0; -+ u32 bmt_pool_size; -+ -+ if (bmtd.mtd) -+ return -ENOSPC; -+ -+ np = mtd_get_of_node(mtd); -+ if (!np) -+ return 0; -+ -+ if (!of_property_read_bool(np, "mediatek,bmt-v2")) -+ return 0; -+ -+ if (of_property_read_u32(np, "mediatek,bmt-pool-size", -+ &bmt_pool_size) != 0) -+ bmt_pool_size = 80; -+ -+ if (of_property_read_u8(np, "mediatek,bmt-oob-offset", -+ &bmtd.oob_offset) != 0) -+ bmtd.oob_offset = 8; -+ -+ bmtd.mtd = mtd; -+ mtk_bmt_replace_ops(mtd); -+ -+ bmtd.blk_size = mtd->erasesize; -+ bmtd.blk_shift = ffs(bmtd.blk_size) - 1; -+ bmtd.pg_size = mtd->writesize; -+ bmtd.pg_shift = ffs(bmtd.pg_size) - 1; -+ total_blocks = mtd->size >> bmtd.blk_shift; -+ pmt_block = total_blocks - bmt_pool_size - 2; -+ -+ mtd->size = pmt_block << bmtd.blk_shift; -+ -+ /* -+ * --------------------------------------- -+ * | PMT(2blks) | BMT POOL(totalblks * 2%) | -+ * --------------------------------------- -+ * ^ ^ -+ * | | -+ * pmt_block pmt_block + 2blocks(pool_lba) -+ * -+ * ATTETION!!!!!! -+ * The blocks ahead of the boundary block are stored in bb_tbl -+ * and blocks behind are stored in bmt_tbl -+ */ -+ -+ bmtd.pool_lba = (u16)(pmt_block + 2); -+ bmtd.total_blks = total_blocks; -+ bmtd.bb_max = bmtd.total_blks * BBPOOL_RATIO / 100; -+ -+ /* 3 buffers we need */ -+ bufsz = round_up(sizeof(struct bbbt), bmtd.pg_size); -+ bmtd.bmt_pgs = bufsz >> bmtd.pg_shift; -+ -+ nand_bbt_buf = kzalloc(bufsz, GFP_KERNEL); -+ nand_data_buf = kzalloc(bmtd.pg_size, GFP_KERNEL); -+ -+ if (!nand_bbt_buf || !nand_data_buf) { -+ pr_info("nand: FATAL ERR: allocate buffer failed!\n"); -+ ret = -1; -+ goto error; -+ } -+ -+ memset(nand_bbt_buf, 0xff, bufsz); -+ memset(nand_data_buf, 0xff, bmtd.pg_size); -+ -+ BBT_LOG("bbtbuf=0x%p(0x%x) dat=0x%p(0x%x)", -+ nand_bbt_buf, bufsz, nand_data_buf, bmtd.pg_size); -+ BBT_LOG("pool_lba=0x%x total_blks=0x%x bb_max=0x%x", -+ bmtd.pool_lba, bmtd.total_blks, bmtd.bb_max); -+ -+ /* Scanning start from the first page of the last block -+ * of whole flash -+ */ -+ bbt = scan_bmt(bmtd.total_blks - 1); -+ if (!bbt) { -+ /* BMT not found */ -+ if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) { -+ pr_info("nand: FATAL: Too many blocks, can not support!\n"); -+ ret = -1; -+ goto error; -+ } -+ -+ bbt = (struct bbbt *)nand_bbt_buf; -+ memset(bbt->bmt_tbl, BMT_TBL_DEF_VAL, sizeof(bbt->bmt_tbl)); -+ -+ if (scan_bad_blocks(bbt)) { -+ ret = -1; -+ goto error; -+ } -+ -+ /* BMT always in the last valid block in pool */ -+ bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx); -+ block = bbt->bmt_tbl[bmtd.bmt_blk_idx].block; -+ pr_notice("[BBT] BMT.v2 is written into PBA:0x%x\n", block); -+ -+ if (bmtd.bmt_blk_idx == 0) -+ pr_info("nand: Warning: no available block in BMT pool!\n"); -+ else if (bmtd.bmt_blk_idx == (u16)-1) { -+ ret = -1; -+ goto error; -+ } -+ } -+ mtk_bmt_add_debugfs(); -+ -+ bmtd.bbt = bbt; -+ return 0; -+ -+error: -+ mtk_bmt_detach(mtd); -+ return ret; -+} -+ -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou@mediatek.com>, Felix Fietkau <nbd@nbd.name>"); -+MODULE_DESCRIPTION("Bad Block mapping management v2 for MediaTek NAND Flash Driver"); -+ ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -18,6 +18,7 @@ - #include <linux/slab.h> - #include <linux/spi/spi.h> - #include <linux/spi/spi-mem.h> -+#include <linux/mtd/mtk_bmt.h> - - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) - { -@@ -1100,6 +1101,8 @@ static int spinand_probe(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_attach(mtd); -+ - ret = mtd_device_register(mtd, NULL, 0); - if (ret) - goto err_spinand_cleanup; -@@ -1125,6 +1128,7 @@ static int spinand_remove(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return 0; ---- /dev/null -+++ b/include/linux/mtd/mtk_bmt.h -@@ -0,0 +1,18 @@ -+#ifndef __MTK_BMT_H -+#define __MTK_BMT_H -+ -+#ifdef CONFIG_MTD_NAND_MTK_BMT -+int mtk_bmt_attach(struct mtd_info *mtd); -+void mtk_bmt_detach(struct mtd_info *mtd); -+#else -+static inline int mtk_bmt_attach(struct mtd_info *mtd) -+{ -+ return 0; -+} -+ -+static inline void mtk_bmt_detach(struct mtd_info *mtd) -+{ -+} -+#endif -+ -+#endif diff --git a/target/linux/mediatek/patches-5.4/0350-mtd-parsers-trx-Allow-to-specify-trx-magic-in-DT.patch b/target/linux/mediatek/patches-5.4/0350-mtd-parsers-trx-Allow-to-specify-trx-magic-in-DT.patch deleted file mode 100644 index 0446ce9386..0000000000 --- a/target/linux/mediatek/patches-5.4/0350-mtd-parsers-trx-Allow-to-specify-trx-magic-in-DT.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0600e3d81628002a5cd80cf83ee454851b0063c0 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 7 Mar 2021 18:19:26 +0100 -Subject: mtd: parsers: trx: Allow to specify brcm,trx-magic in DT - -Buffalo uses a different TRX magic for every device, to be able to use -this trx parser, make it possible to specify the TRX magic in device -tree. If no TRX magic is specified in device tree, the standard value -will be used. This value should only be specified if a vendor chooses to -use a non standard TRX magic. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - .../bindings/mtd/partitions/brcm,trx.txt | 5 +++++ - drivers/mtd/parsers/parser_trx.c | 21 ++++++++++++++++++- - 2 files changed, 25 insertions(+), 1 deletion(-) - ---- a/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt -+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,trx.txt -@@ -28,6 +28,11 @@ detected by a software parsing TRX heade - Required properties: - - compatible : (required) must be "brcm,trx" - -+Optional properties: -+ -+- brcm,trx-magic: TRX magic, if it is different from the default magic -+ 0x30524448 as a u32. -+ - Example: - - flash@0 { ---- a/drivers/mtd/parsers/parser_trx.c -+++ b/drivers/mtd/parsers/parser_trx.c -@@ -74,6 +74,24 @@ out_default: - return "rootfs"; - } - -+static uint32_t parser_trx_get_magic(struct mtd_info *mtd) -+{ -+ uint32_t trx_magic = TRX_MAGIC; -+ struct device_node *np; -+ int err; -+ -+ np = mtd_get_of_node(mtd); -+ if (!np) -+ return trx_magic; -+ -+ /* Get different magic from device tree if specified */ -+ err = of_property_read_u32(np, "brcm,trx-magic", &trx_magic); -+ if (err != 0 && err != -EINVAL) -+ pr_err("failed to parse \"brcm,trx-magic\" DT attribute, use default: %d\n", err); -+ -+ return trx_magic; -+} -+ - static int parser_trx_parse(struct mtd_info *mtd, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -@@ -83,6 +101,7 @@ static int parser_trx_parse(struct mtd_i - struct trx_header trx; - size_t bytes_read; - uint8_t curr_part = 0, i = 0; -+ uint32_t trx_magic = parser_trx_get_magic(mtd); - int err; - - parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), -@@ -97,7 +116,7 @@ static int parser_trx_parse(struct mtd_i - return err; - } - -- if (trx.magic != TRX_MAGIC) { -+ if (trx.magic != trx_magic) { - kfree(parts); - return -ENOENT; - } diff --git a/target/linux/mediatek/patches-5.4/0351-mtd-parsers-Remove-dependency-to-BRCM-architectures.patch b/target/linux/mediatek/patches-5.4/0351-mtd-parsers-Remove-dependency-to-BRCM-architectures.patch deleted file mode 100644 index fa94c22304..0000000000 --- a/target/linux/mediatek/patches-5.4/0351-mtd-parsers-Remove-dependency-to-BRCM-architectures.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 63f0cf88ab5461acb0911252f12bb94ee3bf05a2 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 7 Mar 2021 18:23:29 +0100 -Subject: mtd: parsers: Remove dependency to BRCM architectures - -Buffalo uses the TRX partition format also on Mediatek SoCs. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/mtd/parsers/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -131,7 +131,7 @@ config MTD_AFS_PARTS - - config MTD_PARSER_TRX - tristate "Parser for TRX format partitions" -- depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST) -+ depends on MTD - help - TRX is a firmware format used by Broadcom on their devices. It - may contain up to 3/4 partitions (depending on the version). diff --git a/target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch b/target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch deleted file mode 100644 index 2fae90ef9e..0000000000 --- a/target/linux/mediatek/patches-5.4/0500-v5.6-crypto-backport-inside-secure.patch +++ /dev/null @@ -1,5464 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.c -+++ b/drivers/crypto/inside-secure/safexcel.c -@@ -75,9 +75,9 @@ static void eip197_trc_cache_banksel(str - } - - static u32 eip197_trc_cache_probe(struct safexcel_crypto_priv *priv, -- int maxbanks, u32 probemask) -+ int maxbanks, u32 probemask, u32 stride) - { -- u32 val, addrhi, addrlo, addrmid; -+ u32 val, addrhi, addrlo, addrmid, addralias, delta, marker; - int actbank; - - /* -@@ -87,32 +87,37 @@ static u32 eip197_trc_cache_probe(struct - addrhi = 1 << (16 + maxbanks); - addrlo = 0; - actbank = min(maxbanks - 1, 0); -- while ((addrhi - addrlo) > 32) { -+ while ((addrhi - addrlo) > stride) { - /* write marker to lowest address in top half */ - addrmid = (addrhi + addrlo) >> 1; -+ marker = (addrmid ^ 0xabadbabe) & probemask; /* Unique */ - eip197_trc_cache_banksel(priv, addrmid, &actbank); -- writel((addrmid | (addrlo << 16)) & probemask, -+ writel(marker, - priv->base + EIP197_CLASSIFICATION_RAMS + - (addrmid & 0xffff)); - -- /* write marker to lowest address in bottom half */ -- eip197_trc_cache_banksel(priv, addrlo, &actbank); -- writel((addrlo | (addrhi << 16)) & probemask, -- priv->base + EIP197_CLASSIFICATION_RAMS + -- (addrlo & 0xffff)); -+ /* write invalid markers to possible aliases */ -+ delta = 1 << __fls(addrmid); -+ while (delta >= stride) { -+ addralias = addrmid - delta; -+ eip197_trc_cache_banksel(priv, addralias, &actbank); -+ writel(~marker, -+ priv->base + EIP197_CLASSIFICATION_RAMS + -+ (addralias & 0xffff)); -+ delta >>= 1; -+ } - - /* read back marker from top half */ - eip197_trc_cache_banksel(priv, addrmid, &actbank); - val = readl(priv->base + EIP197_CLASSIFICATION_RAMS + - (addrmid & 0xffff)); - -- if (val == ((addrmid | (addrlo << 16)) & probemask)) { -+ if ((val & probemask) == marker) - /* read back correct, continue with top half */ - addrlo = addrmid; -- } else { -+ else - /* not read back correct, continue with bottom half */ - addrhi = addrmid; -- } - } - return addrhi; - } -@@ -150,7 +155,7 @@ static void eip197_trc_cache_clear(struc - htable_offset + i * sizeof(u32)); - } - --static void eip197_trc_cache_init(struct safexcel_crypto_priv *priv) -+static int eip197_trc_cache_init(struct safexcel_crypto_priv *priv) - { - u32 val, dsize, asize; - int cs_rc_max, cs_ht_wc, cs_trc_rec_wc, cs_trc_lg_rec_wc; -@@ -183,7 +188,7 @@ static void eip197_trc_cache_init(struct - writel(val, priv->base + EIP197_TRC_PARAMS); - - /* Probed data RAM size in bytes */ -- dsize = eip197_trc_cache_probe(priv, maxbanks, 0xffffffff); -+ dsize = eip197_trc_cache_probe(priv, maxbanks, 0xffffffff, 32); - - /* - * Now probe the administration RAM size pretty much the same way -@@ -196,11 +201,18 @@ static void eip197_trc_cache_init(struct - writel(val, priv->base + EIP197_TRC_PARAMS); - - /* Probed admin RAM size in admin words */ -- asize = eip197_trc_cache_probe(priv, 0, 0xbfffffff) >> 4; -+ asize = eip197_trc_cache_probe(priv, 0, 0x3fffffff, 16) >> 4; - - /* Clear any ECC errors detected while probing! */ - writel(0, priv->base + EIP197_TRC_ECCCTRL); - -+ /* Sanity check probing results */ -+ if (dsize < EIP197_MIN_DSIZE || asize < EIP197_MIN_ASIZE) { -+ dev_err(priv->dev, "Record cache probing failed (%d,%d).", -+ dsize, asize); -+ return -ENODEV; -+ } -+ - /* - * Determine optimal configuration from RAM sizes - * Note that we assume that the physical RAM configuration is sane -@@ -251,6 +263,7 @@ static void eip197_trc_cache_init(struct - - dev_info(priv->dev, "TRC init: %dd,%da (%dr,%dh)\n", - dsize, asize, cs_rc_max, cs_ht_wc + cs_ht_wc); -+ return 0; - } - - static void eip197_init_firmware(struct safexcel_crypto_priv *priv) -@@ -298,13 +311,14 @@ static void eip197_init_firmware(struct - static int eip197_write_firmware(struct safexcel_crypto_priv *priv, - const struct firmware *fw) - { -- const u32 *data = (const u32 *)fw->data; -+ const __be32 *data = (const __be32 *)fw->data; - int i; - - /* Write the firmware */ - for (i = 0; i < fw->size / sizeof(u32); i++) - writel(be32_to_cpu(data[i]), -- priv->base + EIP197_CLASSIFICATION_RAMS + i * sizeof(u32)); -+ priv->base + EIP197_CLASSIFICATION_RAMS + -+ i * sizeof(__be32)); - - /* Exclude final 2 NOPs from size */ - return i - EIP197_FW_TERMINAL_NOPS; -@@ -471,6 +485,14 @@ static int safexcel_hw_setup_cdesc_rings - cd_fetch_cnt = ((1 << priv->hwconfig.hwcfsize) / - cd_size_rnd) - 1; - } -+ /* -+ * Since we're using command desc's way larger than formally specified, -+ * we need to check whether we can fit even 1 for low-end EIP196's! -+ */ -+ if (!cd_fetch_cnt) { -+ dev_err(priv->dev, "Unable to fit even 1 command desc!\n"); -+ return -ENODEV; -+ } - - for (i = 0; i < priv->config.rings; i++) { - /* ring base address */ -@@ -479,12 +501,12 @@ static int safexcel_hw_setup_cdesc_rings - writel(upper_32_bits(priv->ring[i].cdr.base_dma), - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI); - -- writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.cd_offset << 16) | -- priv->config.cd_size, -+ writel(EIP197_xDR_DESC_MODE_64BIT | EIP197_CDR_DESC_MODE_ADCP | -+ (priv->config.cd_offset << 14) | priv->config.cd_size, - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_DESC_SIZE); - writel(((cd_fetch_cnt * - (cd_size_rnd << priv->hwconfig.hwdataw)) << 16) | -- (cd_fetch_cnt * priv->config.cd_offset), -+ (cd_fetch_cnt * (priv->config.cd_offset / sizeof(u32))), - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_CFG); - - /* Configure DMA tx control */ -@@ -527,13 +549,13 @@ static int safexcel_hw_setup_rdesc_rings - writel(upper_32_bits(priv->ring[i].rdr.base_dma), - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_BASE_ADDR_HI); - -- writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.rd_offset << 16) | -+ writel(EIP197_xDR_DESC_MODE_64BIT | (priv->config.rd_offset << 14) | - priv->config.rd_size, - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_DESC_SIZE); - - writel(((rd_fetch_cnt * - (rd_size_rnd << priv->hwconfig.hwdataw)) << 16) | -- (rd_fetch_cnt * priv->config.rd_offset), -+ (rd_fetch_cnt * (priv->config.rd_offset / sizeof(u32))), - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_CFG); - - /* Configure DMA tx control */ -@@ -559,7 +581,7 @@ static int safexcel_hw_setup_rdesc_rings - static int safexcel_hw_init(struct safexcel_crypto_priv *priv) - { - u32 val; -- int i, ret, pe; -+ int i, ret, pe, opbuflo, opbufhi; - - dev_dbg(priv->dev, "HW init: using %d pipe(s) and %d ring(s)\n", - priv->config.pes, priv->config.rings); -@@ -595,8 +617,8 @@ static int safexcel_hw_init(struct safex - writel(EIP197_DxE_THR_CTRL_RESET_PE, - EIP197_HIA_DFE_THR(priv) + EIP197_HIA_DFE_THR_CTRL(pe)); - -- if (priv->flags & SAFEXCEL_HW_EIP197) -- /* Reset HIA input interface arbiter (EIP197 only) */ -+ if (priv->flags & EIP197_PE_ARB) -+ /* Reset HIA input interface arbiter (if present) */ - writel(EIP197_HIA_RA_PE_CTRL_RESET, - EIP197_HIA_AIC(priv) + EIP197_HIA_RA_PE_CTRL(pe)); - -@@ -639,9 +661,16 @@ static int safexcel_hw_init(struct safex - ; - - /* DMA transfer size to use */ -+ if (priv->hwconfig.hwnumpes > 4) { -+ opbuflo = 9; -+ opbufhi = 10; -+ } else { -+ opbuflo = 7; -+ opbufhi = 8; -+ } - val = EIP197_HIA_DSE_CFG_DIS_DEBUG; -- val |= EIP197_HIA_DxE_CFG_MIN_DATA_SIZE(7) | -- EIP197_HIA_DxE_CFG_MAX_DATA_SIZE(8); -+ val |= EIP197_HIA_DxE_CFG_MIN_DATA_SIZE(opbuflo) | -+ EIP197_HIA_DxE_CFG_MAX_DATA_SIZE(opbufhi); - val |= EIP197_HIA_DxE_CFG_DATA_CACHE_CTRL(WR_CACHE_3BITS); - val |= EIP197_HIA_DSE_CFG_ALWAYS_BUFFERABLE; - /* FIXME: instability issues can occur for EIP97 but disabling -@@ -655,8 +684,8 @@ static int safexcel_hw_init(struct safex - writel(0, EIP197_HIA_DSE_THR(priv) + EIP197_HIA_DSE_THR_CTRL(pe)); - - /* Configure the procesing engine thresholds */ -- writel(EIP197_PE_OUT_DBUF_THRES_MIN(7) | -- EIP197_PE_OUT_DBUF_THRES_MAX(8), -+ writel(EIP197_PE_OUT_DBUF_THRES_MIN(opbuflo) | -+ EIP197_PE_OUT_DBUF_THRES_MAX(opbufhi), - EIP197_PE(priv) + EIP197_PE_OUT_DBUF_THRES(pe)); - - /* Processing Engine configuration */ -@@ -696,7 +725,7 @@ static int safexcel_hw_init(struct safex - writel(0, - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_PROC_PNTR); - -- writel((EIP197_DEFAULT_RING_SIZE * priv->config.cd_offset) << 2, -+ writel((EIP197_DEFAULT_RING_SIZE * priv->config.cd_offset), - EIP197_HIA_CDR(priv, i) + EIP197_HIA_xDR_RING_SIZE); - } - -@@ -719,7 +748,7 @@ static int safexcel_hw_init(struct safex - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_PROC_PNTR); - - /* Ring size */ -- writel((EIP197_DEFAULT_RING_SIZE * priv->config.rd_offset) << 2, -+ writel((EIP197_DEFAULT_RING_SIZE * priv->config.rd_offset), - EIP197_HIA_RDR(priv, i) + EIP197_HIA_xDR_RING_SIZE); - } - -@@ -736,19 +765,28 @@ static int safexcel_hw_init(struct safex - /* Clear any HIA interrupt */ - writel(GENMASK(30, 20), EIP197_HIA_AIC_G(priv) + EIP197_HIA_AIC_G_ACK); - -- if (priv->flags & SAFEXCEL_HW_EIP197) { -- eip197_trc_cache_init(priv); -- priv->flags |= EIP197_TRC_CACHE; -+ if (priv->flags & EIP197_SIMPLE_TRC) { -+ writel(EIP197_STRC_CONFIG_INIT | -+ EIP197_STRC_CONFIG_LARGE_REC(EIP197_CS_TRC_REC_WC) | -+ EIP197_STRC_CONFIG_SMALL_REC(EIP197_CS_TRC_REC_WC), -+ priv->base + EIP197_STRC_CONFIG); -+ writel(EIP197_PE_EIP96_TOKEN_CTRL2_CTX_DONE, -+ EIP197_PE(priv) + EIP197_PE_EIP96_TOKEN_CTRL2(0)); -+ } else if (priv->flags & SAFEXCEL_HW_EIP197) { -+ ret = eip197_trc_cache_init(priv); -+ if (ret) -+ return ret; -+ } - -+ if (priv->flags & EIP197_ICE) { - ret = eip197_load_firmwares(priv); - if (ret) - return ret; - } - -- safexcel_hw_setup_cdesc_rings(priv); -- safexcel_hw_setup_rdesc_rings(priv); -- -- return 0; -+ return safexcel_hw_setup_cdesc_rings(priv) ?: -+ safexcel_hw_setup_rdesc_rings(priv) ?: -+ 0; - } - - /* Called with ring's lock taken */ -@@ -836,20 +874,24 @@ finalize: - spin_unlock_bh(&priv->ring[ring].lock); - - /* let the RDR know we have pending descriptors */ -- writel((rdesc * priv->config.rd_offset) << 2, -+ writel((rdesc * priv->config.rd_offset), - EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PREP_COUNT); - - /* let the CDR know we have pending descriptors */ -- writel((cdesc * priv->config.cd_offset) << 2, -+ writel((cdesc * priv->config.cd_offset), - EIP197_HIA_CDR(priv, ring) + EIP197_HIA_xDR_PREP_COUNT); - } - - inline int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv, -- struct safexcel_result_desc *rdesc) -+ void *rdp) - { -- if (likely((!rdesc->descriptor_overflow) && -- (!rdesc->buffer_overflow) && -- (!rdesc->result_data.error_code))) -+ struct safexcel_result_desc *rdesc = rdp; -+ struct result_data_desc *result_data = rdp + priv->config.res_offset; -+ -+ if (likely((!rdesc->last_seg) || /* Rest only valid if last seg! */ -+ ((!rdesc->descriptor_overflow) && -+ (!rdesc->buffer_overflow) && -+ (!result_data->error_code)))) - return 0; - - if (rdesc->descriptor_overflow) -@@ -858,13 +900,14 @@ inline int safexcel_rdesc_check_errors(s - if (rdesc->buffer_overflow) - dev_err(priv->dev, "Buffer overflow detected"); - -- if (rdesc->result_data.error_code & 0x4066) { -+ if (result_data->error_code & 0x4066) { - /* Fatal error (bits 1,2,5,6 & 14) */ - dev_err(priv->dev, - "result descriptor error (%x)", -- rdesc->result_data.error_code); -+ result_data->error_code); -+ - return -EIO; -- } else if (rdesc->result_data.error_code & -+ } else if (result_data->error_code & - (BIT(7) | BIT(4) | BIT(3) | BIT(0))) { - /* - * Give priority over authentication fails: -@@ -872,7 +915,7 @@ inline int safexcel_rdesc_check_errors(s - * something wrong with the input! - */ - return -EINVAL; -- } else if (rdesc->result_data.error_code & BIT(9)) { -+ } else if (result_data->error_code & BIT(9)) { - /* Authentication failed */ - return -EBADMSG; - } -@@ -931,16 +974,18 @@ int safexcel_invalidate_cache(struct cry - { - struct safexcel_command_desc *cdesc; - struct safexcel_result_desc *rdesc; -+ struct safexcel_token *dmmy; - int ret = 0; - - /* Prepare command descriptor */ -- cdesc = safexcel_add_cdesc(priv, ring, true, true, 0, 0, 0, ctxr_dma); -+ cdesc = safexcel_add_cdesc(priv, ring, true, true, 0, 0, 0, ctxr_dma, -+ &dmmy); - if (IS_ERR(cdesc)) - return PTR_ERR(cdesc); - - cdesc->control_data.type = EIP197_TYPE_EXTENDED; - cdesc->control_data.options = 0; -- cdesc->control_data.refresh = 0; -+ cdesc->control_data.context_lo &= ~EIP197_CONTEXT_SIZE_MASK; - cdesc->control_data.control0 = CONTEXT_CONTROL_INV_TR; - - /* Prepare result descriptor */ -@@ -1003,7 +1048,7 @@ handle_results: - acknowledge: - if (i) - writel(EIP197_xDR_PROC_xD_PKT(i) | -- EIP197_xDR_PROC_xD_COUNT(tot_descs * priv->config.rd_offset), -+ (tot_descs * priv->config.rd_offset), - EIP197_HIA_RDR(priv, ring) + EIP197_HIA_xDR_PROC_COUNT); - - /* If the number of requests overflowed the counter, try to proceed more -@@ -1171,6 +1216,44 @@ static struct safexcel_alg_template *saf - &safexcel_alg_xts_aes, - &safexcel_alg_gcm, - &safexcel_alg_ccm, -+ &safexcel_alg_crc32, -+ &safexcel_alg_cbcmac, -+ &safexcel_alg_xcbcmac, -+ &safexcel_alg_cmac, -+ &safexcel_alg_chacha20, -+ &safexcel_alg_chachapoly, -+ &safexcel_alg_chachapoly_esp, -+ &safexcel_alg_sm3, -+ &safexcel_alg_hmac_sm3, -+ &safexcel_alg_ecb_sm4, -+ &safexcel_alg_cbc_sm4, -+ &safexcel_alg_ofb_sm4, -+ &safexcel_alg_cfb_sm4, -+ &safexcel_alg_ctr_sm4, -+ &safexcel_alg_authenc_hmac_sha1_cbc_sm4, -+ &safexcel_alg_authenc_hmac_sm3_cbc_sm4, -+ &safexcel_alg_authenc_hmac_sha1_ctr_sm4, -+ &safexcel_alg_authenc_hmac_sm3_ctr_sm4, -+ &safexcel_alg_sha3_224, -+ &safexcel_alg_sha3_256, -+ &safexcel_alg_sha3_384, -+ &safexcel_alg_sha3_512, -+ &safexcel_alg_hmac_sha3_224, -+ &safexcel_alg_hmac_sha3_256, -+ &safexcel_alg_hmac_sha3_384, -+ &safexcel_alg_hmac_sha3_512, -+ &safexcel_alg_authenc_hmac_sha1_cbc_des, -+ &safexcel_alg_authenc_hmac_sha256_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha224_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha512_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha384_cbc_des3_ede, -+ &safexcel_alg_authenc_hmac_sha256_cbc_des, -+ &safexcel_alg_authenc_hmac_sha224_cbc_des, -+ &safexcel_alg_authenc_hmac_sha512_cbc_des, -+ &safexcel_alg_authenc_hmac_sha384_cbc_des, -+ &safexcel_alg_rfc4106_gcm, -+ &safexcel_alg_rfc4543_gcm, -+ &safexcel_alg_rfc4309_ccm, - }; - - static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv) -@@ -1240,30 +1323,30 @@ static void safexcel_unregister_algorith - - static void safexcel_configure(struct safexcel_crypto_priv *priv) - { -- u32 val, mask = 0; -- -- val = readl(EIP197_HIA_AIC_G(priv) + EIP197_HIA_OPTIONS); -- -- /* Read number of PEs from the engine */ -- if (priv->flags & SAFEXCEL_HW_EIP197) -- /* Wider field width for all EIP197 type engines */ -- mask = EIP197_N_PES_MASK; -- else -- /* Narrow field width for EIP97 type engine */ -- mask = EIP97_N_PES_MASK; -- -- priv->config.pes = (val >> EIP197_N_PES_OFFSET) & mask; -+ u32 mask = BIT(priv->hwconfig.hwdataw) - 1; - -- priv->config.rings = min_t(u32, val & GENMASK(3, 0), max_rings); -+ priv->config.pes = priv->hwconfig.hwnumpes; -+ priv->config.rings = min_t(u32, priv->hwconfig.hwnumrings, max_rings); -+ /* Cannot currently support more rings than we have ring AICs! */ -+ priv->config.rings = min_t(u32, priv->config.rings, -+ priv->hwconfig.hwnumraic); - -- val = (val & GENMASK(27, 25)) >> 25; -- mask = BIT(val) - 1; -- -- priv->config.cd_size = (sizeof(struct safexcel_command_desc) / sizeof(u32)); -+ priv->config.cd_size = EIP197_CD64_FETCH_SIZE; - priv->config.cd_offset = (priv->config.cd_size + mask) & ~mask; -+ priv->config.cdsh_offset = (EIP197_MAX_TOKENS + mask) & ~mask; - -- priv->config.rd_size = (sizeof(struct safexcel_result_desc) / sizeof(u32)); -+ /* res token is behind the descr, but ofs must be rounded to buswdth */ -+ priv->config.res_offset = (EIP197_RD64_FETCH_SIZE + mask) & ~mask; -+ /* now the size of the descr is this 1st part plus the result struct */ -+ priv->config.rd_size = priv->config.res_offset + -+ EIP197_RD64_RESULT_SIZE; - priv->config.rd_offset = (priv->config.rd_size + mask) & ~mask; -+ -+ /* convert dwords to bytes */ -+ priv->config.cd_offset *= sizeof(u32); -+ priv->config.cdsh_offset *= sizeof(u32); -+ priv->config.rd_offset *= sizeof(u32); -+ priv->config.res_offset *= sizeof(u32); - } - - static void safexcel_init_register_offsets(struct safexcel_crypto_priv *priv) -@@ -1309,7 +1392,7 @@ static int safexcel_probe_generic(void * - int is_pci_dev) - { - struct device *dev = priv->dev; -- u32 peid, version, mask, val, hiaopt; -+ u32 peid, version, mask, val, hiaopt, hwopt, peopt; - int i, ret, hwctg; - - priv->context_pool = dmam_pool_create("safexcel-context", dev, -@@ -1371,13 +1454,16 @@ static int safexcel_probe_generic(void * - */ - version = readl(EIP197_GLOBAL(priv) + EIP197_VERSION); - if (((priv->flags & SAFEXCEL_HW_EIP197) && -- (EIP197_REG_LO16(version) != EIP197_VERSION_LE)) || -+ (EIP197_REG_LO16(version) != EIP197_VERSION_LE) && -+ (EIP197_REG_LO16(version) != EIP196_VERSION_LE)) || - ((!(priv->flags & SAFEXCEL_HW_EIP197) && - (EIP197_REG_LO16(version) != EIP97_VERSION_LE)))) { - /* - * We did not find the device that matched our initial probing - * (or our initial probing failed) Report appropriate error. - */ -+ dev_err(priv->dev, "Probing for EIP97/EIP19x failed - no such device (read %08x)\n", -+ version); - return -ENODEV; - } - -@@ -1385,6 +1471,14 @@ static int safexcel_probe_generic(void * - hwctg = version >> 28; - peid = version & 255; - -+ /* Detect EIP206 processing pipe */ -+ version = readl(EIP197_PE(priv) + + EIP197_PE_VERSION(0)); -+ if (EIP197_REG_LO16(version) != EIP206_VERSION_LE) { -+ dev_err(priv->dev, "EIP%d: EIP206 not detected\n", peid); -+ return -ENODEV; -+ } -+ priv->hwconfig.ppver = EIP197_VERSION_MASK(version); -+ - /* Detect EIP96 packet engine and version */ - version = readl(EIP197_PE(priv) + EIP197_PE_EIP96_VERSION(0)); - if (EIP197_REG_LO16(version) != EIP96_VERSION_LE) { -@@ -1393,10 +1487,13 @@ static int safexcel_probe_generic(void * - } - priv->hwconfig.pever = EIP197_VERSION_MASK(version); - -+ hwopt = readl(EIP197_GLOBAL(priv) + EIP197_OPTIONS); - hiaopt = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_OPTIONS); - - if (priv->flags & SAFEXCEL_HW_EIP197) { - /* EIP197 */ -+ peopt = readl(EIP197_PE(priv) + EIP197_PE_OPTIONS(0)); -+ - priv->hwconfig.hwdataw = (hiaopt >> EIP197_HWDATAW_OFFSET) & - EIP197_HWDATAW_MASK; - priv->hwconfig.hwcfsize = ((hiaopt >> EIP197_CFSIZE_OFFSET) & -@@ -1405,6 +1502,19 @@ static int safexcel_probe_generic(void * - priv->hwconfig.hwrfsize = ((hiaopt >> EIP197_RFSIZE_OFFSET) & - EIP197_RFSIZE_MASK) + - EIP197_RFSIZE_ADJUST; -+ priv->hwconfig.hwnumpes = (hiaopt >> EIP197_N_PES_OFFSET) & -+ EIP197_N_PES_MASK; -+ priv->hwconfig.hwnumrings = (hiaopt >> EIP197_N_RINGS_OFFSET) & -+ EIP197_N_RINGS_MASK; -+ if (hiaopt & EIP197_HIA_OPT_HAS_PE_ARB) -+ priv->flags |= EIP197_PE_ARB; -+ if (EIP206_OPT_ICE_TYPE(peopt) == 1) -+ priv->flags |= EIP197_ICE; -+ /* If not a full TRC, then assume simple TRC */ -+ if (!(hwopt & EIP197_OPT_HAS_TRC)) -+ priv->flags |= EIP197_SIMPLE_TRC; -+ /* EIP197 always has SOME form of TRC */ -+ priv->flags |= EIP197_TRC_CACHE; - } else { - /* EIP97 */ - priv->hwconfig.hwdataw = (hiaopt >> EIP197_HWDATAW_OFFSET) & -@@ -1413,6 +1523,23 @@ static int safexcel_probe_generic(void * - EIP97_CFSIZE_MASK; - priv->hwconfig.hwrfsize = (hiaopt >> EIP97_RFSIZE_OFFSET) & - EIP97_RFSIZE_MASK; -+ priv->hwconfig.hwnumpes = 1; /* by definition */ -+ priv->hwconfig.hwnumrings = (hiaopt >> EIP197_N_RINGS_OFFSET) & -+ EIP197_N_RINGS_MASK; -+ } -+ -+ /* Scan for ring AIC's */ -+ for (i = 0; i < EIP197_MAX_RING_AIC; i++) { -+ version = readl(EIP197_HIA_AIC_R(priv) + -+ EIP197_HIA_AIC_R_VERSION(i)); -+ if (EIP197_REG_LO16(version) != EIP201_VERSION_LE) -+ break; -+ } -+ priv->hwconfig.hwnumraic = i; -+ /* Low-end EIP196 may not have any ring AIC's ... */ -+ if (!priv->hwconfig.hwnumraic) { -+ dev_err(priv->dev, "No ring interrupt controller present!\n"); -+ return -ENODEV; - } - - /* Get supported algorithms from EIP96 transform engine */ -@@ -1420,10 +1547,12 @@ static int safexcel_probe_generic(void * - EIP197_PE_EIP96_OPTIONS(0)); - - /* Print single info line describing what we just detected */ -- dev_info(priv->dev, "EIP%d:%x(%d)-HIA:%x(%d,%d,%d),PE:%x,alg:%08x\n", -- peid, priv->hwconfig.hwver, hwctg, priv->hwconfig.hiaver, -- priv->hwconfig.hwdataw, priv->hwconfig.hwcfsize, -- priv->hwconfig.hwrfsize, priv->hwconfig.pever, -+ dev_info(priv->dev, "EIP%d:%x(%d,%d,%d,%d)-HIA:%x(%d,%d,%d),PE:%x/%x,alg:%08x\n", -+ peid, priv->hwconfig.hwver, hwctg, priv->hwconfig.hwnumpes, -+ priv->hwconfig.hwnumrings, priv->hwconfig.hwnumraic, -+ priv->hwconfig.hiaver, priv->hwconfig.hwdataw, -+ priv->hwconfig.hwcfsize, priv->hwconfig.hwrfsize, -+ priv->hwconfig.ppver, priv->hwconfig.pever, - priv->hwconfig.algo_flags); - - safexcel_configure(priv); -@@ -1547,7 +1676,6 @@ static void safexcel_hw_reset_rings(stru - } - } - --#if IS_ENABLED(CONFIG_OF) - /* for Device Tree platform driver */ - - static int safexcel_probe(struct platform_device *pdev) -@@ -1625,6 +1753,7 @@ static int safexcel_remove(struct platfo - safexcel_unregister_algorithms(priv); - safexcel_hw_reset_rings(priv); - -+ clk_disable_unprepare(priv->reg_clk); - clk_disable_unprepare(priv->clk); - - for (i = 0; i < priv->config.rings; i++) -@@ -1666,9 +1795,7 @@ static struct platform_driver crypto_sa - .of_match_table = safexcel_of_match_table, - }, - }; --#endif - --#if IS_ENABLED(CONFIG_PCI) - /* PCIE devices - i.e. Inside Secure development boards */ - - static int safexcel_pci_probe(struct pci_dev *pdev, -@@ -1759,7 +1886,7 @@ static int safexcel_pci_probe(struct pci - return rc; - } - --void safexcel_pci_remove(struct pci_dev *pdev) -+static void safexcel_pci_remove(struct pci_dev *pdev) - { - struct safexcel_crypto_priv *priv = pci_get_drvdata(pdev); - int i; -@@ -1789,54 +1916,32 @@ static struct pci_driver safexcel_pci_dr - .probe = safexcel_pci_probe, - .remove = safexcel_pci_remove, - }; --#endif -- --/* Unfortunately, we have to resort to global variables here */ --#if IS_ENABLED(CONFIG_PCI) --int pcireg_rc = -EINVAL; /* Default safe value */ --#endif --#if IS_ENABLED(CONFIG_OF) --int ofreg_rc = -EINVAL; /* Default safe value */ --#endif - - static int __init safexcel_init(void) - { --#if IS_ENABLED(CONFIG_PCI) -+ int ret; -+ - /* Register PCI driver */ -- pcireg_rc = pci_register_driver(&safexcel_pci_driver); --#endif -+ ret = pci_register_driver(&safexcel_pci_driver); - --#if IS_ENABLED(CONFIG_OF) - /* Register platform driver */ -- ofreg_rc = platform_driver_register(&crypto_safexcel); -- #if IS_ENABLED(CONFIG_PCI) -- /* Return success if either PCI or OF registered OK */ -- return pcireg_rc ? ofreg_rc : 0; -- #else -- return ofreg_rc; -- #endif --#else -- #if IS_ENABLED(CONFIG_PCI) -- return pcireg_rc; -- #else -- return -EINVAL; -- #endif --#endif -+ if (IS_ENABLED(CONFIG_OF) && !ret) { -+ ret = platform_driver_register(&crypto_safexcel); -+ if (ret) -+ pci_unregister_driver(&safexcel_pci_driver); -+ } -+ -+ return ret; - } - - static void __exit safexcel_exit(void) - { --#if IS_ENABLED(CONFIG_OF) - /* Unregister platform driver */ -- if (!ofreg_rc) -+ if (IS_ENABLED(CONFIG_OF)) - platform_driver_unregister(&crypto_safexcel); --#endif - --#if IS_ENABLED(CONFIG_PCI) - /* Unregister PCI driver if successfully registered before */ -- if (!pcireg_rc) -- pci_unregister_driver(&safexcel_pci_driver); --#endif -+ pci_unregister_driver(&safexcel_pci_driver); - } - - module_init(safexcel_init); ---- a/drivers/crypto/inside-secure/safexcel_cipher.c -+++ b/drivers/crypto/inside-secure/safexcel_cipher.c -@@ -5,18 +5,22 @@ - * Antoine Tenart <antoine.tenart@free-electrons.com> - */ - -+#include <asm/unaligned.h> - #include <linux/device.h> - #include <linux/dma-mapping.h> - #include <linux/dmapool.h> -- - #include <crypto/aead.h> - #include <crypto/aes.h> - #include <crypto/authenc.h> -+#include <crypto/chacha.h> - #include <crypto/ctr.h> - #include <crypto/internal/des.h> - #include <crypto/gcm.h> - #include <crypto/ghash.h> -+#include <crypto/poly1305.h> - #include <crypto/sha.h> -+#include <crypto/sm3.h> -+#include <crypto/sm4.h> - #include <crypto/xts.h> - #include <crypto/skcipher.h> - #include <crypto/internal/aead.h> -@@ -33,6 +37,8 @@ enum safexcel_cipher_alg { - SAFEXCEL_DES, - SAFEXCEL_3DES, - SAFEXCEL_AES, -+ SAFEXCEL_CHACHA20, -+ SAFEXCEL_SM4, - }; - - struct safexcel_cipher_ctx { -@@ -41,8 +47,12 @@ struct safexcel_cipher_ctx { - - u32 mode; - enum safexcel_cipher_alg alg; -- bool aead; -- int xcm; /* 0=authenc, 1=GCM, 2 reserved for CCM */ -+ u8 aead; /* !=0=AEAD, 2=IPSec ESP AEAD, 3=IPsec ESP GMAC */ -+ u8 xcm; /* 0=authenc, 1=GCM, 2 reserved for CCM */ -+ u8 aadskip; -+ u8 blocksz; -+ u32 ivmask; -+ u32 ctrinit; - - __le32 key[16]; - u32 nonce; -@@ -51,10 +61,11 @@ struct safexcel_cipher_ctx { - /* All the below is AEAD specific */ - u32 hash_alg; - u32 state_sz; -- u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; -- u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; -+ __be32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; -+ __be32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; - - struct crypto_cipher *hkaes; -+ struct crypto_aead *fback; - }; - - struct safexcel_cipher_req { -@@ -65,206 +76,298 @@ struct safexcel_cipher_req { - int nr_src, nr_dst; - }; - --static void safexcel_cipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, -- struct safexcel_command_desc *cdesc) -+static int safexcel_skcipher_iv(struct safexcel_cipher_ctx *ctx, u8 *iv, -+ struct safexcel_command_desc *cdesc) - { -- u32 block_sz = 0; -- - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { - cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- - /* 32 bit nonce */ - cdesc->control_data.token[0] = ctx->nonce; - /* 64 bit IV part */ - memcpy(&cdesc->control_data.token[1], iv, 8); -- /* 32 bit counter, start at 1 (big endian!) */ -- cdesc->control_data.token[3] = cpu_to_be32(1); -- -- return; -- } else if (ctx->xcm == EIP197_XCM_MODE_GCM) { -- cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- -- /* 96 bit IV part */ -- memcpy(&cdesc->control_data.token[0], iv, 12); -- /* 32 bit counter, start at 1 (big endian!) */ -- cdesc->control_data.token[3] = cpu_to_be32(1); -- -- return; -- } else if (ctx->xcm == EIP197_XCM_MODE_CCM) { -+ /* 32 bit counter, start at 0 or 1 (big endian!) */ -+ cdesc->control_data.token[3] = -+ (__force u32)cpu_to_be32(ctx->ctrinit); -+ return 4; -+ } -+ if (ctx->alg == SAFEXCEL_CHACHA20) { - cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- -- /* Variable length IV part */ -- memcpy(&cdesc->control_data.token[0], iv, 15 - iv[0]); -- /* Start variable length counter at 0 */ -- memset((u8 *)&cdesc->control_data.token[0] + 15 - iv[0], -- 0, iv[0] + 1); -- -- return; -+ /* 96 bit nonce part */ -+ memcpy(&cdesc->control_data.token[0], &iv[4], 12); -+ /* 32 bit counter */ -+ cdesc->control_data.token[3] = *(u32 *)iv; -+ return 4; - } - -- if (ctx->mode != CONTEXT_CONTROL_CRYPTO_MODE_ECB) { -- switch (ctx->alg) { -- case SAFEXCEL_DES: -- block_sz = DES_BLOCK_SIZE; -- cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; -- break; -- case SAFEXCEL_3DES: -- block_sz = DES3_EDE_BLOCK_SIZE; -- cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; -- break; -- case SAFEXCEL_AES: -- block_sz = AES_BLOCK_SIZE; -- cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; -- break; -- } -- memcpy(cdesc->control_data.token, iv, block_sz); -- } -+ cdesc->control_data.options |= ctx->ivmask; -+ memcpy(cdesc->control_data.token, iv, ctx->blocksz); -+ return ctx->blocksz / sizeof(u32); - } - - static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, - struct safexcel_command_desc *cdesc, -+ struct safexcel_token *atoken, - u32 length) - { - struct safexcel_token *token; -+ int ivlen; - -- safexcel_cipher_token(ctx, iv, cdesc); -- -- /* skip over worst case IV of 4 dwords, no need to be exact */ -- token = (struct safexcel_token *)(cdesc->control_data.token + 4); -+ ivlen = safexcel_skcipher_iv(ctx, iv, cdesc); -+ if (ivlen == 4) { -+ /* No space in cdesc, instruction moves to atoken */ -+ cdesc->additional_cdata_size = 1; -+ token = atoken; -+ } else { -+ /* Everything fits in cdesc */ -+ token = (struct safexcel_token *)(cdesc->control_data.token + 2); -+ /* Need to pad with NOP */ -+ eip197_noop_token(&token[1]); -+ } -+ -+ token->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ token->packet_length = length; -+ token->stat = EIP197_TOKEN_STAT_LAST_PACKET | -+ EIP197_TOKEN_STAT_LAST_HASH; -+ token->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_CRYPTO | -+ EIP197_TOKEN_INS_TYPE_OUTPUT; -+} - -- token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; -- token[0].packet_length = length; -- token[0].stat = EIP197_TOKEN_STAT_LAST_PACKET | -- EIP197_TOKEN_STAT_LAST_HASH; -- token[0].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_CRYPTO | -- EIP197_TOKEN_INS_TYPE_OUTPUT; -+static void safexcel_aead_iv(struct safexcel_cipher_ctx *ctx, u8 *iv, -+ struct safexcel_command_desc *cdesc) -+{ -+ if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD || -+ ctx->aead & EIP197_AEAD_TYPE_IPSEC_ESP) { /* _ESP and _ESP_GMAC */ -+ /* 32 bit nonce */ -+ cdesc->control_data.token[0] = ctx->nonce; -+ /* 64 bit IV part */ -+ memcpy(&cdesc->control_data.token[1], iv, 8); -+ /* 32 bit counter, start at 0 or 1 (big endian!) */ -+ cdesc->control_data.token[3] = -+ (__force u32)cpu_to_be32(ctx->ctrinit); -+ return; -+ } -+ if (ctx->xcm == EIP197_XCM_MODE_GCM || ctx->alg == SAFEXCEL_CHACHA20) { -+ /* 96 bit IV part */ -+ memcpy(&cdesc->control_data.token[0], iv, 12); -+ /* 32 bit counter, start at 0 or 1 (big endian!) */ -+ cdesc->control_data.token[3] = -+ (__force u32)cpu_to_be32(ctx->ctrinit); -+ return; -+ } -+ /* CBC */ -+ memcpy(cdesc->control_data.token, iv, ctx->blocksz); - } - - static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, - struct safexcel_command_desc *cdesc, -+ struct safexcel_token *atoken, - enum safexcel_cipher_direction direction, - u32 cryptlen, u32 assoclen, u32 digestsize) - { -- struct safexcel_token *token; -+ struct safexcel_token *aadref; -+ int atoksize = 2; /* Start with minimum size */ -+ int assocadj = assoclen - ctx->aadskip, aadalign; - -- safexcel_cipher_token(ctx, iv, cdesc); -+ /* Always 4 dwords of embedded IV for AEAD modes */ -+ cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; - -- if (direction == SAFEXCEL_ENCRYPT) { -- /* align end of instruction sequence to end of token */ -- token = (struct safexcel_token *)(cdesc->control_data.token + -- EIP197_MAX_TOKENS - 13); -- -- token[12].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[12].packet_length = digestsize; -- token[12].stat = EIP197_TOKEN_STAT_LAST_HASH | -- EIP197_TOKEN_STAT_LAST_PACKET; -- token[12].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -- EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -- } else { -+ if (direction == SAFEXCEL_DECRYPT) - cryptlen -= digestsize; - -- /* align end of instruction sequence to end of token */ -- token = (struct safexcel_token *)(cdesc->control_data.token + -- EIP197_MAX_TOKENS - 14); -- -- token[12].opcode = EIP197_TOKEN_OPCODE_RETRIEVE; -- token[12].packet_length = digestsize; -- token[12].stat = EIP197_TOKEN_STAT_LAST_HASH | -- EIP197_TOKEN_STAT_LAST_PACKET; -- token[12].instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -- -- token[13].opcode = EIP197_TOKEN_OPCODE_VERIFY; -- token[13].packet_length = digestsize | -- EIP197_TOKEN_HASH_RESULT_VERIFY; -- token[13].stat = EIP197_TOKEN_STAT_LAST_HASH | -- EIP197_TOKEN_STAT_LAST_PACKET; -- token[13].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; -- } -- -- token[6].opcode = EIP197_TOKEN_OPCODE_DIRECTION; -- token[6].packet_length = assoclen; -- -- if (likely(cryptlen)) { -- token[6].instructions = EIP197_TOKEN_INS_TYPE_HASH; -- -- token[10].opcode = EIP197_TOKEN_OPCODE_DIRECTION; -- token[10].packet_length = cryptlen; -- token[10].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[10].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_CRYPTO | -- EIP197_TOKEN_INS_TYPE_HASH | -- EIP197_TOKEN_INS_TYPE_OUTPUT; -- } else if (ctx->xcm != EIP197_XCM_MODE_CCM) { -- token[6].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[6].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_HASH; -- } -- -- if (!ctx->xcm) -- return; -- -- token[8].opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES; -- token[8].packet_length = 0; -- token[8].instructions = AES_BLOCK_SIZE; -- -- token[9].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[9].packet_length = AES_BLOCK_SIZE; -- token[9].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -- EIP197_TOKEN_INS_TYPE_CRYPTO; -- -- if (ctx->xcm == EIP197_XCM_MODE_GCM) { -- token[6].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_HASH; -- } else { -- u8 *cbcmaciv = (u8 *)&token[1]; -- u32 *aadlen = (u32 *)&token[5]; -- -+ if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM)) { - /* Construct IV block B0 for the CBC-MAC */ -- token[0].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[0].packet_length = AES_BLOCK_SIZE + -- ((assoclen > 0) << 1); -- token[0].instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN | -- EIP197_TOKEN_INS_TYPE_HASH; -- /* Variable length IV part */ -- memcpy(cbcmaciv, iv, 15 - iv[0]); -- /* fixup flags byte */ -- cbcmaciv[0] |= ((assoclen > 0) << 6) | ((digestsize - 2) << 2); -- /* Clear upper bytes of variable message length to 0 */ -- memset(cbcmaciv + 15 - iv[0], 0, iv[0] - 1); -- /* insert lower 2 bytes of message length */ -- cbcmaciv[14] = cryptlen >> 8; -- cbcmaciv[15] = cryptlen & 255; -- -- if (assoclen) { -- *aadlen = cpu_to_le32(cpu_to_be16(assoclen)); -- assoclen += 2; -+ u8 *final_iv = (u8 *)cdesc->control_data.token; -+ u8 *cbcmaciv = (u8 *)&atoken[1]; -+ __le32 *aadlen = (__le32 *)&atoken[5]; -+ -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) { -+ /* Length + nonce */ -+ cdesc->control_data.token[0] = ctx->nonce; -+ /* Fixup flags byte */ -+ *(__le32 *)cbcmaciv = -+ cpu_to_le32(ctx->nonce | -+ ((assocadj > 0) << 6) | -+ ((digestsize - 2) << 2)); -+ /* 64 bit IV part */ -+ memcpy(&cdesc->control_data.token[1], iv, 8); -+ memcpy(cbcmaciv + 4, iv, 8); -+ /* Start counter at 0 */ -+ cdesc->control_data.token[3] = 0; -+ /* Message length */ -+ *(__be32 *)(cbcmaciv + 12) = cpu_to_be32(cryptlen); -+ } else { -+ /* Variable length IV part */ -+ memcpy(final_iv, iv, 15 - iv[0]); -+ memcpy(cbcmaciv, iv, 15 - iv[0]); -+ /* Start variable length counter at 0 */ -+ memset(final_iv + 15 - iv[0], 0, iv[0] + 1); -+ memset(cbcmaciv + 15 - iv[0], 0, iv[0] - 1); -+ /* fixup flags byte */ -+ cbcmaciv[0] |= ((assocadj > 0) << 6) | -+ ((digestsize - 2) << 2); -+ /* insert lower 2 bytes of message length */ -+ cbcmaciv[14] = cryptlen >> 8; -+ cbcmaciv[15] = cryptlen & 255; -+ } -+ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = AES_BLOCK_SIZE + -+ ((assocadj > 0) << 1); -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_ORIGIN_TOKEN | -+ EIP197_TOKEN_INS_TYPE_HASH; -+ -+ if (likely(assocadj)) { -+ *aadlen = cpu_to_le32((assocadj >> 8) | -+ (assocadj & 255) << 8); -+ atoken += 6; -+ atoksize += 7; -+ } else { -+ atoken += 5; -+ atoksize += 6; - } - -- token[6].instructions = EIP197_TOKEN_INS_TYPE_HASH; -- -- /* Align AAD data towards hash engine */ -- token[7].opcode = EIP197_TOKEN_OPCODE_INSERT; -- assoclen &= 15; -- token[7].packet_length = assoclen ? 16 - assoclen : 0; -- -+ /* Process AAD data */ -+ aadref = atoken; -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = assocadj; -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ atoken++; -+ -+ /* For CCM only, align AAD data towards hash engine */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ aadalign = (assocadj + 2) & 15; -+ atoken->packet_length = assocadj && aadalign ? -+ 16 - aadalign : -+ 0; - if (likely(cryptlen)) { -- token[7].instructions = EIP197_TOKEN_INS_TYPE_HASH; -- -- /* Align crypto data towards hash engine */ -- token[10].stat = 0; -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ } else { -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_HASH; -+ } -+ } else { -+ safexcel_aead_iv(ctx, iv, cdesc); - -- token[11].opcode = EIP197_TOKEN_OPCODE_INSERT; -- cryptlen &= 15; -- token[11].packet_length = cryptlen ? 16 - cryptlen : 0; -- token[11].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[11].instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ /* Process AAD data */ -+ aadref = atoken; -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = assocadj; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_HASH; -+ } -+ atoken++; -+ -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) { -+ /* For ESP mode (and not GMAC), skip over the IV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = EIP197_AEAD_IPSEC_IV_SIZE; -+ atoken->stat = 0; -+ atoken->instructions = 0; -+ atoken++; -+ atoksize++; -+ } else if (unlikely(ctx->alg == SAFEXCEL_CHACHA20 && -+ direction == SAFEXCEL_DECRYPT)) { -+ /* Poly-chacha decryption needs a dummy NOP here ... */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = 16; /* According to Op Manual */ -+ atoken->stat = 0; -+ atoken->instructions = 0; -+ atoken++; -+ atoksize++; -+ } -+ -+ if (ctx->xcm) { -+ /* For GCM and CCM, obtain enc(Y0) */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT_REMRES; -+ atoken->packet_length = 0; -+ atoken->stat = 0; -+ atoken->instructions = AES_BLOCK_SIZE; -+ atoken++; -+ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = AES_BLOCK_SIZE; -+ atoken->stat = 0; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -+ EIP197_TOKEN_INS_TYPE_CRYPTO; -+ atoken++; -+ atoksize += 2; -+ } -+ -+ if (likely(cryptlen || ctx->alg == SAFEXCEL_CHACHA20)) { -+ /* Fixup stat field for AAD direction instruction */ -+ aadref->stat = 0; -+ -+ /* Process crypto data */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_DIRECTION; -+ atoken->packet_length = cryptlen; -+ -+ if (unlikely(ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) { -+ /* Fixup instruction field for AAD dir instruction */ -+ aadref->instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ -+ /* Do not send to crypt engine in case of GMAC */ -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_HASH | -+ EIP197_TOKEN_INS_TYPE_OUTPUT; -+ } else { -+ atoken->instructions = EIP197_TOKEN_INS_LAST | -+ EIP197_TOKEN_INS_TYPE_CRYPTO | -+ EIP197_TOKEN_INS_TYPE_HASH | -+ EIP197_TOKEN_INS_TYPE_OUTPUT; -+ } -+ -+ cryptlen &= 15; -+ if (unlikely(ctx->xcm == EIP197_XCM_MODE_CCM && cryptlen)) { -+ atoken->stat = 0; -+ /* For CCM only, pad crypto data to the hash engine */ -+ atoken++; -+ atoksize++; -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = 16 - cryptlen; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_HASH; - } else { -- token[7].stat = EIP197_TOKEN_STAT_LAST_HASH; -- token[7].instructions = EIP197_TOKEN_INS_LAST | -- EIP197_TOKEN_INS_TYPE_HASH; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH; - } -+ atoken++; -+ atoksize++; - } -+ -+ if (direction == SAFEXCEL_ENCRYPT) { -+ /* Append ICV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_INSERT; -+ atoken->packet_length = digestsize; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH | -+ EIP197_TOKEN_STAT_LAST_PACKET; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -+ EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -+ } else { -+ /* Extract ICV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_RETRIEVE; -+ atoken->packet_length = digestsize; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH | -+ EIP197_TOKEN_STAT_LAST_PACKET; -+ atoken->instructions = EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -+ atoken++; -+ atoksize++; -+ -+ /* Verify ICV */ -+ atoken->opcode = EIP197_TOKEN_OPCODE_VERIFY; -+ atoken->packet_length = digestsize | -+ EIP197_TOKEN_HASH_RESULT_VERIFY; -+ atoken->stat = EIP197_TOKEN_STAT_LAST_HASH | -+ EIP197_TOKEN_STAT_LAST_PACKET; -+ atoken->instructions = EIP197_TOKEN_INS_TYPE_OUTPUT; -+ } -+ -+ /* Fixup length of the token in the command descriptor */ -+ cdesc->additional_cdata_size = atoksize; - } - - static int safexcel_skcipher_aes_setkey(struct crypto_skcipher *ctfm, -@@ -277,14 +380,12 @@ static int safexcel_skcipher_aes_setkey( - int ret, i; - - ret = aes_expandkey(&aes, key, len); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < len / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -309,43 +410,57 @@ static int safexcel_aead_setkey(struct c - struct safexcel_crypto_priv *priv = ctx->priv; - struct crypto_authenc_keys keys; - struct crypto_aes_ctx aes; -- int err = -EINVAL; -+ int err = -EINVAL, i; - -- if (crypto_authenc_extractkeys(&keys, key, len) != 0) -+ if (unlikely(crypto_authenc_extractkeys(&keys, key, len))) - goto badkey; - - if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD) { -- /* Minimum keysize is minimum AES key size + nonce size */ -- if (keys.enckeylen < (AES_MIN_KEY_SIZE + -- CTR_RFC3686_NONCE_SIZE)) -+ /* Must have at least space for the nonce here */ -+ if (unlikely(keys.enckeylen < CTR_RFC3686_NONCE_SIZE)) - goto badkey; - /* last 4 bytes of key are the nonce! */ - ctx->nonce = *(u32 *)(keys.enckey + keys.enckeylen - - CTR_RFC3686_NONCE_SIZE); - /* exclude the nonce here */ -- keys.enckeylen -= CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; - } - - /* Encryption key */ - switch (ctx->alg) { -+ case SAFEXCEL_DES: -+ err = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen); -+ if (unlikely(err)) -+ goto badkey; -+ break; - case SAFEXCEL_3DES: - err = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen); - if (unlikely(err)) -- goto badkey_expflags; -+ goto badkey; - break; - case SAFEXCEL_AES: - err = aes_expandkey(&aes, keys.enckey, keys.enckeylen); - if (unlikely(err)) - goto badkey; - break; -+ case SAFEXCEL_SM4: -+ if (unlikely(keys.enckeylen != SM4_KEY_SIZE)) -+ goto badkey; -+ break; - default: - dev_err(priv->dev, "aead: unsupported cipher algorithm\n"); - goto badkey; - } - -- if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma && -- memcmp(ctx->key, keys.enckey, keys.enckeylen)) -- ctx->base.needs_inv = true; -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { -+ for (i = 0; i < keys.enckeylen / sizeof(u32); i++) { -+ if (le32_to_cpu(ctx->key[i]) != -+ ((u32 *)keys.enckey)[i]) { -+ ctx->base.needs_inv = true; -+ break; -+ } -+ } -+ } - - /* Auth key */ - switch (ctx->hash_alg) { -@@ -374,21 +489,24 @@ static int safexcel_aead_setkey(struct c - keys.authkeylen, &istate, &ostate)) - goto badkey; - break; -+ case CONTEXT_CONTROL_CRYPTO_ALG_SM3: -+ if (safexcel_hmac_setkey("safexcel-sm3", keys.authkey, -+ keys.authkeylen, &istate, &ostate)) -+ goto badkey; -+ break; - default: - dev_err(priv->dev, "aead: unsupported hash algorithm\n"); - goto badkey; - } - -- crypto_aead_set_flags(ctfm, crypto_aead_get_flags(ctfm) & -- CRYPTO_TFM_RES_MASK); -- - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma && - (memcmp(ctx->ipad, istate.state, ctx->state_sz) || - memcmp(ctx->opad, ostate.state, ctx->state_sz))) - ctx->base.needs_inv = true; - - /* Now copy the keys into the context */ -- memcpy(ctx->key, keys.enckey, keys.enckeylen); -+ for (i = 0; i < keys.enckeylen / sizeof(u32); i++) -+ ctx->key[i] = cpu_to_le32(((u32 *)keys.enckey)[i]); - ctx->key_len = keys.enckeylen; - - memcpy(ctx->ipad, &istate.state, ctx->state_sz); -@@ -398,8 +516,6 @@ static int safexcel_aead_setkey(struct c - return 0; - - badkey: -- crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); --badkey_expflags: - memzero_explicit(&keys, sizeof(keys)); - return err; - } -@@ -423,6 +539,17 @@ static int safexcel_context_control(stru - CONTEXT_CONTROL_DIGEST_XCM | - ctx->hash_alg | - CONTEXT_CONTROL_SIZE(ctrl_size); -+ } else if (ctx->alg == SAFEXCEL_CHACHA20) { -+ /* Chacha20-Poly1305 */ -+ cdesc->control_data.control0 = -+ CONTEXT_CONTROL_KEY_EN | -+ CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 | -+ (sreq->direction == SAFEXCEL_ENCRYPT ? -+ CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT : -+ CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN) | -+ ctx->hash_alg | -+ CONTEXT_CONTROL_SIZE(ctrl_size); -+ return 0; - } else { - ctrl_size += ctx->state_sz / sizeof(u32) * 2; - cdesc->control_data.control0 = -@@ -431,17 +558,21 @@ static int safexcel_context_control(stru - ctx->hash_alg | - CONTEXT_CONTROL_SIZE(ctrl_size); - } -- if (sreq->direction == SAFEXCEL_ENCRYPT) -- cdesc->control_data.control0 |= -- (ctx->xcm == EIP197_XCM_MODE_CCM) ? -- CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT : -- CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT; - -+ if (sreq->direction == SAFEXCEL_ENCRYPT && -+ (ctx->xcm == EIP197_XCM_MODE_CCM || -+ ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP_GMAC)) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_TYPE_HASH_ENCRYPT_OUT; -+ else if (sreq->direction == SAFEXCEL_ENCRYPT) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_TYPE_ENCRYPT_HASH_OUT; -+ else if (ctx->xcm == EIP197_XCM_MODE_CCM) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN; - else - cdesc->control_data.control0 |= -- (ctx->xcm == EIP197_XCM_MODE_CCM) ? -- CONTEXT_CONTROL_TYPE_DECRYPT_HASH_IN : -- CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN; -+ CONTEXT_CONTROL_TYPE_HASH_DECRYPT_IN; - } else { - if (sreq->direction == SAFEXCEL_ENCRYPT) - cdesc->control_data.control0 = -@@ -480,6 +611,12 @@ static int safexcel_context_control(stru - ctx->key_len >> ctx->xts); - return -EINVAL; - } -+ } else if (ctx->alg == SAFEXCEL_CHACHA20) { -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20; -+ } else if (ctx->alg == SAFEXCEL_SM4) { -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_CRYPTO_ALG_SM4; - } - - return 0; -@@ -563,6 +700,7 @@ static int safexcel_send_req(struct cryp - unsigned int totlen; - unsigned int totlen_src = cryptlen + assoclen; - unsigned int totlen_dst = totlen_src; -+ struct safexcel_token *atoken; - int n_cdesc = 0, n_rdesc = 0; - int queued, i, ret = 0; - bool first = true; -@@ -637,56 +775,60 @@ static int safexcel_send_req(struct cryp - - memcpy(ctx->base.ctxr->data, ctx->key, ctx->key_len); - -- /* The EIP cannot deal with zero length input packets! */ -- if (totlen == 0) -- totlen = 1; -+ if (!totlen) { -+ /* -+ * The EIP97 cannot deal with zero length input packets! -+ * So stuff a dummy command descriptor indicating a 1 byte -+ * (dummy) input packet, using the context record as source. -+ */ -+ first_cdesc = safexcel_add_cdesc(priv, ring, -+ 1, 1, ctx->base.ctxr_dma, -+ 1, 1, ctx->base.ctxr_dma, -+ &atoken); -+ if (IS_ERR(first_cdesc)) { -+ /* No space left in the command descriptor ring */ -+ ret = PTR_ERR(first_cdesc); -+ goto cdesc_rollback; -+ } -+ n_cdesc = 1; -+ goto skip_cdesc; -+ } - - /* command descriptors */ - for_each_sg(src, sg, sreq->nr_src, i) { - int len = sg_dma_len(sg); - - /* Do not overflow the request */ -- if (queued - len < 0) -+ if (queued < len) - len = queued; - - cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, - !(queued - len), - sg_dma_address(sg), len, totlen, -- ctx->base.ctxr_dma); -+ ctx->base.ctxr_dma, &atoken); - if (IS_ERR(cdesc)) { - /* No space left in the command descriptor ring */ - ret = PTR_ERR(cdesc); - goto cdesc_rollback; - } -- n_cdesc++; - -- if (n_cdesc == 1) { -+ if (!n_cdesc) - first_cdesc = cdesc; -- } - -+ n_cdesc++; - queued -= len; - if (!queued) - break; - } -- -- if (unlikely(!n_cdesc)) { -- /* -- * Special case: zero length input buffer. -- * The engine always needs the 1st command descriptor, however! -- */ -- first_cdesc = safexcel_add_cdesc(priv, ring, 1, 1, 0, 0, totlen, -- ctx->base.ctxr_dma); -- n_cdesc = 1; -- } -- -+skip_cdesc: - /* Add context control words and token to first command descriptor */ - safexcel_context_control(ctx, base, sreq, first_cdesc); - if (ctx->aead) -- safexcel_aead_token(ctx, iv, first_cdesc, -+ safexcel_aead_token(ctx, iv, first_cdesc, atoken, - sreq->direction, cryptlen, - assoclen, digestsize); - else -- safexcel_skcipher_token(ctx, iv, first_cdesc, -+ safexcel_skcipher_token(ctx, iv, first_cdesc, atoken, - cryptlen); - - /* result descriptors */ -@@ -1073,6 +1215,8 @@ static int safexcel_skcipher_cra_init(st - - ctx->base.send = safexcel_skcipher_send; - ctx->base.handle_result = safexcel_skcipher_handle_result; -+ ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD; -+ ctx->ctrinit = 1; - return 0; - } - -@@ -1137,6 +1281,8 @@ static int safexcel_skcipher_aes_ecb_cra - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1171,6 +1317,7 @@ static int safexcel_skcipher_aes_cbc_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; - return 0; - } -@@ -1207,6 +1354,7 @@ static int safexcel_skcipher_aes_cfb_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB; - return 0; - } -@@ -1243,6 +1391,7 @@ static int safexcel_skcipher_aes_ofb_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB; - return 0; - } -@@ -1288,14 +1437,12 @@ static int safexcel_skcipher_aesctr_setk - /* exclude the nonce here */ - keylen = len - CTR_RFC3686_NONCE_SIZE; - ret = aes_expandkey(&aes, key, keylen); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < keylen / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -1317,6 +1464,7 @@ static int safexcel_skcipher_aes_ctr_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; - return 0; - } -@@ -1352,6 +1500,7 @@ static int safexcel_des_setkey(struct cr - unsigned int len) - { - struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); -+ struct safexcel_crypto_priv *priv = ctx->priv; - int ret; - - ret = verify_skcipher_des_key(ctfm, key); -@@ -1359,7 +1508,7 @@ static int safexcel_des_setkey(struct cr - return ret; - - /* if context exits and key changed, need to invalidate it */ -- if (ctx->base.ctxr_dma) -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) - if (memcmp(ctx->key, key, len)) - ctx->base.needs_inv = true; - -@@ -1375,6 +1524,8 @@ static int safexcel_skcipher_des_cbc_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_DES; -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; - return 0; - } -@@ -1412,6 +1563,8 @@ static int safexcel_skcipher_des_ecb_cra - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_DES; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1444,6 +1597,7 @@ static int safexcel_des3_ede_setkey(stru - const u8 *key, unsigned int len) - { - struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); -+ struct safexcel_crypto_priv *priv = ctx->priv; - int err; - - err = verify_skcipher_des3_key(ctfm, key); -@@ -1451,13 +1605,11 @@ static int safexcel_des3_ede_setkey(stru - return err; - - /* if context exits and key changed, need to invalidate it */ -- if (ctx->base.ctxr_dma) { -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) - if (memcmp(ctx->key, key, len)) - ctx->base.needs_inv = true; -- } - - memcpy(ctx->key, key, len); -- - ctx->key_len = len; - - return 0; -@@ -1469,6 +1621,8 @@ static int safexcel_skcipher_des3_cbc_cr - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_3DES; -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; - return 0; - } -@@ -1506,6 +1660,8 @@ static int safexcel_skcipher_des3_ecb_cr - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_3DES; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1561,6 +1717,9 @@ static int safexcel_aead_cra_init(struct - ctx->priv = tmpl->priv; - - ctx->alg = SAFEXCEL_AES; /* default */ -+ ctx->blocksz = AES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_4_TOKEN_IV_CMD; -+ ctx->ctrinit = 1; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; /* default */ - ctx->aead = true; - ctx->base.send = safexcel_aead_send; -@@ -1749,6 +1908,8 @@ static int safexcel_aead_sha1_des3_cra_i - - safexcel_aead_sha1_cra_init(tfm); - ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; - return 0; - } - -@@ -1777,6 +1938,330 @@ struct safexcel_alg_template safexcel_al - }, - }; - -+static int safexcel_aead_sha256_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha256_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha256_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha224_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha224_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha224_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha512_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha512_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha512),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha512_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha384_des3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha384_cra_init(tfm); -+ ctx->alg = SAFEXCEL_3DES; /* override default */ -+ ctx->blocksz = DES3_EDE_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha384),cbc(des3_ede))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des3_ede", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha384_des3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha1_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha1_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA1, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha1_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha256_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha256_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha256-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha256_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha224_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha224_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_256, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha224-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha224_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha512_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha512_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha512),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha512-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha512_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sha384_des_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sha384_cra_init(tfm); -+ ctx->alg = SAFEXCEL_DES; /* override default */ -+ ctx->blocksz = DES_BLOCK_SIZE; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_DES | SAFEXCEL_ALG_SHA2_512, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha384),cbc(des))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha384-cbc-des", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = DES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sha384_des_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ - static int safexcel_aead_sha1_ctr_cra_init(struct crypto_tfm *tfm) - { - struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -@@ -1965,14 +2450,12 @@ static int safexcel_skcipher_aesxts_setk - /* Only half of the key data is cipher key */ - keylen = (len >> 1); - ret = aes_expandkey(&aes, key, keylen); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < keylen / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -1984,15 +2467,13 @@ static int safexcel_skcipher_aesxts_setk - - /* The other half is the tweak key */ - ret = aes_expandkey(&aes, (u8 *)(key + keylen), keylen); -- if (ret) { -- crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ if (ret) - return ret; -- } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < keylen / sizeof(u32); i++) { -- if (ctx->key[i + keylen / sizeof(u32)] != -- cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i + keylen / sizeof(u32)]) != -+ aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2015,6 +2496,7 @@ static int safexcel_skcipher_aes_xts_cra - - safexcel_skcipher_cra_init(tfm); - ctx->alg = SAFEXCEL_AES; -+ ctx->blocksz = AES_BLOCK_SIZE; - ctx->xts = 1; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XTS; - return 0; -@@ -2075,14 +2557,13 @@ static int safexcel_aead_gcm_setkey(stru - - ret = aes_expandkey(&aes, key, len); - if (ret) { -- crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - memzero_explicit(&aes, sizeof(aes)); - return ret; - } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < len / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2099,8 +2580,6 @@ static int safexcel_aead_gcm_setkey(stru - crypto_cipher_set_flags(ctx->hkaes, crypto_aead_get_flags(ctfm) & - CRYPTO_TFM_REQ_MASK); - ret = crypto_cipher_setkey(ctx->hkaes, key, len); -- crypto_aead_set_flags(ctfm, crypto_cipher_get_flags(ctx->hkaes) & -- CRYPTO_TFM_RES_MASK); - if (ret) - return ret; - -@@ -2109,7 +2588,7 @@ static int safexcel_aead_gcm_setkey(stru - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) { -- if (ctx->ipad[i] != cpu_to_be32(hashkey[i])) { -+ if (be32_to_cpu(ctx->ipad[i]) != hashkey[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2135,10 +2614,7 @@ static int safexcel_aead_gcm_cra_init(st - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */ - - ctx->hkaes = crypto_alloc_cipher("aes", 0, 0); -- if (IS_ERR(ctx->hkaes)) -- return PTR_ERR(ctx->hkaes); -- -- return 0; -+ return PTR_ERR_OR_ZERO(ctx->hkaes); - } - - static void safexcel_aead_gcm_cra_exit(struct crypto_tfm *tfm) -@@ -2192,14 +2668,13 @@ static int safexcel_aead_ccm_setkey(stru - - ret = aes_expandkey(&aes, key, len); - if (ret) { -- crypto_aead_set_flags(ctfm, CRYPTO_TFM_RES_BAD_KEY_LEN); - memzero_explicit(&aes, sizeof(aes)); - return ret; - } - - if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) { - for (i = 0; i < len / sizeof(u32); i++) { -- if (ctx->key[i] != cpu_to_le32(aes.key_enc[i])) { -+ if (le32_to_cpu(ctx->key[i]) != aes.key_enc[i]) { - ctx->base.needs_inv = true; - break; - } -@@ -2235,6 +2710,7 @@ static int safexcel_aead_ccm_cra_init(st - ctx->state_sz = 3 * AES_BLOCK_SIZE; - ctx->xcm = EIP197_XCM_MODE_CCM; - ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_XCM; /* override default */ -+ ctx->ctrinit = 0; - return 0; - } - -@@ -2301,5 +2777,949 @@ struct safexcel_alg_template safexcel_al - .cra_exit = safexcel_aead_cra_exit, - .cra_module = THIS_MODULE, - }, -+ }, -+}; -+ -+static void safexcel_chacha20_setkey(struct safexcel_cipher_ctx *ctx, -+ const u8 *key) -+{ -+ struct safexcel_crypto_priv *priv = ctx->priv; -+ -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) -+ if (memcmp(ctx->key, key, CHACHA_KEY_SIZE)) -+ ctx->base.needs_inv = true; -+ -+ memcpy(ctx->key, key, CHACHA_KEY_SIZE); -+ ctx->key_len = CHACHA_KEY_SIZE; -+} -+ -+static int safexcel_skcipher_chacha20_setkey(struct crypto_skcipher *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_skcipher_ctx(ctfm); -+ -+ if (len != CHACHA_KEY_SIZE) -+ return -EINVAL; -+ -+ safexcel_chacha20_setkey(ctx, key); -+ -+ return 0; -+} -+ -+static int safexcel_skcipher_chacha20_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_CHACHA20; -+ ctx->ctrinit = 0; -+ ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_chacha20 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_CHACHA20, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_chacha20_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ .min_keysize = CHACHA_KEY_SIZE, -+ .max_keysize = CHACHA_KEY_SIZE, -+ .ivsize = CHACHA_IV_SIZE, -+ .base = { -+ .cra_name = "chacha20", -+ .cra_driver_name = "safexcel-chacha20", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_chacha20_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_chachapoly_setkey(struct crypto_aead *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_aead_ctx(ctfm); -+ -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP && -+ len > EIP197_AEAD_IPSEC_NONCE_SIZE) { -+ /* ESP variant has nonce appended to key */ -+ len -= EIP197_AEAD_IPSEC_NONCE_SIZE; -+ ctx->nonce = *(u32 *)(key + len); -+ } -+ if (len != CHACHA_KEY_SIZE) -+ return -EINVAL; -+ -+ safexcel_chacha20_setkey(ctx, key); -+ -+ return 0; -+} -+ -+static int safexcel_aead_chachapoly_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ if (authsize != POLY1305_DIGEST_SIZE) -+ return -EINVAL; -+ return 0; -+} -+ -+static int safexcel_aead_chachapoly_crypt(struct aead_request *req, -+ enum safexcel_cipher_direction dir) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_tfm *tfm = crypto_aead_tfm(aead); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct aead_request *subreq = aead_request_ctx(req); -+ u32 key[CHACHA_KEY_SIZE / sizeof(u32) + 1]; -+ int ret = 0; -+ -+ /* -+ * Instead of wasting time detecting umpteen silly corner cases, -+ * just dump all "small" requests to the fallback implementation. -+ * HW would not be faster on such small requests anyway. -+ */ -+ if (likely((ctx->aead != EIP197_AEAD_TYPE_IPSEC_ESP || -+ req->assoclen >= EIP197_AEAD_IPSEC_IV_SIZE) && -+ req->cryptlen > POLY1305_DIGEST_SIZE)) { -+ return safexcel_queue_req(&req->base, creq, dir); -+ } -+ -+ /* HW cannot do full (AAD+payload) zero length, use fallback */ -+ memcpy(key, ctx->key, CHACHA_KEY_SIZE); -+ if (ctx->aead == EIP197_AEAD_TYPE_IPSEC_ESP) { -+ /* ESP variant has nonce appended to the key */ -+ key[CHACHA_KEY_SIZE / sizeof(u32)] = ctx->nonce; -+ ret = crypto_aead_setkey(ctx->fback, (u8 *)key, -+ CHACHA_KEY_SIZE + -+ EIP197_AEAD_IPSEC_NONCE_SIZE); -+ } else { -+ ret = crypto_aead_setkey(ctx->fback, (u8 *)key, -+ CHACHA_KEY_SIZE); -+ } -+ if (ret) { -+ crypto_aead_clear_flags(aead, CRYPTO_TFM_REQ_MASK); -+ crypto_aead_set_flags(aead, crypto_aead_get_flags(ctx->fback) & -+ CRYPTO_TFM_REQ_MASK); -+ return ret; -+ } -+ -+ aead_request_set_tfm(subreq, ctx->fback); -+ aead_request_set_callback(subreq, req->base.flags, req->base.complete, -+ req->base.data); -+ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, -+ req->iv); -+ aead_request_set_ad(subreq, req->assoclen); -+ -+ return (dir == SAFEXCEL_ENCRYPT) ? -+ crypto_aead_encrypt(subreq) : -+ crypto_aead_decrypt(subreq); -+} -+ -+static int safexcel_aead_chachapoly_encrypt(struct aead_request *req) -+{ -+ return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_aead_chachapoly_decrypt(struct aead_request *req) -+{ -+ return safexcel_aead_chachapoly_crypt(req, SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_aead_fallback_cra_init(struct crypto_tfm *tfm) -+{ -+ struct crypto_aead *aead = __crypto_aead_cast(tfm); -+ struct aead_alg *alg = crypto_aead_alg(aead); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_cra_init(tfm); -+ -+ /* Allocate fallback implementation */ -+ ctx->fback = crypto_alloc_aead(alg->base.cra_name, 0, -+ CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->fback)) -+ return PTR_ERR(ctx->fback); -+ -+ crypto_aead_set_reqsize(aead, max(sizeof(struct safexcel_cipher_req), -+ sizeof(struct aead_request) + -+ crypto_aead_reqsize(ctx->fback))); -+ -+ return 0; -+} -+ -+static int safexcel_aead_chachapoly_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_fallback_cra_init(tfm); -+ ctx->alg = SAFEXCEL_CHACHA20; -+ ctx->mode = CONTEXT_CONTROL_CHACHA20_MODE_256_32 | -+ CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK; -+ ctx->ctrinit = 0; -+ ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_POLY1305; -+ ctx->state_sz = 0; /* Precomputed by HW */ -+ return 0; -+} -+ -+static void safexcel_aead_fallback_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_aead(ctx->fback); -+ safexcel_aead_cra_exit(tfm); -+} -+ -+struct safexcel_alg_template safexcel_alg_chachapoly = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305, -+ .alg.aead = { -+ .setkey = safexcel_aead_chachapoly_setkey, -+ .setauthsize = safexcel_aead_chachapoly_setauthsize, -+ .encrypt = safexcel_aead_chachapoly_encrypt, -+ .decrypt = safexcel_aead_chachapoly_decrypt, -+ .ivsize = CHACHAPOLY_IV_SIZE, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc7539(chacha20,poly1305)", -+ .cra_driver_name = "safexcel-chacha20-poly1305", -+ /* +1 to put it above HW chacha + SW poly */ -+ .cra_priority = SAFEXCEL_CRA_PRIORITY + 1, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_chachapoly_cra_init, -+ .cra_exit = safexcel_aead_fallback_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_chachapolyesp_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_chachapoly_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP; -+ ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_chachapoly_esp = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_CHACHA20 | SAFEXCEL_ALG_POLY1305, -+ .alg.aead = { -+ .setkey = safexcel_aead_chachapoly_setkey, -+ .setauthsize = safexcel_aead_chachapoly_setauthsize, -+ .encrypt = safexcel_aead_chachapoly_encrypt, -+ .decrypt = safexcel_aead_chachapoly_decrypt, -+ .ivsize = CHACHAPOLY_IV_SIZE - EIP197_AEAD_IPSEC_NONCE_SIZE, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc7539esp(chacha20,poly1305)", -+ .cra_driver_name = "safexcel-chacha20-poly1305-esp", -+ /* +1 to put it above HW chacha + SW poly */ -+ .cra_priority = SAFEXCEL_CRA_PRIORITY + 1, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_chachapolyesp_cra_init, -+ .cra_exit = safexcel_aead_fallback_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_setkey(struct crypto_skcipher *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct safexcel_crypto_priv *priv = ctx->priv; -+ -+ if (len != SM4_KEY_SIZE) -+ return -EINVAL; -+ -+ if (priv->flags & EIP197_TRC_CACHE && ctx->base.ctxr_dma) -+ if (memcmp(ctx->key, key, SM4_KEY_SIZE)) -+ ctx->base.needs_inv = true; -+ -+ memcpy(ctx->key, key, SM4_KEY_SIZE); -+ ctx->key_len = SM4_KEY_SIZE; -+ -+ return 0; -+} -+ -+static int safexcel_sm4_blk_encrypt(struct skcipher_request *req) -+{ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else -+ return safexcel_queue_req(&req->base, skcipher_request_ctx(req), -+ SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_sm4_blk_decrypt(struct skcipher_request *req) -+{ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else -+ return safexcel_queue_req(&req->base, skcipher_request_ctx(req), -+ SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_skcipher_sm4_ecb_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_ECB; -+ ctx->blocksz = 0; -+ ctx->ivmask = EIP197_OPTION_2_TOKEN_IV_CMD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_ecb_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_sm4_blk_encrypt, -+ .decrypt = safexcel_sm4_blk_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .base = { -+ .cra_name = "ecb(sm4)", -+ .cra_driver_name = "safexcel-ecb-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_ecb_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_cbc_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CBC; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_cbc_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_sm4_blk_encrypt, -+ .decrypt = safexcel_sm4_blk_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .ivsize = SM4_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cbc(sm4)", -+ .cra_driver_name = "safexcel-cbc-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_cbc_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_ofb_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_OFB; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_ofb_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .ivsize = SM4_BLOCK_SIZE, -+ .base = { -+ .cra_name = "ofb(sm4)", -+ .cra_driver_name = "safexcel-ofb-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_ofb_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4_cfb_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CFB; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_cfb_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_AES_XFB, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ .min_keysize = SM4_KEY_SIZE, -+ .max_keysize = SM4_KEY_SIZE, -+ .ivsize = SM4_BLOCK_SIZE, -+ .base = { -+ .cra_name = "cfb(sm4)", -+ .cra_driver_name = "safexcel-cfb-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_cfb_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_skcipher_sm4ctr_setkey(struct crypto_skcipher *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* last 4 bytes of key are the nonce! */ -+ ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE); -+ /* exclude the nonce here */ -+ len -= CTR_RFC3686_NONCE_SIZE; -+ -+ return safexcel_skcipher_sm4_setkey(ctfm, key, len); -+} -+ -+static int safexcel_skcipher_sm4_ctr_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_skcipher_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_ctr_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_SKCIPHER, -+ .algo_mask = SAFEXCEL_ALG_SM4, -+ .alg.skcipher = { -+ .setkey = safexcel_skcipher_sm4ctr_setkey, -+ .encrypt = safexcel_encrypt, -+ .decrypt = safexcel_decrypt, -+ /* Add nonce size */ -+ .min_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .max_keysize = SM4_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .base = { -+ .cra_name = "rfc3686(ctr(sm4))", -+ .cra_driver_name = "safexcel-ctr-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_skcipher_sm4_ctr_cra_init, -+ .cra_exit = safexcel_skcipher_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sm4_blk_encrypt(struct aead_request *req) -+{ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, aead_request_ctx(req), -+ SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_aead_sm4_blk_decrypt(struct aead_request *req) -+{ -+ struct crypto_aead *tfm = crypto_aead_reqtfm(req); -+ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, aead_request_ctx(req), -+ SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_aead_sm4cbc_sha1_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; -+ ctx->state_sz = SHA1_DIGEST_SIZE; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_sm4_blk_encrypt, -+ .decrypt = safexcel_aead_sm4_blk_decrypt, -+ .ivsize = SM4_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(sm4))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha1-cbc-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4cbc_sha1_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_fallback_setkey(struct crypto_aead *ctfm, -+ const u8 *key, unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* Keep fallback cipher synchronized */ -+ return crypto_aead_setkey(ctx->fback, (u8 *)key, len) ?: -+ safexcel_aead_setkey(ctfm, key, len); -+} -+ -+static int safexcel_aead_fallback_setauthsize(struct crypto_aead *ctfm, -+ unsigned int authsize) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* Keep fallback cipher synchronized */ -+ return crypto_aead_setauthsize(ctx->fback, authsize); -+} -+ -+static int safexcel_aead_fallback_crypt(struct aead_request *req, -+ enum safexcel_cipher_direction dir) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_tfm *tfm = crypto_aead_tfm(aead); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct aead_request *subreq = aead_request_ctx(req); -+ -+ aead_request_set_tfm(subreq, ctx->fback); -+ aead_request_set_callback(subreq, req->base.flags, req->base.complete, -+ req->base.data); -+ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, -+ req->iv); -+ aead_request_set_ad(subreq, req->assoclen); -+ -+ return (dir == SAFEXCEL_ENCRYPT) ? -+ crypto_aead_encrypt(subreq) : -+ crypto_aead_decrypt(subreq); -+} -+ -+static int safexcel_aead_sm4cbc_sm3_encrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if (req->cryptlen & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else if (req->cryptlen || req->assoclen) /* If input length > 0 only */ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT); -+ -+ /* HW cannot do full (AAD+payload) zero length, use fallback */ -+ return safexcel_aead_fallback_crypt(req, SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_aead_sm4cbc_sm3_decrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ struct crypto_aead *tfm = crypto_aead_reqtfm(req); -+ -+ /* Workaround for HW bug: EIP96 4.3 does not report blocksize error */ -+ if ((req->cryptlen - crypto_aead_authsize(tfm)) & (SM4_BLOCK_SIZE - 1)) -+ return -EINVAL; -+ else if (req->cryptlen > crypto_aead_authsize(tfm) || req->assoclen) -+ /* If input length > 0 only */ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT); -+ -+ /* HW cannot do full (AAD+payload) zero length, use fallback */ -+ return safexcel_aead_fallback_crypt(req, SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_aead_sm4cbc_sm3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_fallback_cra_init(tfm); -+ ctx->alg = SAFEXCEL_SM4; -+ ctx->blocksz = SM4_BLOCK_SIZE; -+ ctx->hash_alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; -+ ctx->state_sz = SM3_DIGEST_SIZE; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3, -+ .alg.aead = { -+ .setkey = safexcel_aead_fallback_setkey, -+ .setauthsize = safexcel_aead_fallback_setauthsize, -+ .encrypt = safexcel_aead_sm4cbc_sm3_encrypt, -+ .decrypt = safexcel_aead_sm4cbc_sm3_decrypt, -+ .ivsize = SM4_BLOCK_SIZE, -+ .maxauthsize = SM3_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sm3),cbc(sm4))", -+ .cra_driver_name = "safexcel-authenc-hmac-sm3-cbc-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SM4_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4cbc_sm3_cra_init, -+ .cra_exit = safexcel_aead_fallback_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sm4ctr_sha1_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sm4cbc_sha1_cra_init(tfm); -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SHA1, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sha1),rfc3686(ctr(sm4)))", -+ .cra_driver_name = "safexcel-authenc-hmac-sha1-ctr-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4ctr_sha1_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_aead_sm4ctr_sm3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_aead_sm4cbc_sm3_cra_init(tfm); -+ ctx->mode = CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD; -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4 = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_SM4 | SAFEXCEL_ALG_SM3, -+ .alg.aead = { -+ .setkey = safexcel_aead_setkey, -+ .encrypt = safexcel_aead_encrypt, -+ .decrypt = safexcel_aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SM3_DIGEST_SIZE, -+ .base = { -+ .cra_name = "authenc(hmac(sm3),rfc3686(ctr(sm4)))", -+ .cra_driver_name = "safexcel-authenc-hmac-sm3-ctr-sm4", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_aead_sm4ctr_sm3_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+}; -+ -+static int safexcel_rfc4106_gcm_setkey(struct crypto_aead *ctfm, const u8 *key, -+ unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* last 4 bytes of key are the nonce! */ -+ ctx->nonce = *(u32 *)(key + len - CTR_RFC3686_NONCE_SIZE); -+ -+ len -= CTR_RFC3686_NONCE_SIZE; -+ return safexcel_aead_gcm_setkey(ctfm, key, len); -+} -+ -+static int safexcel_rfc4106_gcm_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ return crypto_rfc4106_check_authsize(authsize); -+} -+ -+static int safexcel_rfc4106_encrypt(struct aead_request *req) -+{ -+ return crypto_ipsec_check_assoclen(req->assoclen) ?: -+ safexcel_aead_encrypt(req); -+} -+ -+static int safexcel_rfc4106_decrypt(struct aead_request *req) -+{ -+ return crypto_ipsec_check_assoclen(req->assoclen) ?: -+ safexcel_aead_decrypt(req); -+} -+ -+static int safexcel_rfc4106_gcm_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_gcm_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP; -+ ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_rfc4106_gcm = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH, -+ .alg.aead = { -+ .setkey = safexcel_rfc4106_gcm_setkey, -+ .setauthsize = safexcel_rfc4106_gcm_setauthsize, -+ .encrypt = safexcel_rfc4106_encrypt, -+ .decrypt = safexcel_rfc4106_decrypt, -+ .ivsize = GCM_RFC4106_IV_SIZE, -+ .maxauthsize = GHASH_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc4106(gcm(aes))", -+ .cra_driver_name = "safexcel-rfc4106-gcm-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_rfc4106_gcm_cra_init, -+ .cra_exit = safexcel_aead_gcm_cra_exit, -+ }, -+ }, -+}; -+ -+static int safexcel_rfc4543_gcm_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ if (authsize != GHASH_DIGEST_SIZE) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int safexcel_rfc4543_gcm_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_gcm_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP_GMAC; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_rfc4543_gcm = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_GHASH, -+ .alg.aead = { -+ .setkey = safexcel_rfc4106_gcm_setkey, -+ .setauthsize = safexcel_rfc4543_gcm_setauthsize, -+ .encrypt = safexcel_rfc4106_encrypt, -+ .decrypt = safexcel_rfc4106_decrypt, -+ .ivsize = GCM_RFC4543_IV_SIZE, -+ .maxauthsize = GHASH_DIGEST_SIZE, -+ .base = { -+ .cra_name = "rfc4543(gcm(aes))", -+ .cra_driver_name = "safexcel-rfc4543-gcm-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_rfc4543_gcm_cra_init, -+ .cra_exit = safexcel_aead_gcm_cra_exit, -+ }, -+ }, -+}; -+ -+static int safexcel_rfc4309_ccm_setkey(struct crypto_aead *ctfm, const u8 *key, -+ unsigned int len) -+{ -+ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ /* First byte of the nonce = L = always 3 for RFC4309 (4 byte ctr) */ -+ *(u8 *)&ctx->nonce = EIP197_AEAD_IPSEC_COUNTER_SIZE - 1; -+ /* last 3 bytes of key are the nonce! */ -+ memcpy((u8 *)&ctx->nonce + 1, key + len - -+ EIP197_AEAD_IPSEC_CCM_NONCE_SIZE, -+ EIP197_AEAD_IPSEC_CCM_NONCE_SIZE); -+ -+ len -= EIP197_AEAD_IPSEC_CCM_NONCE_SIZE; -+ return safexcel_aead_ccm_setkey(ctfm, key, len); -+} -+ -+static int safexcel_rfc4309_ccm_setauthsize(struct crypto_aead *tfm, -+ unsigned int authsize) -+{ -+ /* Borrowed from crypto/ccm.c */ -+ switch (authsize) { -+ case 8: -+ case 12: -+ case 16: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int safexcel_rfc4309_ccm_encrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ -+ /* Borrowed from crypto/ccm.c */ -+ if (req->assoclen != 16 && req->assoclen != 20) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_ENCRYPT); -+} -+ -+static int safexcel_rfc4309_ccm_decrypt(struct aead_request *req) -+{ -+ struct safexcel_cipher_req *creq = aead_request_ctx(req); -+ -+ /* Borrowed from crypto/ccm.c */ -+ if (req->assoclen != 16 && req->assoclen != 20) -+ return -EINVAL; -+ -+ return safexcel_queue_req(&req->base, creq, SAFEXCEL_DECRYPT); -+} -+ -+static int safexcel_rfc4309_ccm_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_aead_ccm_cra_init(tfm); -+ ctx->aead = EIP197_AEAD_TYPE_IPSEC_ESP; -+ ctx->aadskip = EIP197_AEAD_IPSEC_IV_SIZE; -+ return ret; -+} -+ -+struct safexcel_alg_template safexcel_alg_rfc4309_ccm = { -+ .type = SAFEXCEL_ALG_TYPE_AEAD, -+ .algo_mask = SAFEXCEL_ALG_AES | SAFEXCEL_ALG_CBC_MAC_ALL, -+ .alg.aead = { -+ .setkey = safexcel_rfc4309_ccm_setkey, -+ .setauthsize = safexcel_rfc4309_ccm_setauthsize, -+ .encrypt = safexcel_rfc4309_ccm_encrypt, -+ .decrypt = safexcel_rfc4309_ccm_decrypt, -+ .ivsize = EIP197_AEAD_IPSEC_IV_SIZE, -+ .maxauthsize = AES_BLOCK_SIZE, -+ .base = { -+ .cra_name = "rfc4309(ccm(aes))", -+ .cra_driver_name = "safexcel-rfc4309-ccm-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_cipher_ctx), -+ .cra_alignmask = 0, -+ .cra_init = safexcel_rfc4309_ccm_cra_init, -+ .cra_exit = safexcel_aead_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, - }, - }; ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -17,8 +17,11 @@ - #define EIP197_HIA_VERSION_BE 0xca35 - #define EIP197_HIA_VERSION_LE 0x35ca - #define EIP97_VERSION_LE 0x9e61 -+#define EIP196_VERSION_LE 0x3bc4 - #define EIP197_VERSION_LE 0x3ac5 - #define EIP96_VERSION_LE 0x9f60 -+#define EIP201_VERSION_LE 0x36c9 -+#define EIP206_VERSION_LE 0x31ce - #define EIP197_REG_LO16(reg) (reg & 0xffff) - #define EIP197_REG_HI16(reg) ((reg >> 16) & 0xffff) - #define EIP197_VERSION_MASK(reg) ((reg >> 16) & 0xfff) -@@ -26,12 +29,23 @@ - ((reg >> 4) & 0xf0) | \ - ((reg >> 12) & 0xf)) - -+/* EIP197 HIA OPTIONS ENCODING */ -+#define EIP197_HIA_OPT_HAS_PE_ARB BIT(29) -+ -+/* EIP206 OPTIONS ENCODING */ -+#define EIP206_OPT_ICE_TYPE(n) ((n>>8)&3) -+ -+/* EIP197 OPTIONS ENCODING */ -+#define EIP197_OPT_HAS_TRC BIT(31) -+ - /* Static configuration */ - #define EIP197_DEFAULT_RING_SIZE 400 --#define EIP197_MAX_TOKENS 18 -+#define EIP197_EMB_TOKENS 4 /* Pad CD to 16 dwords */ -+#define EIP197_MAX_TOKENS 16 - #define EIP197_MAX_RINGS 4 - #define EIP197_FETCH_DEPTH 2 - #define EIP197_MAX_BATCH_SZ 64 -+#define EIP197_MAX_RING_AIC 14 - - #define EIP197_GFP_FLAGS(base) ((base).flags & CRYPTO_TFM_REQ_MAY_SLEEP ? \ - GFP_KERNEL : GFP_ATOMIC) -@@ -138,6 +152,7 @@ - #define EIP197_HIA_AIC_R_ENABLED_STAT(r) (0xe010 - EIP197_HIA_AIC_R_OFF(r)) - #define EIP197_HIA_AIC_R_ACK(r) (0xe010 - EIP197_HIA_AIC_R_OFF(r)) - #define EIP197_HIA_AIC_R_ENABLE_CLR(r) (0xe014 - EIP197_HIA_AIC_R_OFF(r)) -+#define EIP197_HIA_AIC_R_VERSION(r) (0xe01c - EIP197_HIA_AIC_R_OFF(r)) - #define EIP197_HIA_AIC_G_ENABLE_CTRL 0xf808 - #define EIP197_HIA_AIC_G_ENABLED_STAT 0xf810 - #define EIP197_HIA_AIC_G_ACK 0xf810 -@@ -157,12 +172,16 @@ - #define EIP197_PE_EIP96_FUNCTION_EN(n) (0x1004 + (0x2000 * (n))) - #define EIP197_PE_EIP96_CONTEXT_CTRL(n) (0x1008 + (0x2000 * (n))) - #define EIP197_PE_EIP96_CONTEXT_STAT(n) (0x100c + (0x2000 * (n))) -+#define EIP197_PE_EIP96_TOKEN_CTRL2(n) (0x102c + (0x2000 * (n))) - #define EIP197_PE_EIP96_FUNCTION2_EN(n) (0x1030 + (0x2000 * (n))) - #define EIP197_PE_EIP96_OPTIONS(n) (0x13f8 + (0x2000 * (n))) - #define EIP197_PE_EIP96_VERSION(n) (0x13fc + (0x2000 * (n))) - #define EIP197_PE_OUT_DBUF_THRES(n) (0x1c00 + (0x2000 * (n))) - #define EIP197_PE_OUT_TBUF_THRES(n) (0x1d00 + (0x2000 * (n))) -+#define EIP197_PE_OPTIONS(n) (0x1ff8 + (0x2000 * (n))) -+#define EIP197_PE_VERSION(n) (0x1ffc + (0x2000 * (n))) - #define EIP197_MST_CTRL 0xfff4 -+#define EIP197_OPTIONS 0xfff8 - #define EIP197_VERSION 0xfffc - - /* EIP197-specific registers, no indirection */ -@@ -178,6 +197,7 @@ - #define EIP197_TRC_ECCADMINSTAT 0xf0838 - #define EIP197_TRC_ECCDATASTAT 0xf083c - #define EIP197_TRC_ECCDATA 0xf0840 -+#define EIP197_STRC_CONFIG 0xf43f0 - #define EIP197_FLUE_CACHEBASE_LO(n) (0xf6000 + (32 * (n))) - #define EIP197_FLUE_CACHEBASE_HI(n) (0xf6004 + (32 * (n))) - #define EIP197_FLUE_CONFIG(n) (0xf6010 + (32 * (n))) -@@ -188,6 +208,7 @@ - - /* EIP197_HIA_xDR_DESC_SIZE */ - #define EIP197_xDR_DESC_MODE_64BIT BIT(31) -+#define EIP197_CDR_DESC_MODE_ADCP BIT(30) - - /* EIP197_HIA_xDR_DMA_CFG */ - #define EIP197_HIA_xDR_WR_RES_BUF BIT(22) -@@ -213,7 +234,6 @@ - /* EIP197_HIA_xDR_PROC_COUNT */ - #define EIP197_xDR_PROC_xD_PKT_OFFSET 24 - #define EIP197_xDR_PROC_xD_PKT_MASK GENMASK(6, 0) --#define EIP197_xDR_PROC_xD_COUNT(n) ((n) << 2) - #define EIP197_xDR_PROC_xD_PKT(n) ((n) << 24) - #define EIP197_xDR_PROC_CLR_COUNT BIT(31) - -@@ -228,6 +248,8 @@ - #define EIP197_HIA_RA_PE_CTRL_EN BIT(30) - - /* EIP197_HIA_OPTIONS */ -+#define EIP197_N_RINGS_OFFSET 0 -+#define EIP197_N_RINGS_MASK GENMASK(3, 0) - #define EIP197_N_PES_OFFSET 4 - #define EIP197_N_PES_MASK GENMASK(4, 0) - #define EIP97_N_PES_MASK GENMASK(2, 0) -@@ -237,13 +259,13 @@ - #define EIP197_CFSIZE_OFFSET 9 - #define EIP197_CFSIZE_ADJUST 4 - #define EIP97_CFSIZE_OFFSET 8 --#define EIP197_CFSIZE_MASK GENMASK(3, 0) --#define EIP97_CFSIZE_MASK GENMASK(4, 0) -+#define EIP197_CFSIZE_MASK GENMASK(2, 0) -+#define EIP97_CFSIZE_MASK GENMASK(3, 0) - #define EIP197_RFSIZE_OFFSET 12 - #define EIP197_RFSIZE_ADJUST 4 - #define EIP97_RFSIZE_OFFSET 12 --#define EIP197_RFSIZE_MASK GENMASK(3, 0) --#define EIP97_RFSIZE_MASK GENMASK(4, 0) -+#define EIP197_RFSIZE_MASK GENMASK(2, 0) -+#define EIP97_RFSIZE_MASK GENMASK(3, 0) - - /* EIP197_HIA_AIC_R_ENABLE_CTRL */ - #define EIP197_CDR_IRQ(n) BIT((n) * 2) -@@ -257,9 +279,9 @@ - #define EIP197_HIA_DxE_CFG_MIN_CTRL_SIZE(n) ((n) << 16) - #define EIP197_HIA_DxE_CFG_CTRL_CACHE_CTRL(n) (((n) & 0x7) << 20) - #define EIP197_HIA_DxE_CFG_MAX_CTRL_SIZE(n) ((n) << 24) --#define EIP197_HIA_DFE_CFG_DIS_DEBUG (BIT(31) | BIT(29)) -+#define EIP197_HIA_DFE_CFG_DIS_DEBUG GENMASK(31, 29) - #define EIP197_HIA_DSE_CFG_EN_SINGLE_WR BIT(29) --#define EIP197_HIA_DSE_CFG_DIS_DEBUG BIT(31) -+#define EIP197_HIA_DSE_CFG_DIS_DEBUG GENMASK(31, 30) - - /* EIP197_HIA_DFE/DSE_THR_CTRL */ - #define EIP197_DxE_THR_CTRL_EN BIT(30) -@@ -327,13 +349,21 @@ - #define EIP197_ADDRESS_MODE BIT(8) - #define EIP197_CONTROL_MODE BIT(9) - -+/* EIP197_PE_EIP96_TOKEN_CTRL2 */ -+#define EIP197_PE_EIP96_TOKEN_CTRL2_CTX_DONE BIT(3) -+ -+/* EIP197_STRC_CONFIG */ -+#define EIP197_STRC_CONFIG_INIT BIT(31) -+#define EIP197_STRC_CONFIG_LARGE_REC(s) (s<<8) -+#define EIP197_STRC_CONFIG_SMALL_REC(s) (s<<0) -+ - /* EIP197_FLUE_CONFIG */ - #define EIP197_FLUE_CONFIG_MAGIC 0xc7000004 - - /* Context Control */ - struct safexcel_context_record { -- u32 control0; -- u32 control1; -+ __le32 control0; -+ __le32 control1; - - __le32 data[40]; - } __packed; -@@ -358,10 +388,14 @@ struct safexcel_context_record { - #define CONTEXT_CONTROL_CRYPTO_ALG_AES128 (0x5 << 17) - #define CONTEXT_CONTROL_CRYPTO_ALG_AES192 (0x6 << 17) - #define CONTEXT_CONTROL_CRYPTO_ALG_AES256 (0x7 << 17) -+#define CONTEXT_CONTROL_CRYPTO_ALG_CHACHA20 (0x8 << 17) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SM4 (0xd << 17) -+#define CONTEXT_CONTROL_DIGEST_INITIAL (0x0 << 21) - #define CONTEXT_CONTROL_DIGEST_PRECOMPUTED (0x1 << 21) - #define CONTEXT_CONTROL_DIGEST_XCM (0x2 << 21) - #define CONTEXT_CONTROL_DIGEST_HMAC (0x3 << 21) - #define CONTEXT_CONTROL_CRYPTO_ALG_MD5 (0x0 << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_CRC32 (0x0 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_SHA1 (0x2 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_SHA224 (0x4 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_SHA256 (0x3 << 23) -@@ -371,17 +405,25 @@ struct safexcel_context_record { - #define CONTEXT_CONTROL_CRYPTO_ALG_XCBC128 (0x1 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_XCBC192 (0x2 << 23) - #define CONTEXT_CONTROL_CRYPTO_ALG_XCBC256 (0x3 << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SM3 (0x7 << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256 (0xb << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224 (0xc << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512 (0xd << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384 (0xe << 23) -+#define CONTEXT_CONTROL_CRYPTO_ALG_POLY1305 (0xf << 23) - #define CONTEXT_CONTROL_INV_FR (0x5 << 24) - #define CONTEXT_CONTROL_INV_TR (0x6 << 24) - - /* control1 */ - #define CONTEXT_CONTROL_CRYPTO_MODE_ECB (0 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_CBC (1 << 0) -+#define CONTEXT_CONTROL_CHACHA20_MODE_256_32 (2 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_OFB (4 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_CFB (5 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_CTR_LOAD (6 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_XTS (7 << 0) - #define CONTEXT_CONTROL_CRYPTO_MODE_XCM ((6 << 0) | BIT(17)) -+#define CONTEXT_CONTROL_CHACHA20_MODE_CALC_OTK (12 << 0) - #define CONTEXT_CONTROL_IV0 BIT(5) - #define CONTEXT_CONTROL_IV1 BIT(6) - #define CONTEXT_CONTROL_IV2 BIT(7) -@@ -394,6 +436,13 @@ struct safexcel_context_record { - #define EIP197_XCM_MODE_GCM 1 - #define EIP197_XCM_MODE_CCM 2 - -+#define EIP197_AEAD_TYPE_IPSEC_ESP 2 -+#define EIP197_AEAD_TYPE_IPSEC_ESP_GMAC 3 -+#define EIP197_AEAD_IPSEC_IV_SIZE 8 -+#define EIP197_AEAD_IPSEC_NONCE_SIZE 4 -+#define EIP197_AEAD_IPSEC_COUNTER_SIZE 4 -+#define EIP197_AEAD_IPSEC_CCM_NONCE_SIZE 3 -+ - /* The hash counter given to the engine in the context has a granularity of - * 64 bits. - */ -@@ -423,6 +472,8 @@ struct safexcel_context_record { - #define EIP197_TRC_PARAMS2_RC_SZ_SMALL(n) ((n) << 18) - - /* Cache helpers */ -+#define EIP197_MIN_DSIZE 1024 -+#define EIP197_MIN_ASIZE 8 - #define EIP197_CS_TRC_REC_WC 64 - #define EIP197_CS_RC_SIZE (4 * sizeof(u32)) - #define EIP197_CS_RC_NEXT(x) (x) -@@ -447,7 +498,7 @@ struct result_data_desc { - u16 application_id; - u16 rsvd1; - -- u32 rsvd2; -+ u32 rsvd2[5]; - } __packed; - - -@@ -465,16 +516,15 @@ struct safexcel_result_desc { - - u32 data_lo; - u32 data_hi; -- -- struct result_data_desc result_data; - } __packed; - - /* - * The EIP(1)97 only needs to fetch the descriptor part of - * the result descriptor, not the result token part! - */ --#define EIP197_RD64_FETCH_SIZE ((sizeof(struct safexcel_result_desc) -\ -- sizeof(struct result_data_desc)) /\ -+#define EIP197_RD64_FETCH_SIZE (sizeof(struct safexcel_result_desc) /\ -+ sizeof(u32)) -+#define EIP197_RD64_RESULT_SIZE (sizeof(struct result_data_desc) /\ - sizeof(u32)) - - struct safexcel_token { -@@ -505,6 +555,8 @@ static inline void eip197_noop_token(str - { - token->opcode = EIP197_TOKEN_OPCODE_NOOP; - token->packet_length = BIT(2); -+ token->stat = 0; -+ token->instructions = 0; - } - - /* Instructions */ -@@ -526,14 +578,13 @@ struct safexcel_control_data_desc { - u16 application_id; - u16 rsvd; - -- u8 refresh:2; -- u32 context_lo:30; -+ u32 context_lo; - u32 context_hi; - - u32 control0; - u32 control1; - -- u32 token[EIP197_MAX_TOKENS]; -+ u32 token[EIP197_EMB_TOKENS]; - } __packed; - - #define EIP197_OPTION_MAGIC_VALUE BIT(0) -@@ -543,7 +594,10 @@ struct safexcel_control_data_desc { - #define EIP197_OPTION_2_TOKEN_IV_CMD GENMASK(11, 10) - #define EIP197_OPTION_4_TOKEN_IV_CMD GENMASK(11, 9) - -+#define EIP197_TYPE_BCLA 0x0 - #define EIP197_TYPE_EXTENDED 0x3 -+#define EIP197_CONTEXT_SMALL 0x2 -+#define EIP197_CONTEXT_SIZE_MASK 0x3 - - /* Basic Command Descriptor format */ - struct safexcel_command_desc { -@@ -551,16 +605,22 @@ struct safexcel_command_desc { - u8 rsvd0:5; - u8 last_seg:1; - u8 first_seg:1; -- u16 additional_cdata_size:8; -+ u8 additional_cdata_size:8; - - u32 rsvd1; - - u32 data_lo; - u32 data_hi; - -+ u32 atok_lo; -+ u32 atok_hi; -+ - struct safexcel_control_data_desc control_data; - } __packed; - -+#define EIP197_CD64_FETCH_SIZE (sizeof(struct safexcel_command_desc) /\ -+ sizeof(u32)) -+ - /* - * Internal structures & functions - */ -@@ -578,15 +638,20 @@ enum eip197_fw { - - struct safexcel_desc_ring { - void *base; -+ void *shbase; - void *base_end; -+ void *shbase_end; - dma_addr_t base_dma; -+ dma_addr_t shbase_dma; - - /* write and read pointers */ - void *write; -+ void *shwrite; - void *read; - - /* descriptor element offset */ -- unsigned offset; -+ unsigned int offset; -+ unsigned int shoffset; - }; - - enum safexcel_alg_type { -@@ -601,9 +666,11 @@ struct safexcel_config { - - u32 cd_size; - u32 cd_offset; -+ u32 cdsh_offset; - - u32 rd_size; - u32 rd_offset; -+ u32 res_offset; - }; - - struct safexcel_work_data { -@@ -654,6 +721,12 @@ enum safexcel_eip_version { - /* Priority we use for advertising our algorithms */ - #define SAFEXCEL_CRA_PRIORITY 300 - -+/* SM3 digest result for zero length message */ -+#define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ -+ "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ -+ "\x22\xBE\xC8\xC7\x28\xFE\xFB\x74" \ -+ "\x7E\xD0\x35\xEB\x50\x82\xAA\x2B" -+ - /* EIP algorithm presence flags */ - enum safexcel_eip_algorithms { - SAFEXCEL_ALG_BC0 = BIT(5), -@@ -697,16 +770,23 @@ struct safexcel_register_offsets { - enum safexcel_flags { - EIP197_TRC_CACHE = BIT(0), - SAFEXCEL_HW_EIP197 = BIT(1), -+ EIP197_PE_ARB = BIT(2), -+ EIP197_ICE = BIT(3), -+ EIP197_SIMPLE_TRC = BIT(4), - }; - - struct safexcel_hwconfig { - enum safexcel_eip_algorithms algo_flags; - int hwver; - int hiaver; -+ int ppver; - int pever; - int hwdataw; - int hwcfsize; - int hwrfsize; -+ int hwnumpes; -+ int hwnumrings; -+ int hwnumraic; - }; - - struct safexcel_crypto_priv { -@@ -778,7 +858,7 @@ struct safexcel_inv_result { - - void safexcel_dequeue(struct safexcel_crypto_priv *priv, int ring); - int safexcel_rdesc_check_errors(struct safexcel_crypto_priv *priv, -- struct safexcel_result_desc *rdesc); -+ void *rdp); - void safexcel_complete(struct safexcel_crypto_priv *priv, int ring); - int safexcel_invalidate_cache(struct crypto_async_request *async, - struct safexcel_crypto_priv *priv, -@@ -797,7 +877,8 @@ struct safexcel_command_desc *safexcel_a - bool first, bool last, - dma_addr_t data, u32 len, - u32 full_data_len, -- dma_addr_t context); -+ dma_addr_t context, -+ struct safexcel_token **atoken); - struct safexcel_result_desc *safexcel_add_rdesc(struct safexcel_crypto_priv *priv, - int ring_id, - bool first, bool last, -@@ -853,5 +934,43 @@ extern struct safexcel_alg_template safe - extern struct safexcel_alg_template safexcel_alg_xts_aes; - extern struct safexcel_alg_template safexcel_alg_gcm; - extern struct safexcel_alg_template safexcel_alg_ccm; -+extern struct safexcel_alg_template safexcel_alg_crc32; -+extern struct safexcel_alg_template safexcel_alg_cbcmac; -+extern struct safexcel_alg_template safexcel_alg_xcbcmac; -+extern struct safexcel_alg_template safexcel_alg_cmac; -+extern struct safexcel_alg_template safexcel_alg_chacha20; -+extern struct safexcel_alg_template safexcel_alg_chachapoly; -+extern struct safexcel_alg_template safexcel_alg_chachapoly_esp; -+extern struct safexcel_alg_template safexcel_alg_sm3; -+extern struct safexcel_alg_template safexcel_alg_hmac_sm3; -+extern struct safexcel_alg_template safexcel_alg_ecb_sm4; -+extern struct safexcel_alg_template safexcel_alg_cbc_sm4; -+extern struct safexcel_alg_template safexcel_alg_ofb_sm4; -+extern struct safexcel_alg_template safexcel_alg_cfb_sm4; -+extern struct safexcel_alg_template safexcel_alg_ctr_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_cbc_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_ctr_sm4; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sm3_ctr_sm4; -+extern struct safexcel_alg_template safexcel_alg_sha3_224; -+extern struct safexcel_alg_template safexcel_alg_sha3_256; -+extern struct safexcel_alg_template safexcel_alg_sha3_384; -+extern struct safexcel_alg_template safexcel_alg_sha3_512; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_224; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_256; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_384; -+extern struct safexcel_alg_template safexcel_alg_hmac_sha3_512; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha1_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des3_ede; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha256_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha224_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha384_cbc_des; -+extern struct safexcel_alg_template safexcel_alg_rfc4106_gcm; -+extern struct safexcel_alg_template safexcel_alg_rfc4543_gcm; -+extern struct safexcel_alg_template safexcel_alg_rfc4309_ccm; - - #endif ---- a/drivers/crypto/inside-secure/safexcel_hash.c -+++ b/drivers/crypto/inside-secure/safexcel_hash.c -@@ -5,9 +5,13 @@ - * Antoine Tenart <antoine.tenart@free-electrons.com> - */ - -+#include <crypto/aes.h> - #include <crypto/hmac.h> - #include <crypto/md5.h> - #include <crypto/sha.h> -+#include <crypto/sha3.h> -+#include <crypto/skcipher.h> -+#include <crypto/sm3.h> - #include <linux/device.h> - #include <linux/dma-mapping.h> - #include <linux/dmapool.h> -@@ -19,9 +23,19 @@ struct safexcel_ahash_ctx { - struct safexcel_crypto_priv *priv; - - u32 alg; -- -- u32 ipad[SHA512_DIGEST_SIZE / sizeof(u32)]; -- u32 opad[SHA512_DIGEST_SIZE / sizeof(u32)]; -+ u8 key_sz; -+ bool cbcmac; -+ bool do_fallback; -+ bool fb_init_done; -+ bool fb_do_setkey; -+ -+ __le32 ipad[SHA3_512_BLOCK_SIZE / sizeof(__le32)]; -+ __le32 opad[SHA3_512_BLOCK_SIZE / sizeof(__le32)]; -+ -+ struct crypto_cipher *kaes; -+ struct crypto_ahash *fback; -+ struct crypto_shash *shpre; -+ struct shash_desc *shdesc; - }; - - struct safexcel_ahash_req { -@@ -31,6 +45,8 @@ struct safexcel_ahash_req { - bool needs_inv; - bool hmac_zlen; - bool len_is_le; -+ bool not_first; -+ bool xcbcmac; - - int nents; - dma_addr_t result_dma; -@@ -39,7 +55,9 @@ struct safexcel_ahash_req { - - u8 state_sz; /* expected state size, only set once */ - u8 block_sz; /* block size, only set once */ -- u32 state[SHA512_DIGEST_SIZE / sizeof(u32)] __aligned(sizeof(u32)); -+ u8 digest_sz; /* output digest size, only set once */ -+ __le32 state[SHA3_512_BLOCK_SIZE / -+ sizeof(__le32)] __aligned(sizeof(__le32)); - - u64 len; - u64 processed; -@@ -57,22 +75,36 @@ static inline u64 safexcel_queued_len(st - } - - static void safexcel_hash_token(struct safexcel_command_desc *cdesc, -- u32 input_length, u32 result_length) -+ u32 input_length, u32 result_length, -+ bool cbcmac) - { - struct safexcel_token *token = - (struct safexcel_token *)cdesc->control_data.token; - - token[0].opcode = EIP197_TOKEN_OPCODE_DIRECTION; - token[0].packet_length = input_length; -- token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; - token[0].instructions = EIP197_TOKEN_INS_TYPE_HASH; - -- token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; -- token[1].packet_length = result_length; -- token[1].stat = EIP197_TOKEN_STAT_LAST_HASH | -+ input_length &= 15; -+ if (unlikely(cbcmac && input_length)) { -+ token[0].stat = 0; -+ token[1].opcode = EIP197_TOKEN_OPCODE_INSERT; -+ token[1].packet_length = 16 - input_length; -+ token[1].stat = EIP197_TOKEN_STAT_LAST_HASH; -+ token[1].instructions = EIP197_TOKEN_INS_TYPE_HASH; -+ } else { -+ token[0].stat = EIP197_TOKEN_STAT_LAST_HASH; -+ eip197_noop_token(&token[1]); -+ } -+ -+ token[2].opcode = EIP197_TOKEN_OPCODE_INSERT; -+ token[2].stat = EIP197_TOKEN_STAT_LAST_HASH | - EIP197_TOKEN_STAT_LAST_PACKET; -- token[1].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | -+ token[2].packet_length = result_length; -+ token[2].instructions = EIP197_TOKEN_INS_TYPE_OUTPUT | - EIP197_TOKEN_INS_INSERT_HASH_DIGEST; -+ -+ eip197_noop_token(&token[3]); - } - - static void safexcel_context_control(struct safexcel_ahash_ctx *ctx, -@@ -82,29 +114,49 @@ static void safexcel_context_control(str - struct safexcel_crypto_priv *priv = ctx->priv; - u64 count = 0; - -- cdesc->control_data.control0 |= ctx->alg; -+ cdesc->control_data.control0 = ctx->alg; -+ cdesc->control_data.control1 = 0; - - /* - * Copy the input digest if needed, and setup the context - * fields. Do this now as we need it to setup the first command - * descriptor. - */ -- if (!req->processed) { -- /* First - and possibly only - block of basic hash only */ -- if (req->finish) { -+ if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) { -+ if (req->xcbcmac) -+ memcpy(ctx->base.ctxr->data, ctx->ipad, ctx->key_sz); -+ else -+ memcpy(ctx->base.ctxr->data, req->state, req->state_sz); -+ -+ if (!req->finish && req->xcbcmac) -+ cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_DIGEST_XCM | -+ CONTEXT_CONTROL_TYPE_HASH_OUT | -+ CONTEXT_CONTROL_NO_FINISH_HASH | -+ CONTEXT_CONTROL_SIZE(req->state_sz / -+ sizeof(u32)); -+ else - cdesc->control_data.control0 |= -+ CONTEXT_CONTROL_DIGEST_XCM | -+ CONTEXT_CONTROL_TYPE_HASH_OUT | -+ CONTEXT_CONTROL_SIZE(req->state_sz / -+ sizeof(u32)); -+ return; -+ } else if (!req->processed) { -+ /* First - and possibly only - block of basic hash only */ -+ if (req->finish) -+ cdesc->control_data.control0 |= req->digest | - CONTEXT_CONTROL_TYPE_HASH_OUT | - CONTEXT_CONTROL_RESTART_HASH | - /* ensure its not 0! */ - CONTEXT_CONTROL_SIZE(1); -- } else { -- cdesc->control_data.control0 |= -+ else -+ cdesc->control_data.control0 |= req->digest | - CONTEXT_CONTROL_TYPE_HASH_OUT | - CONTEXT_CONTROL_RESTART_HASH | - CONTEXT_CONTROL_NO_FINISH_HASH | - /* ensure its not 0! */ - CONTEXT_CONTROL_SIZE(1); -- } - return; - } - -@@ -204,7 +256,7 @@ static int safexcel_handle_req_result(st - } - - if (sreq->result_dma) { -- dma_unmap_single(priv->dev, sreq->result_dma, sreq->state_sz, -+ dma_unmap_single(priv->dev, sreq->result_dma, sreq->digest_sz, - DMA_FROM_DEVICE); - sreq->result_dma = 0; - } -@@ -223,14 +275,15 @@ static int safexcel_handle_req_result(st - memcpy(sreq->cache, sreq->state, - crypto_ahash_digestsize(ahash)); - -- memcpy(sreq->state, ctx->opad, sreq->state_sz); -+ memcpy(sreq->state, ctx->opad, sreq->digest_sz); - - sreq->len = sreq->block_sz + - crypto_ahash_digestsize(ahash); - sreq->processed = sreq->block_sz; - sreq->hmac = 0; - -- ctx->base.needs_inv = true; -+ if (priv->flags & EIP197_TRC_CACHE) -+ ctx->base.needs_inv = true; - areq->nbytes = 0; - safexcel_ahash_enqueue(areq); - -@@ -238,8 +291,14 @@ static int safexcel_handle_req_result(st - return 1; - } - -- memcpy(areq->result, sreq->state, -- crypto_ahash_digestsize(ahash)); -+ if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM && -+ ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_CRC32)) { -+ /* Undo final XOR with 0xffffffff ...*/ -+ *(__le32 *)areq->result = ~sreq->state[0]; -+ } else { -+ memcpy(areq->result, sreq->state, -+ crypto_ahash_digestsize(ahash)); -+ } - } - - cache_len = safexcel_queued_len(sreq); -@@ -261,10 +320,11 @@ static int safexcel_ahash_send_req(struc - struct safexcel_command_desc *cdesc, *first_cdesc = NULL; - struct safexcel_result_desc *rdesc; - struct scatterlist *sg; -- int i, extra = 0, n_cdesc = 0, ret = 0; -- u64 queued, len, cache_len; -+ struct safexcel_token *dmmy; -+ int i, extra = 0, n_cdesc = 0, ret = 0, cache_len, skip = 0; -+ u64 queued, len; - -- queued = len = safexcel_queued_len(req); -+ queued = safexcel_queued_len(req); - if (queued <= HASH_CACHE_SIZE) - cache_len = queued; - else -@@ -287,15 +347,52 @@ static int safexcel_ahash_send_req(struc - areq->nbytes - extra); - - queued -= extra; -- len -= extra; - - if (!queued) { - *commands = 0; - *results = 0; - return 0; - } -+ -+ extra = 0; -+ } -+ -+ if (unlikely(req->xcbcmac && req->processed > AES_BLOCK_SIZE)) { -+ if (unlikely(cache_len < AES_BLOCK_SIZE)) { -+ /* -+ * Cache contains less than 1 full block, complete. -+ */ -+ extra = AES_BLOCK_SIZE - cache_len; -+ if (queued > cache_len) { -+ /* More data follows: borrow bytes */ -+ u64 tmp = queued - cache_len; -+ -+ skip = min_t(u64, tmp, extra); -+ sg_pcopy_to_buffer(areq->src, -+ sg_nents(areq->src), -+ req->cache + cache_len, -+ skip, 0); -+ } -+ extra -= skip; -+ memset(req->cache + cache_len + skip, 0, extra); -+ if (!ctx->cbcmac && extra) { -+ // 10- padding for XCBCMAC & CMAC -+ req->cache[cache_len + skip] = 0x80; -+ // HW will use K2 iso K3 - compensate! -+ for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) -+ ((__be32 *)req->cache)[i] ^= -+ cpu_to_be32(le32_to_cpu( -+ ctx->ipad[i] ^ ctx->ipad[i + 4])); -+ } -+ cache_len = AES_BLOCK_SIZE; -+ queued = queued + extra; -+ } -+ -+ /* XCBC continue: XOR previous result into 1st word */ -+ crypto_xor(req->cache, (const u8 *)req->state, AES_BLOCK_SIZE); - } - -+ len = queued; - /* Add a command descriptor for the cached data, if any */ - if (cache_len) { - req->cache_dma = dma_map_single(priv->dev, req->cache, -@@ -306,8 +403,9 @@ static int safexcel_ahash_send_req(struc - req->cache_sz = cache_len; - first_cdesc = safexcel_add_cdesc(priv, ring, 1, - (cache_len == len), -- req->cache_dma, cache_len, len, -- ctx->base.ctxr_dma); -+ req->cache_dma, cache_len, -+ len, ctx->base.ctxr_dma, -+ &dmmy); - if (IS_ERR(first_cdesc)) { - ret = PTR_ERR(first_cdesc); - goto unmap_cache; -@@ -319,10 +417,6 @@ static int safexcel_ahash_send_req(struc - goto send_command; - } - -- /* Skip descriptor generation for zero-length requests */ -- if (!areq->nbytes) -- goto send_command; -- - /* Now handle the current ahash request buffer(s) */ - req->nents = dma_map_sg(priv->dev, areq->src, - sg_nents_for_len(areq->src, -@@ -336,26 +430,34 @@ static int safexcel_ahash_send_req(struc - for_each_sg(areq->src, sg, req->nents, i) { - int sglen = sg_dma_len(sg); - -+ if (unlikely(sglen <= skip)) { -+ skip -= sglen; -+ continue; -+ } -+ - /* Do not overflow the request */ -- if (queued < sglen) -+ if ((queued + skip) <= sglen) - sglen = queued; -+ else -+ sglen -= skip; - - cdesc = safexcel_add_cdesc(priv, ring, !n_cdesc, - !(queued - sglen), -- sg_dma_address(sg), -- sglen, len, ctx->base.ctxr_dma); -+ sg_dma_address(sg) + skip, sglen, -+ len, ctx->base.ctxr_dma, &dmmy); - if (IS_ERR(cdesc)) { - ret = PTR_ERR(cdesc); - goto unmap_sg; - } -- n_cdesc++; - -- if (n_cdesc == 1) -+ if (!n_cdesc) - first_cdesc = cdesc; -+ n_cdesc++; - - queued -= sglen; - if (!queued) - break; -+ skip = 0; - } - - send_command: -@@ -363,9 +465,9 @@ send_command: - safexcel_context_control(ctx, req, first_cdesc); - - /* Add the token */ -- safexcel_hash_token(first_cdesc, len, req->state_sz); -+ safexcel_hash_token(first_cdesc, len, req->digest_sz, ctx->cbcmac); - -- req->result_dma = dma_map_single(priv->dev, req->state, req->state_sz, -+ req->result_dma = dma_map_single(priv->dev, req->state, req->digest_sz, - DMA_FROM_DEVICE); - if (dma_mapping_error(priv->dev, req->result_dma)) { - ret = -EINVAL; -@@ -374,7 +476,7 @@ send_command: - - /* Add a result descriptor */ - rdesc = safexcel_add_rdesc(priv, ring, 1, 1, req->result_dma, -- req->state_sz); -+ req->digest_sz); - if (IS_ERR(rdesc)) { - ret = PTR_ERR(rdesc); - goto unmap_result; -@@ -382,17 +484,20 @@ send_command: - - safexcel_rdr_req_set(priv, ring, rdesc, &areq->base); - -- req->processed += len; -+ req->processed += len - extra; - - *commands = n_cdesc; - *results = 1; - return 0; - - unmap_result: -- dma_unmap_single(priv->dev, req->result_dma, req->state_sz, -+ dma_unmap_single(priv->dev, req->result_dma, req->digest_sz, - DMA_FROM_DEVICE); - unmap_sg: -- dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); -+ if (req->nents) { -+ dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); -+ req->nents = 0; -+ } - cdesc_rollback: - for (i = 0; i < n_cdesc; i++) - safexcel_ring_rollback_wptr(priv, &priv->ring[ring].cdr); -@@ -590,16 +695,12 @@ static int safexcel_ahash_enqueue(struct - - if (ctx->base.ctxr) { - if (priv->flags & EIP197_TRC_CACHE && !ctx->base.needs_inv && -- req->processed && -- (/* invalidate for basic hash continuation finish */ -- (req->finish && -- (req->digest == CONTEXT_CONTROL_DIGEST_PRECOMPUTED)) || -+ /* invalidate for *any* non-XCBC continuation */ -+ ((req->not_first && !req->xcbcmac) || - /* invalidate if (i)digest changed */ - memcmp(ctx->base.ctxr->data, req->state, req->state_sz) || -- /* invalidate for HMAC continuation finish */ -- (req->finish && (req->processed != req->block_sz)) || - /* invalidate for HMAC finish with odigest changed */ -- (req->finish && -+ (req->finish && req->hmac && - memcmp(ctx->base.ctxr->data + (req->state_sz>>2), - ctx->opad, req->state_sz)))) - /* -@@ -622,6 +723,7 @@ static int safexcel_ahash_enqueue(struct - if (!ctx->base.ctxr) - return -ENOMEM; - } -+ req->not_first = true; - - ring = ctx->base.ring; - -@@ -691,8 +793,34 @@ static int safexcel_ahash_final(struct a - else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SHA512) - memcpy(areq->result, sha512_zero_message_hash, - SHA512_DIGEST_SIZE); -+ else if (ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_SM3) { -+ memcpy(areq->result, -+ EIP197_SM3_ZEROM_HASH, SM3_DIGEST_SIZE); -+ } - - return 0; -+ } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM && -+ ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 && -+ req->len == sizeof(u32) && !areq->nbytes)) { -+ /* Zero length CRC32 */ -+ memcpy(areq->result, ctx->ipad, sizeof(u32)); -+ return 0; -+ } else if (unlikely(ctx->cbcmac && req->len == AES_BLOCK_SIZE && -+ !areq->nbytes)) { -+ /* Zero length CBC MAC */ -+ memset(areq->result, 0, AES_BLOCK_SIZE); -+ return 0; -+ } else if (unlikely(req->xcbcmac && req->len == AES_BLOCK_SIZE && -+ !areq->nbytes)) { -+ /* Zero length (X)CBC/CMAC */ -+ int i; -+ -+ for (i = 0; i < AES_BLOCK_SIZE / sizeof(u32); i++) -+ ((__be32 *)areq->result)[i] = -+ cpu_to_be32(le32_to_cpu(ctx->ipad[i + 4]));//K3 -+ areq->result[0] ^= 0x80; // 10- padding -+ crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result); -+ return 0; - } else if (unlikely(req->hmac && - (req->len == req->block_sz) && - !areq->nbytes)) { -@@ -792,6 +920,7 @@ static int safexcel_ahash_cra_init(struc - ctx->priv = tmpl->priv; - ctx->base.send = safexcel_ahash_send; - ctx->base.handle_result = safexcel_handle_result; -+ ctx->fb_do_setkey = false; - - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct safexcel_ahash_req)); -@@ -808,6 +937,7 @@ static int safexcel_sha1_init(struct aha - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA1_DIGEST_SIZE; -+ req->digest_sz = SHA1_DIGEST_SIZE; - req->block_sz = SHA1_BLOCK_SIZE; - - return 0; -@@ -889,6 +1019,7 @@ static int safexcel_hmac_sha1_init(struc - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA1; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA1_DIGEST_SIZE; -+ req->digest_sz = SHA1_DIGEST_SIZE; - req->block_sz = SHA1_BLOCK_SIZE; - req->hmac = true; - -@@ -1125,6 +1256,7 @@ static int safexcel_sha256_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - - return 0; -@@ -1180,6 +1312,7 @@ static int safexcel_sha224_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - - return 0; -@@ -1248,6 +1381,7 @@ static int safexcel_hmac_sha224_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA224; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - req->hmac = true; - -@@ -1318,6 +1452,7 @@ static int safexcel_hmac_sha256_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA256; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA256_DIGEST_SIZE; -+ req->digest_sz = SHA256_DIGEST_SIZE; - req->block_sz = SHA256_BLOCK_SIZE; - req->hmac = true; - -@@ -1375,6 +1510,7 @@ static int safexcel_sha512_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - - return 0; -@@ -1430,6 +1566,7 @@ static int safexcel_sha384_init(struct a - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - - return 0; -@@ -1498,6 +1635,7 @@ static int safexcel_hmac_sha512_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA512; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - req->hmac = true; - -@@ -1568,6 +1706,7 @@ static int safexcel_hmac_sha384_init(str - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA384; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = SHA512_DIGEST_SIZE; -+ req->digest_sz = SHA512_DIGEST_SIZE; - req->block_sz = SHA512_BLOCK_SIZE; - req->hmac = true; - -@@ -1625,6 +1764,7 @@ static int safexcel_md5_init(struct ahas - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = MD5_DIGEST_SIZE; -+ req->digest_sz = MD5_DIGEST_SIZE; - req->block_sz = MD5_HMAC_BLOCK_SIZE; - - return 0; -@@ -1686,6 +1826,7 @@ static int safexcel_hmac_md5_init(struct - ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_MD5; - req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; - req->state_sz = MD5_DIGEST_SIZE; -+ req->digest_sz = MD5_DIGEST_SIZE; - req->block_sz = MD5_HMAC_BLOCK_SIZE; - req->len_is_le = true; /* MD5 is little endian! ... */ - req->hmac = true; -@@ -1738,5 +1879,1235 @@ struct safexcel_alg_template safexcel_al - .cra_module = THIS_MODULE, - }, - }, -+ }, -+}; -+ -+static int safexcel_crc32_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret = safexcel_ahash_cra_init(tfm); -+ -+ /* Default 'key' is all zeroes */ -+ memset(ctx->ipad, 0, sizeof(u32)); -+ return ret; -+} -+ -+static int safexcel_crc32_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Start from loaded key */ -+ req->state[0] = (__force __le32)le32_to_cpu(~ctx->ipad[0]); -+ /* Set processed to non-zero to enable invalidation detection */ -+ req->len = sizeof(u32); -+ req->processed = sizeof(u32); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32; -+ req->digest = CONTEXT_CONTROL_DIGEST_XCM; -+ req->state_sz = sizeof(u32); -+ req->digest_sz = sizeof(u32); -+ req->block_sz = sizeof(u32); -+ -+ return 0; -+} -+ -+static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int keylen) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ -+ if (keylen != sizeof(u32)) -+ return -EINVAL; -+ -+ memcpy(ctx->ipad, key, sizeof(u32)); -+ return 0; -+} -+ -+static int safexcel_crc32_digest(struct ahash_request *areq) -+{ -+ return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_crc32 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_crc32_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_crc32_digest, -+ .setkey = safexcel_crc32_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = sizeof(u32), -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "crc32", -+ .cra_driver_name = "safexcel-crc32", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY | -+ CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_crc32_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_cbcmac_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Start from loaded keys */ -+ memcpy(req->state, ctx->ipad, ctx->key_sz); -+ /* Set processed to non-zero to enable invalidation detection */ -+ req->len = AES_BLOCK_SIZE; -+ req->processed = AES_BLOCK_SIZE; -+ -+ req->digest = CONTEXT_CONTROL_DIGEST_XCM; -+ req->state_sz = ctx->key_sz; -+ req->digest_sz = AES_BLOCK_SIZE; -+ req->block_sz = AES_BLOCK_SIZE; -+ req->xcbcmac = true; -+ -+ return 0; -+} -+ -+static int safexcel_cbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int len) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ struct crypto_aes_ctx aes; -+ int ret, i; -+ -+ ret = aes_expandkey(&aes, key, len); -+ if (ret) -+ return ret; -+ -+ memset(ctx->ipad, 0, 2 * AES_BLOCK_SIZE); -+ for (i = 0; i < len / sizeof(u32); i++) -+ ctx->ipad[i + 8] = (__force __le32)cpu_to_be32(aes.key_enc[i]); -+ -+ if (len == AES_KEYSIZE_192) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else if (len == AES_KEYSIZE_256) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; -+ ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } -+ ctx->cbcmac = true; -+ -+ memzero_explicit(&aes, sizeof(aes)); -+ return 0; -+} -+ -+static int safexcel_cbcmac_digest(struct ahash_request *areq) -+{ -+ return safexcel_cbcmac_init(areq) ?: safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_cbcmac = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_cbcmac_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_cbcmac_digest, -+ .setkey = safexcel_cbcmac_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = AES_BLOCK_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "cbcmac(aes)", -+ .cra_driver_name = "safexcel-cbcmac-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_ahash_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int len) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ struct crypto_aes_ctx aes; -+ u32 key_tmp[3 * AES_BLOCK_SIZE / sizeof(u32)]; -+ int ret, i; -+ -+ ret = aes_expandkey(&aes, key, len); -+ if (ret) -+ return ret; -+ -+ /* precompute the XCBC key material */ -+ crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); -+ crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & -+ CRYPTO_TFM_REQ_MASK); -+ ret = crypto_cipher_setkey(ctx->kaes, key, len); -+ if (ret) -+ return ret; -+ -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, -+ "\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"); -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp, -+ "\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2\x2"); -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE, -+ "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); -+ for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) -+ ctx->ipad[i] = -+ cpu_to_le32((__force u32)cpu_to_be32(key_tmp[i])); -+ -+ crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); -+ crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & -+ CRYPTO_TFM_REQ_MASK); -+ ret = crypto_cipher_setkey(ctx->kaes, -+ (u8 *)key_tmp + 2 * AES_BLOCK_SIZE, -+ AES_MIN_KEY_SIZE); -+ if (ret) -+ return ret; -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; -+ ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ ctx->cbcmac = false; -+ -+ memzero_explicit(&aes, sizeof(aes)); -+ return 0; -+} -+ -+static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_ahash_cra_init(tfm); -+ ctx->kaes = crypto_alloc_cipher("aes", 0, 0); -+ return PTR_ERR_OR_ZERO(ctx->kaes); -+} -+ -+static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_cipher(ctx->kaes); -+ safexcel_ahash_cra_exit(tfm); -+} -+ -+struct safexcel_alg_template safexcel_alg_xcbcmac = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_cbcmac_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_cbcmac_digest, -+ .setkey = safexcel_xcbcmac_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = AES_BLOCK_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "xcbc(aes)", -+ .cra_driver_name = "safexcel-xcbc-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_xcbcmac_cra_init, -+ .cra_exit = safexcel_xcbcmac_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int len) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); -+ struct crypto_aes_ctx aes; -+ __be64 consts[4]; -+ u64 _const[2]; -+ u8 msb_mask, gfmask; -+ int ret, i; -+ -+ ret = aes_expandkey(&aes, key, len); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < len / sizeof(u32); i++) -+ ctx->ipad[i + 8] = -+ cpu_to_le32((__force u32)cpu_to_be32(aes.key_enc[i])); -+ -+ /* precompute the CMAC key material */ -+ crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); -+ crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & -+ CRYPTO_TFM_REQ_MASK); -+ ret = crypto_cipher_setkey(ctx->kaes, key, len); -+ if (ret) -+ return ret; -+ -+ /* code below borrowed from crypto/cmac.c */ -+ /* encrypt the zero block */ -+ memset(consts, 0, AES_BLOCK_SIZE); -+ crypto_cipher_encrypt_one(ctx->kaes, (u8 *)consts, (u8 *)consts); -+ -+ gfmask = 0x87; -+ _const[0] = be64_to_cpu(consts[1]); -+ _const[1] = be64_to_cpu(consts[0]); -+ -+ /* gf(2^128) multiply zero-ciphertext with u and u^2 */ -+ for (i = 0; i < 4; i += 2) { -+ msb_mask = ((s64)_const[1] >> 63) & gfmask; -+ _const[1] = (_const[1] << 1) | (_const[0] >> 63); -+ _const[0] = (_const[0] << 1) ^ msb_mask; -+ -+ consts[i + 0] = cpu_to_be64(_const[1]); -+ consts[i + 1] = cpu_to_be64(_const[0]); -+ } -+ /* end of code borrowed from crypto/cmac.c */ -+ -+ for (i = 0; i < 2 * AES_BLOCK_SIZE / sizeof(u32); i++) -+ ctx->ipad[i] = (__force __le32)cpu_to_be32(((u32 *)consts)[i]); -+ -+ if (len == AES_KEYSIZE_192) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC192; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else if (len == AES_KEYSIZE_256) { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC256; -+ ctx->key_sz = AES_MAX_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } else { -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_XCBC128; -+ ctx->key_sz = AES_MIN_KEY_SIZE + 2 * AES_BLOCK_SIZE; -+ } -+ ctx->cbcmac = false; -+ -+ memzero_explicit(&aes, sizeof(aes)); -+ return 0; -+} -+ -+struct safexcel_alg_template safexcel_alg_cmac = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = 0, -+ .alg.ahash = { -+ .init = safexcel_cbcmac_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_cbcmac_digest, -+ .setkey = safexcel_cmac_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = AES_BLOCK_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "cmac(aes)", -+ .cra_driver_name = "safexcel-cmac-aes", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_xcbcmac_cra_init, -+ .cra_exit = safexcel_xcbcmac_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sm3_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; -+ req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; -+ req->state_sz = SM3_DIGEST_SIZE; -+ req->digest_sz = SM3_DIGEST_SIZE; -+ req->block_sz = SM3_BLOCK_SIZE; -+ -+ return 0; -+} -+ -+static int safexcel_sm3_digest(struct ahash_request *areq) -+{ -+ int ret = safexcel_sm3_init(areq); -+ -+ if (ret) -+ return ret; -+ -+ return safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_sm3 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SM3, -+ .alg.ahash = { -+ .init = safexcel_sm3_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_sm3_digest, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = SM3_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sm3", -+ .cra_driver_name = "safexcel-sm3", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM3_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_ahash_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sm3_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int keylen) -+{ -+ return safexcel_hmac_alg_setkey(tfm, key, keylen, "safexcel-sm3", -+ SM3_DIGEST_SIZE); -+} -+ -+static int safexcel_hmac_sm3_init(struct ahash_request *areq) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq)); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Start from ipad precompute */ -+ memcpy(req->state, ctx->ipad, SM3_DIGEST_SIZE); -+ /* Already processed the key^ipad part now! */ -+ req->len = SM3_BLOCK_SIZE; -+ req->processed = SM3_BLOCK_SIZE; -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SM3; -+ req->digest = CONTEXT_CONTROL_DIGEST_PRECOMPUTED; -+ req->state_sz = SM3_DIGEST_SIZE; -+ req->digest_sz = SM3_DIGEST_SIZE; -+ req->block_sz = SM3_BLOCK_SIZE; -+ req->hmac = true; -+ -+ return 0; -+} -+ -+static int safexcel_hmac_sm3_digest(struct ahash_request *areq) -+{ -+ int ret = safexcel_hmac_sm3_init(areq); -+ -+ if (ret) -+ return ret; -+ -+ return safexcel_ahash_finup(areq); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sm3 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SM3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sm3_init, -+ .update = safexcel_ahash_update, -+ .final = safexcel_ahash_final, -+ .finup = safexcel_ahash_finup, -+ .digest = safexcel_hmac_sm3_digest, -+ .setkey = safexcel_hmac_sm3_setkey, -+ .export = safexcel_ahash_export, -+ .import = safexcel_ahash_import, -+ .halg = { -+ .digestsize = SM3_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sm3)", -+ .cra_driver_name = "safexcel-hmac-sm3", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY, -+ .cra_blocksize = SM3_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_ahash_cra_init, -+ .cra_exit = safexcel_ahash_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_224_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_224_DIGEST_SIZE; -+ req->digest_sz = SHA3_224_DIGEST_SIZE; -+ req->block_sz = SHA3_224_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_fbcheck(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ int ret = 0; -+ -+ if (ctx->do_fallback) { -+ ahash_request_set_tfm(subreq, ctx->fback); -+ ahash_request_set_callback(subreq, req->base.flags, -+ req->base.complete, req->base.data); -+ ahash_request_set_crypt(subreq, req->src, req->result, -+ req->nbytes); -+ if (!ctx->fb_init_done) { -+ if (ctx->fb_do_setkey) { -+ /* Set fallback cipher HMAC key */ -+ u8 key[SHA3_224_BLOCK_SIZE]; -+ -+ memcpy(key, ctx->ipad, -+ crypto_ahash_blocksize(ctx->fback) / 2); -+ memcpy(key + -+ crypto_ahash_blocksize(ctx->fback) / 2, -+ ctx->opad, -+ crypto_ahash_blocksize(ctx->fback) / 2); -+ ret = crypto_ahash_setkey(ctx->fback, key, -+ crypto_ahash_blocksize(ctx->fback)); -+ memzero_explicit(key, -+ crypto_ahash_blocksize(ctx->fback)); -+ ctx->fb_do_setkey = false; -+ } -+ ret = ret ?: crypto_ahash_init(subreq); -+ ctx->fb_init_done = true; -+ } -+ } -+ return ret; -+} -+ -+static int safexcel_sha3_update(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_update(subreq); -+} -+ -+static int safexcel_sha3_final(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_final(subreq); -+} -+ -+static int safexcel_sha3_finup(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback |= !req->nbytes; -+ if (ctx->do_fallback) -+ /* Update or ex/import happened or len 0, cannot use the HW */ -+ return safexcel_sha3_fbcheck(req) ?: -+ crypto_ahash_finup(subreq); -+ else -+ return safexcel_ahash_finup(req); -+} -+ -+static int safexcel_sha3_digest_fallback(struct ahash_request *req) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ ctx->fb_init_done = false; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_finup(subreq); -+} -+ -+static int safexcel_sha3_224_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_224_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_sha3_export(struct ahash_request *req, void *out) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_export(subreq, out); -+} -+ -+static int safexcel_sha3_import(struct ahash_request *req, const void *in) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct ahash_request *subreq = ahash_request_ctx(req); -+ -+ ctx->do_fallback = true; -+ return safexcel_sha3_fbcheck(req) ?: crypto_ahash_import(subreq, in); -+ // return safexcel_ahash_import(req, in); -+} -+ -+static int safexcel_sha3_cra_init(struct crypto_tfm *tfm) -+{ -+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ safexcel_ahash_cra_init(tfm); -+ -+ /* Allocate fallback implementation */ -+ ctx->fback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, -+ CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->fback)) -+ return PTR_ERR(ctx->fback); -+ -+ /* Update statesize from fallback algorithm! */ -+ crypto_hash_alg_common(ahash)->statesize = -+ crypto_ahash_statesize(ctx->fback); -+ crypto_ahash_set_reqsize(ahash, max(sizeof(struct safexcel_ahash_req), -+ sizeof(struct ahash_request) + -+ crypto_ahash_reqsize(ctx->fback))); -+ return 0; -+} -+ -+static void safexcel_sha3_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_ahash(ctx->fback); -+ safexcel_ahash_cra_exit(tfm); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_224 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_224_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_224_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_224_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-224", -+ .cra_driver_name = "safexcel-sha3-224", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_224_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_256_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_256_DIGEST_SIZE; -+ req->digest_sz = SHA3_256_DIGEST_SIZE; -+ req->block_sz = SHA3_256_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_256_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_256_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_256 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_256_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_256_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_256_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-256", -+ .cra_driver_name = "safexcel-sha3-256", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_256_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_384_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_384_DIGEST_SIZE; -+ req->digest_sz = SHA3_384_DIGEST_SIZE; -+ req->block_sz = SHA3_384_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_384_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_384_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_384 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_384_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_384_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_384_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-384", -+ .cra_driver_name = "safexcel-sha3-384", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_sha3_512_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; -+ req->digest = CONTEXT_CONTROL_DIGEST_INITIAL; -+ req->state_sz = SHA3_512_DIGEST_SIZE; -+ req->digest_sz = SHA3_512_DIGEST_SIZE; -+ req->block_sz = SHA3_512_BLOCK_SIZE; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_sha3_512_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_sha3_512_init(req) ?: safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length hash, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+struct safexcel_alg_template safexcel_alg_sha3_512 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_sha3_512_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_sha3_512_digest, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_512_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "sha3-512", -+ .cra_driver_name = "safexcel-sha3-512", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_sha3_cra_init, -+ .cra_exit = safexcel_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_cra_init(struct crypto_tfm *tfm, const char *alg) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = safexcel_sha3_cra_init(tfm); -+ if (ret) -+ return ret; -+ -+ /* Allocate precalc basic digest implementation */ -+ ctx->shpre = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); -+ if (IS_ERR(ctx->shpre)) -+ return PTR_ERR(ctx->shpre); -+ -+ ctx->shdesc = kmalloc(sizeof(*ctx->shdesc) + -+ crypto_shash_descsize(ctx->shpre), GFP_KERNEL); -+ if (!ctx->shdesc) { -+ crypto_free_shash(ctx->shpre); -+ return -ENOMEM; -+ } -+ ctx->shdesc->tfm = ctx->shpre; -+ return 0; -+} -+ -+static void safexcel_hmac_sha3_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ crypto_free_ahash(ctx->fback); -+ crypto_free_shash(ctx->shpre); -+ kfree(ctx->shdesc); -+ safexcel_ahash_cra_exit(tfm); -+} -+ -+static int safexcel_hmac_sha3_setkey(struct crypto_ahash *tfm, const u8 *key, -+ unsigned int keylen) -+{ -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ int ret = 0; -+ -+ if (keylen > crypto_ahash_blocksize(tfm)) { -+ /* -+ * If the key is larger than the blocksize, then hash it -+ * first using our fallback cipher -+ */ -+ ret = crypto_shash_digest(ctx->shdesc, key, keylen, -+ (u8 *)ctx->ipad); -+ keylen = crypto_shash_digestsize(ctx->shpre); -+ -+ /* -+ * If the digest is larger than half the blocksize, we need to -+ * move the rest to opad due to the way our HMAC infra works. -+ */ -+ if (keylen > crypto_ahash_blocksize(tfm) / 2) -+ /* Buffers overlap, need to use memmove iso memcpy! */ -+ memmove(ctx->opad, -+ (u8 *)ctx->ipad + -+ crypto_ahash_blocksize(tfm) / 2, -+ keylen - crypto_ahash_blocksize(tfm) / 2); -+ } else { -+ /* -+ * Copy the key to our ipad & opad buffers -+ * Note that ipad and opad each contain one half of the key, -+ * to match the existing HMAC driver infrastructure. -+ */ -+ if (keylen <= crypto_ahash_blocksize(tfm) / 2) { -+ memcpy(ctx->ipad, key, keylen); -+ } else { -+ memcpy(ctx->ipad, key, -+ crypto_ahash_blocksize(tfm) / 2); -+ memcpy(ctx->opad, -+ key + crypto_ahash_blocksize(tfm) / 2, -+ keylen - crypto_ahash_blocksize(tfm) / 2); -+ } -+ } -+ -+ /* Pad key with zeroes */ -+ if (keylen <= crypto_ahash_blocksize(tfm) / 2) { -+ memset((u8 *)ctx->ipad + keylen, 0, -+ crypto_ahash_blocksize(tfm) / 2 - keylen); -+ memset(ctx->opad, 0, crypto_ahash_blocksize(tfm) / 2); -+ } else { -+ memset((u8 *)ctx->opad + keylen - -+ crypto_ahash_blocksize(tfm) / 2, 0, -+ crypto_ahash_blocksize(tfm) - keylen); -+ } -+ -+ /* If doing fallback, still need to set the new key! */ -+ ctx->fb_do_setkey = true; -+ return ret; -+} -+ -+static int safexcel_hmac_sha3_224_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_224_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_224_BLOCK_SIZE; -+ req->processed = SHA3_224_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_224; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_224_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_224_DIGEST_SIZE; -+ req->block_sz = SHA3_224_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_224_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_224_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_224_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-224"); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sha3_224 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_224_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_224_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_224_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-224)", -+ .cra_driver_name = "safexcel-hmac-sha3-224", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_224_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_224_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_256_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_256_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_256_BLOCK_SIZE; -+ req->processed = SHA3_256_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_256; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_256_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_256_DIGEST_SIZE; -+ req->block_sz = SHA3_256_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_256_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_256_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_256_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-256"); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sha3_256 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_256_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_256_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_256_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-256)", -+ .cra_driver_name = "safexcel-hmac-sha3-256", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_256_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_256_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_384_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_384_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_384_BLOCK_SIZE; -+ req->processed = SHA3_384_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_384; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_384_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_384_DIGEST_SIZE; -+ req->block_sz = SHA3_384_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_384_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_384_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_384_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-384"); -+} -+ -+struct safexcel_alg_template safexcel_alg_hmac_sha3_384 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_384_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_384_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_384_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-384)", -+ .cra_driver_name = "safexcel-hmac-sha3-384", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_384_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_384_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, -+ }, -+}; -+ -+static int safexcel_hmac_sha3_512_init(struct ahash_request *areq) -+{ -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); -+ struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(tfm); -+ struct safexcel_ahash_req *req = ahash_request_ctx(areq); -+ -+ memset(req, 0, sizeof(*req)); -+ -+ /* Copy (half of) the key */ -+ memcpy(req->state, ctx->ipad, SHA3_512_BLOCK_SIZE / 2); -+ /* Start of HMAC should have len == processed == blocksize */ -+ req->len = SHA3_512_BLOCK_SIZE; -+ req->processed = SHA3_512_BLOCK_SIZE; -+ ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_SHA3_512; -+ req->digest = CONTEXT_CONTROL_DIGEST_HMAC; -+ req->state_sz = SHA3_512_BLOCK_SIZE / 2; -+ req->digest_sz = SHA3_512_DIGEST_SIZE; -+ req->block_sz = SHA3_512_BLOCK_SIZE; -+ req->hmac = true; -+ ctx->do_fallback = false; -+ ctx->fb_init_done = false; -+ return 0; -+} -+ -+static int safexcel_hmac_sha3_512_digest(struct ahash_request *req) -+{ -+ if (req->nbytes) -+ return safexcel_hmac_sha3_512_init(req) ?: -+ safexcel_ahash_finup(req); -+ -+ /* HW cannot do zero length HMAC, use fallback instead */ -+ return safexcel_sha3_digest_fallback(req); -+} -+ -+static int safexcel_hmac_sha3_512_cra_init(struct crypto_tfm *tfm) -+{ -+ return safexcel_hmac_sha3_cra_init(tfm, "sha3-512"); -+} -+struct safexcel_alg_template safexcel_alg_hmac_sha3_512 = { -+ .type = SAFEXCEL_ALG_TYPE_AHASH, -+ .algo_mask = SAFEXCEL_ALG_SHA3, -+ .alg.ahash = { -+ .init = safexcel_hmac_sha3_512_init, -+ .update = safexcel_sha3_update, -+ .final = safexcel_sha3_final, -+ .finup = safexcel_sha3_finup, -+ .digest = safexcel_hmac_sha3_512_digest, -+ .setkey = safexcel_hmac_sha3_setkey, -+ .export = safexcel_sha3_export, -+ .import = safexcel_sha3_import, -+ .halg = { -+ .digestsize = SHA3_512_DIGEST_SIZE, -+ .statesize = sizeof(struct safexcel_ahash_export_state), -+ .base = { -+ .cra_name = "hmac(sha3-512)", -+ .cra_driver_name = "safexcel-hmac-sha3-512", -+ .cra_priority = SAFEXCEL_CRA_PRIORITY, -+ .cra_flags = CRYPTO_ALG_ASYNC | -+ CRYPTO_ALG_KERN_DRIVER_ONLY | -+ CRYPTO_ALG_NEED_FALLBACK, -+ .cra_blocksize = SHA3_512_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct safexcel_ahash_ctx), -+ .cra_init = safexcel_hmac_sha3_512_cra_init, -+ .cra_exit = safexcel_hmac_sha3_cra_exit, -+ .cra_module = THIS_MODULE, -+ }, -+ }, - }, - }; ---- a/drivers/crypto/inside-secure/safexcel_ring.c -+++ b/drivers/crypto/inside-secure/safexcel_ring.c -@@ -14,7 +14,12 @@ int safexcel_init_ring_descriptors(struc - struct safexcel_desc_ring *cdr, - struct safexcel_desc_ring *rdr) - { -- cdr->offset = sizeof(u32) * priv->config.cd_offset; -+ int i; -+ struct safexcel_command_desc *cdesc; -+ dma_addr_t atok; -+ -+ /* Actual command descriptor ring */ -+ cdr->offset = priv->config.cd_offset; - cdr->base = dmam_alloc_coherent(priv->dev, - cdr->offset * EIP197_DEFAULT_RING_SIZE, - &cdr->base_dma, GFP_KERNEL); -@@ -24,7 +29,34 @@ int safexcel_init_ring_descriptors(struc - cdr->base_end = cdr->base + cdr->offset * (EIP197_DEFAULT_RING_SIZE - 1); - cdr->read = cdr->base; - -- rdr->offset = sizeof(u32) * priv->config.rd_offset; -+ /* Command descriptor shadow ring for storing additional token data */ -+ cdr->shoffset = priv->config.cdsh_offset; -+ cdr->shbase = dmam_alloc_coherent(priv->dev, -+ cdr->shoffset * -+ EIP197_DEFAULT_RING_SIZE, -+ &cdr->shbase_dma, GFP_KERNEL); -+ if (!cdr->shbase) -+ return -ENOMEM; -+ cdr->shwrite = cdr->shbase; -+ cdr->shbase_end = cdr->shbase + cdr->shoffset * -+ (EIP197_DEFAULT_RING_SIZE - 1); -+ -+ /* -+ * Populate command descriptors with physical pointers to shadow descs. -+ * Note that we only need to do this once if we don't overwrite them. -+ */ -+ cdesc = cdr->base; -+ atok = cdr->shbase_dma; -+ for (i = 0; i < EIP197_DEFAULT_RING_SIZE; i++) { -+ cdesc->atok_lo = lower_32_bits(atok); -+ cdesc->atok_hi = upper_32_bits(atok); -+ cdesc = (void *)cdesc + cdr->offset; -+ atok += cdr->shoffset; -+ } -+ -+ rdr->offset = priv->config.rd_offset; -+ /* Use shoffset for result token offset here */ -+ rdr->shoffset = priv->config.res_offset; - rdr->base = dmam_alloc_coherent(priv->dev, - rdr->offset * EIP197_DEFAULT_RING_SIZE, - &rdr->base_dma, GFP_KERNEL); -@@ -42,11 +74,40 @@ inline int safexcel_select_ring(struct s - return (atomic_inc_return(&priv->ring_used) % priv->config.rings); - } - --static void *safexcel_ring_next_wptr(struct safexcel_crypto_priv *priv, -- struct safexcel_desc_ring *ring) -+static void *safexcel_ring_next_cwptr(struct safexcel_crypto_priv *priv, -+ struct safexcel_desc_ring *ring, -+ bool first, -+ struct safexcel_token **atoken) - { - void *ptr = ring->write; - -+ if (first) -+ *atoken = ring->shwrite; -+ -+ if ((ring->write == ring->read - ring->offset) || -+ (ring->read == ring->base && ring->write == ring->base_end)) -+ return ERR_PTR(-ENOMEM); -+ -+ if (ring->write == ring->base_end) { -+ ring->write = ring->base; -+ ring->shwrite = ring->shbase; -+ } else { -+ ring->write += ring->offset; -+ ring->shwrite += ring->shoffset; -+ } -+ -+ return ptr; -+} -+ -+static void *safexcel_ring_next_rwptr(struct safexcel_crypto_priv *priv, -+ struct safexcel_desc_ring *ring, -+ struct result_data_desc **rtoken) -+{ -+ void *ptr = ring->write; -+ -+ /* Result token at relative offset shoffset */ -+ *rtoken = ring->write + ring->shoffset; -+ - if ((ring->write == ring->read - ring->offset) || - (ring->read == ring->base && ring->write == ring->base_end)) - return ERR_PTR(-ENOMEM); -@@ -106,10 +167,13 @@ void safexcel_ring_rollback_wptr(struct - if (ring->write == ring->read) - return; - -- if (ring->write == ring->base) -+ if (ring->write == ring->base) { - ring->write = ring->base_end; -- else -+ ring->shwrite = ring->shbase_end; -+ } else { - ring->write -= ring->offset; -+ ring->shwrite -= ring->shoffset; -+ } - } - - struct safexcel_command_desc *safexcel_add_cdesc(struct safexcel_crypto_priv *priv, -@@ -117,26 +181,26 @@ struct safexcel_command_desc *safexcel_a - bool first, bool last, - dma_addr_t data, u32 data_len, - u32 full_data_len, -- dma_addr_t context) { -+ dma_addr_t context, -+ struct safexcel_token **atoken) -+{ - struct safexcel_command_desc *cdesc; -- int i; - -- cdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].cdr); -+ cdesc = safexcel_ring_next_cwptr(priv, &priv->ring[ring_id].cdr, -+ first, atoken); - if (IS_ERR(cdesc)) - return cdesc; - -- memset(cdesc, 0, sizeof(struct safexcel_command_desc)); -- -- cdesc->first_seg = first; -- cdesc->last_seg = last; - cdesc->particle_size = data_len; -+ cdesc->rsvd0 = 0; -+ cdesc->last_seg = last; -+ cdesc->first_seg = first; -+ cdesc->additional_cdata_size = 0; -+ cdesc->rsvd1 = 0; - cdesc->data_lo = lower_32_bits(data); - cdesc->data_hi = upper_32_bits(data); - -- if (first && context) { -- struct safexcel_token *token = -- (struct safexcel_token *)cdesc->control_data.token; -- -+ if (first) { - /* - * Note that the length here MUST be >0 or else the EIP(1)97 - * may hang. Newer EIP197 firmware actually incorporates this -@@ -146,20 +210,12 @@ struct safexcel_command_desc *safexcel_a - cdesc->control_data.packet_length = full_data_len ?: 1; - cdesc->control_data.options = EIP197_OPTION_MAGIC_VALUE | - EIP197_OPTION_64BIT_CTX | -- EIP197_OPTION_CTX_CTRL_IN_CMD; -- cdesc->control_data.context_lo = -- (lower_32_bits(context) & GENMASK(31, 2)) >> 2; -+ EIP197_OPTION_CTX_CTRL_IN_CMD | -+ EIP197_OPTION_RC_AUTO; -+ cdesc->control_data.type = EIP197_TYPE_BCLA; -+ cdesc->control_data.context_lo = lower_32_bits(context) | -+ EIP197_CONTEXT_SMALL; - cdesc->control_data.context_hi = upper_32_bits(context); -- -- if (priv->version == EIP197B_MRVL || -- priv->version == EIP197D_MRVL) -- cdesc->control_data.options |= EIP197_OPTION_RC_AUTO; -- -- /* TODO: large xform HMAC with SHA-384/512 uses refresh = 3 */ -- cdesc->control_data.refresh = 2; -- -- for (i = 0; i < EIP197_MAX_TOKENS; i++) -- eip197_noop_token(&token[i]); - } - - return cdesc; -@@ -171,18 +227,27 @@ struct safexcel_result_desc *safexcel_ad - dma_addr_t data, u32 len) - { - struct safexcel_result_desc *rdesc; -+ struct result_data_desc *rtoken; - -- rdesc = safexcel_ring_next_wptr(priv, &priv->ring[ring_id].rdr); -+ rdesc = safexcel_ring_next_rwptr(priv, &priv->ring[ring_id].rdr, -+ &rtoken); - if (IS_ERR(rdesc)) - return rdesc; - -- memset(rdesc, 0, sizeof(struct safexcel_result_desc)); -- -- rdesc->first_seg = first; -- rdesc->last_seg = last; - rdesc->particle_size = len; -+ rdesc->rsvd0 = 0; -+ rdesc->descriptor_overflow = 0; -+ rdesc->buffer_overflow = 0; -+ rdesc->last_seg = last; -+ rdesc->first_seg = first; -+ rdesc->result_size = EIP197_RD64_RESULT_SIZE; -+ rdesc->rsvd1 = 0; - rdesc->data_lo = lower_32_bits(data); - rdesc->data_hi = upper_32_bits(data); - -+ /* Clear length & error code in result token */ -+ rtoken->packet_length = 0; -+ rtoken->error_code = 0; -+ - return rdesc; - } diff --git a/target/linux/mediatek/patches-5.4/0501-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.4/0501-crypto-add-eip97-inside-secure-support.patch deleted file mode 100644 index 3eda4f291a..0000000000 --- a/target/linux/mediatek/patches-5.4/0501-crypto-add-eip97-inside-secure-support.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.c -+++ b/drivers/crypto/inside-secure/safexcel.c -@@ -595,6 +595,14 @@ static int safexcel_hw_init(struct safex - val |= EIP197_MST_CTRL_TX_MAX_CMD(5); - writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); - } -+ /* -+ * Set maximum number of TX commands to 2^4 = 16 for EIP97 HW2.1/HW2.3 -+ */ -+ else { -+ val = 0; -+ val |= EIP97_MST_CTRL_TX_MAX_CMD(4); -+ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); -+ } - - /* Configure wr/rd cache values */ - writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) | ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -306,6 +306,7 @@ - #define EIP197_MST_CTRL_RD_CACHE(n) (((n) & 0xf) << 0) - #define EIP197_MST_CTRL_WD_CACHE(n) (((n) & 0xf) << 4) - #define EIP197_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 20) -+#define EIP97_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 4) - #define EIP197_MST_CTRL_BYTE_SWAP BIT(24) - #define EIP197_MST_CTRL_NO_BYTE_SWAP BIT(25) - #define EIP197_MST_CTRL_BYTE_SWAP_BITS GENMASK(25, 24) diff --git a/target/linux/mediatek/patches-5.4/0502-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.4/0502-dts-mt7623-eip97-inside-secure-support.patch deleted file mode 100644 index 06077fb984..0000000000 --- a/target/linux/mediatek/patches-5.4/0502-dts-mt7623-eip97-inside-secure-support.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -1047,17 +1047,14 @@ - }; - - crypto: crypto@1b240000 { -- compatible = "mediatek,eip97-crypto"; -+ compatible = "inside-secure,safexcel-eip97"; - reg = <0 0x1b240000 0 0x20000>; - interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_LOW>, - <GIC_SPI 83 IRQ_TYPE_LEVEL_LOW>, - <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>, -- <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>, -- <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>; -+ <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "ring0", "ring1", "ring2", "ring3"; - clocks = <ðsys CLK_ETHSYS_CRYPTO>; -- clock-names = "cryp"; -- power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; -- status = "disabled"; - }; - - bdpsys: syscon@1c000000 { diff --git a/target/linux/mediatek/patches-5.4/0503-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-5.4/0503-crypto-fix-eip97-cache-incoherent.patch deleted file mode 100644 index 5bc0fd0b7d..0000000000 --- a/target/linux/mediatek/patches-5.4/0503-crypto-fix-eip97-cache-incoherent.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -722,6 +722,9 @@ enum safexcel_eip_version { - /* Priority we use for advertising our algorithms */ - #define SAFEXCEL_CRA_PRIORITY 300 - -+/* System cache line size */ -+#define SYSTEM_CACHELINE_SIZE 64 -+ - /* SM3 digest result for zero length message */ - #define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ - "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ ---- a/drivers/crypto/inside-secure/safexcel_hash.c -+++ b/drivers/crypto/inside-secure/safexcel_hash.c -@@ -57,9 +57,9 @@ struct safexcel_ahash_req { - u8 block_sz; /* block size, only set once */ - u8 digest_sz; /* output digest size, only set once */ - __le32 state[SHA3_512_BLOCK_SIZE / -- sizeof(__le32)] __aligned(sizeof(__le32)); -+ sizeof(__le32)] __aligned(SYSTEM_CACHELINE_SIZE); - -- u64 len; -+ u64 len __aligned(SYSTEM_CACHELINE_SIZE); - u64 processed; - - u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); diff --git a/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch b/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch deleted file mode 100644 index bd854613b7..0000000000 --- a/target/linux/mediatek/patches-5.4/0600-net-phylink-propagate-resolved-link-config-via-mac_l.patch +++ /dev/null @@ -1,246 +0,0 @@ -From: Russell King <rmk+kernel@armlinux.org.uk> -Date: Wed, 26 Feb 2020 10:23:41 +0000 -Subject: [PATCH] net: phylink: propagate resolved link config via - mac_link_up() - -Propagate the resolved link parameters via the mac_link_up() call for -MACs that do not automatically track their PCS state. We propagate the -link parameters via function arguments so that inappropriate members -of struct phylink_link_state can't be accessed, and creating a new -structure just for this adds needless complexity to the API. - -Tested-by: Andre Przywara <andre.przywara@arm.com> -Tested-by: Alexandre Belloni <alexandre.belloni@bootlin.com> -Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> -Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> -Signed-off-by: David S. Miller <davem@davemloft.net> ---- - ---- a/Documentation/networking/sfp-phylink.rst -+++ b/Documentation/networking/sfp-phylink.rst -@@ -74,10 +74,13 @@ phylib to the sfp/phylink support. Plea - this documentation. - - 1. Optionally split the network driver's phylib update function into -- three parts dealing with link-down, link-up and reconfiguring the -- MAC settings. This can be done as a separate preparation commit. -+ two parts dealing with link-down and link-up. This can be done as -+ a separate preparation commit. - -- An example of this preparation can be found in git commit fc548b991fb0. -+ An older example of this preparation can be found in git commit -+ fc548b991fb0, although this was splitting into three parts; the -+ link-up part now includes configuring the MAC for the link settings. -+ Please see :c:func:`mac_link_up` for more information on this. - - 2. Replace:: - -@@ -207,6 +210,14 @@ this documentation. - using. This is particularly important for in-band negotiation - methods such as 1000base-X and SGMII. - -+ The :c:func:`mac_link_up` method is used to inform the MAC that the -+ link has come up. The call includes the negotiation mode and interface -+ for reference only. The finalised link parameters are also supplied -+ (speed, duplex and flow control/pause enablement settings) which -+ should be used to configure the MAC when the MAC and PCS are not -+ tightly integrated, or when the settings are not coming from in-band -+ negotiation. -+ - The :c:func:`mac_config` method is used to update the MAC with the - requested state, and must avoid unnecessarily taking the link down - when making changes to the MAC configuration. This means the ---- a/drivers/net/ethernet/marvell/mvneta.c -+++ b/drivers/net/ethernet/marvell/mvneta.c -@@ -3655,9 +3655,11 @@ static void mvneta_mac_link_down(struct - mvneta_set_eee(pp, false); - } - --static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface, -- struct phy_device *phy) -+static void mvneta_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct net_device *ndev = to_net_dev(config->dev); - struct mvneta_port *pp = netdev_priv(ndev); ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -58,8 +58,11 @@ static struct { - */ - static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode, - const struct phylink_link_state *state); --static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface, struct phy_device *phy); -+static void mvpp2_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause); - - /* Queue modes */ - #define MVPP2_QDIST_SINGLE_MODE 0 -@@ -3468,8 +3471,9 @@ static void mvpp2_start_dev(struct mvpp2 - .interface = port->phy_interface, - }; - mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state); -- mvpp2_mac_link_up(&port->phylink_config, MLO_AN_INBAND, -- port->phy_interface, NULL); -+ mvpp2_mac_link_up(&port->phylink_config, NULL, -+ MLO_AN_INBAND, port->phy_interface, -+ SPEED_UNKNOWN, DUPLEX_UNKNOWN, false, false); - } - - netif_tx_start_all_queues(port->dev); -@@ -5137,8 +5141,11 @@ static void mvpp2_mac_config(struct phyl - mvpp2_port_enable(port); - } - --static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface, struct phy_device *phy) -+static void mvpp2_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct mvpp2_port *port = mvpp2_phylink_to_port(config); - u32 val; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -449,9 +449,10 @@ static void mtk_mac_link_down(struct phy - mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); - } - --static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface, -- struct phy_device *phy) -+static void mtk_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) - { - struct mtk_mac *mac = container_of(config, struct mtk_mac, - phylink_config); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -925,8 +925,10 @@ static void stmmac_mac_link_down(struct - } - - static void stmmac_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, - unsigned int mode, phy_interface_t interface, -- struct phy_device *phy) -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); - ---- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c -@@ -1499,9 +1499,10 @@ static void axienet_mac_link_down(struct - } - - static void axienet_mac_link_up(struct phylink_config *config, -- unsigned int mode, -- phy_interface_t interface, -- struct phy_device *phy) -+ struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - /* nothing meaningful to do */ - } ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -447,8 +447,11 @@ static void phylink_mac_link_up(struct p - struct net_device *ndev = pl->netdev; - - pl->cur_interface = link_state.interface; -- pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode, -- pl->cur_interface, pl->phydev); -+ pl->ops->mac_link_up(pl->config, pl->phydev, -+ pl->cur_link_an_mode, pl->cur_interface, -+ link_state.speed, link_state.duplex, -+ !!(link_state.pause & MLO_PAUSE_TX), -+ !!(link_state.pause & MLO_PAUSE_RX)); - - if (ndev) - netif_carrier_on(ndev); ---- a/include/linux/phylink.h -+++ b/include/linux/phylink.h -@@ -91,9 +91,10 @@ struct phylink_mac_ops { - void (*mac_an_restart)(struct phylink_config *config); - void (*mac_link_down)(struct phylink_config *config, unsigned int mode, - phy_interface_t interface); -- void (*mac_link_up)(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface, -- struct phy_device *phy); -+ void (*mac_link_up)(struct phylink_config *config, -+ struct phy_device *phy, unsigned int mode, -+ phy_interface_t interface, int speed, int duplex, -+ bool tx_pause, bool rx_pause); - }; - - #if 0 /* For kernel-doc purposes only. */ -@@ -217,19 +218,34 @@ void mac_link_down(struct phylink_config - /** - * mac_link_up() - allow the link to come up - * @config: a pointer to a &struct phylink_config. -+ * @phy: any attached phy - * @mode: link autonegotiation mode - * @interface: link &typedef phy_interface_t mode -- * @phy: any attached phy -+ * @speed: link speed -+ * @duplex: link duplex -+ * @tx_pause: link transmit pause enablement status -+ * @rx_pause: link receive pause enablement status -+ * -+ * Configure the MAC for an established link. -+ * -+ * @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link -+ * settings, and should be used to configure the MAC block appropriately -+ * where these settings are not automatically conveyed from the PCS block, -+ * or if in-band negotiation (as defined by phylink_autoneg_inband(@mode)) -+ * is disabled. -+ * -+ * Note that when 802.3z in-band negotiation is in use, it is possible -+ * that the user wishes to override the pause settings, and this should -+ * be allowed when considering the implementation of this method. - * -- * If @mode is not an in-band negotiation mode (as defined by -- * phylink_autoneg_inband()), allow the link to come up. If @phy -- * is non-%NULL, configure Energy Efficient Ethernet by calling -+ * If in-band negotiation mode is disabled, allow the link to come up. If -+ * @phy is non-%NULL, configure Energy Efficient Ethernet by calling - * phy_init_eee() and perform appropriate MAC configuration for EEE. - * Interface type selection must be done in mac_config(). - */ --void mac_link_up(struct phylink_config *config, unsigned int mode, -- phy_interface_t interface, -- struct phy_device *phy); -+void mac_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause); - #endif - - struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, ---- a/net/dsa/port.c -+++ b/net/dsa/port.c -@@ -529,9 +529,11 @@ void dsa_port_phylink_mac_link_down(stru - EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_link_down); - - void dsa_port_phylink_mac_link_up(struct phylink_config *config, -+ struct phy_device *phydev, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev) -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); - struct dsa_switch *ds = dp->ds; diff --git a/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch b/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch deleted file mode 100644 index 0df300b627..0000000000 --- a/target/linux/mediatek/patches-5.4/0601-net-dsa-propagate-resolved-link-config-via-mac_link_.patch +++ /dev/null @@ -1,143 +0,0 @@ -From: Russell King <rmk+kernel@armlinux.org.uk> -Date: Wed, 26 Feb 2020 10:23:46 +0000 -Subject: [PATCH] net: dsa: propagate resolved link config via mac_link_up() - -Propagate the resolved link configuration down via DSA's -phylink_mac_link_up() operation to allow split PCS/MAC to work. - -Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> -Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> -Signed-off-by: David S. Miller <davem@davemloft.net> ---- - ---- a/drivers/net/dsa/b53/b53_common.c -+++ b/drivers/net/dsa/b53/b53_common.c -@@ -1284,7 +1284,9 @@ EXPORT_SYMBOL(b53_phylink_mac_link_down) - void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev) -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct b53_device *dev = ds->priv; - ---- a/drivers/net/dsa/b53/b53_priv.h -+++ b/drivers/net/dsa/b53/b53_priv.h -@@ -337,7 +337,9 @@ void b53_phylink_mac_link_down(struct ds - void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev); -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause); - int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering); - int b53_vlan_prepare(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan); ---- a/drivers/net/dsa/bcm_sf2.c -+++ b/drivers/net/dsa/bcm_sf2.c -@@ -636,7 +636,9 @@ static void bcm_sf2_sw_mac_link_down(str - static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev) -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); - struct ethtool_eee *p = &priv->dev->ports[port].eee; ---- a/drivers/net/dsa/lantiq_gswip.c -+++ b/drivers/net/dsa/lantiq_gswip.c -@@ -1663,7 +1663,9 @@ static void gswip_phylink_mac_link_down( - static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev) -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct gswip_priv *priv = ds->priv; - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -1440,7 +1440,9 @@ static void mt7530_phylink_mac_link_down - static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev) -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - struct mt7530_priv *priv = ds->priv; - ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -652,7 +652,9 @@ static void mv88e6xxx_mac_link_down(stru - - static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, phy_interface_t interface, -- struct phy_device *phydev) -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - if (mode == MLO_AN_FIXED) - mv88e6xxx_mac_link_force(ds, port, LINK_FORCED_UP); ---- a/drivers/net/dsa/sja1105/sja1105_main.c -+++ b/drivers/net/dsa/sja1105/sja1105_main.c -@@ -831,7 +831,9 @@ static void sja1105_mac_link_down(struct - static void sja1105_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev) -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) - { - sja1105_inhibit_tx(ds->priv, BIT(port), false); - } ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -406,7 +406,9 @@ struct dsa_switch_ops { - void (*phylink_mac_link_up)(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev); -+ struct phy_device *phydev, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause); - void (*phylink_fixed_state)(struct dsa_switch *ds, int port, - struct phylink_link_state *state); - /* ---- a/net/dsa/port.c -+++ b/net/dsa/port.c -@@ -544,7 +544,8 @@ void dsa_port_phylink_mac_link_up(struct - return; - } - -- ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev); -+ ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev, -+ speed, duplex, tx_pause, rx_pause); - } - EXPORT_SYMBOL_GPL(dsa_port_phylink_mac_link_up); - ---- a/net/dsa/dsa_priv.h -+++ b/net/dsa/dsa_priv.h -@@ -192,9 +192,11 @@ void dsa_port_phylink_mac_link_down(stru - unsigned int mode, - phy_interface_t interface); - void dsa_port_phylink_mac_link_up(struct phylink_config *config, -+ struct phy_device *phydev, - unsigned int mode, - phy_interface_t interface, -- struct phy_device *phydev); -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause); - extern const struct phylink_mac_ops dsa_port_phylink_mac_ops; - - /* slave.c */ diff --git a/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch b/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch deleted file mode 100644 index 23fba85252..0000000000 --- a/target/linux/mediatek/patches-5.4/0602-net-dsa-mt7530-use-resolved-link-config-in-mac_link_.patch +++ /dev/null @@ -1,145 +0,0 @@ -From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= <opensource@vdorst.com> -Date: Fri, 27 Mar 2020 15:44:12 +0100 -Subject: [PATCH] net: dsa: mt7530: use resolved link config in mac_link_up() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Convert the mt7530 switch driver to use the finalised link -parameters in mac_link_up() rather than the parameters in mac_config(). - -Signed-off-by: René van Dorst <opensource@vdorst.com> -Tested-by: Sean Wang <sean.wang@mediatek.com> -Signed-off-by: David S. Miller <davem@davemloft.net> ---- - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -489,17 +489,6 @@ mt7530_mib_reset(struct dsa_switch *ds) - mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE); - } - --static void --mt7530_port_set_status(struct mt7530_priv *priv, int port, int enable) --{ -- u32 mask = PMCR_TX_EN | PMCR_RX_EN | PMCR_FORCE_LNK; -- -- if (enable) -- mt7530_set(priv, MT7530_PMCR_P(port), mask); -- else -- mt7530_clear(priv, MT7530_PMCR_P(port), mask); --} -- - static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum) - { - struct mt7530_priv *priv = ds->priv; -@@ -673,7 +662,7 @@ mt7530_port_enable(struct dsa_switch *ds - priv->ports[port].enable = true; - mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, - priv->ports[port].pm); -- mt7530_port_set_status(priv, port, 0); -+ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); - - mutex_unlock(&priv->reg_mutex); - -@@ -696,7 +685,7 @@ mt7530_port_disable(struct dsa_switch *d - priv->ports[port].enable = false; - mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, - PCR_MATRIX_CLR); -- mt7530_port_set_status(priv, port, 0); -+ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); - - mutex_unlock(&priv->reg_mutex); - } -@@ -1395,8 +1384,7 @@ static void mt7530_phylink_mac_config(st - - mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port)); - mcr_new = mcr_cur; -- mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 | -- PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN); -+ mcr_new &= ~PMCR_LINK_SETTINGS_MASK; - mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | - PMCR_BACKPR_EN | PMCR_FORCE_MODE; - -@@ -1404,26 +1392,6 @@ static void mt7530_phylink_mac_config(st - if (port == 5 && dsa_is_user_port(ds, 5)) - mcr_new |= PMCR_EXT_PHY; - -- switch (state->speed) { -- case SPEED_1000: -- mcr_new |= PMCR_FORCE_SPEED_1000; -- if (priv->eee_enable & BIT(port)) -- mcr_new |= PMCR_FORCE_EEE1G; -- break; -- case SPEED_100: -- mcr_new |= PMCR_FORCE_SPEED_100; -- if (priv->eee_enable & BIT(port)) -- mcr_new |= PMCR_FORCE_EEE100; -- break; -- } -- if (state->duplex == DUPLEX_FULL) { -- mcr_new |= PMCR_FORCE_FDX; -- if (state->pause & MLO_PAUSE_TX) -- mcr_new |= PMCR_TX_FC_EN; -- if (state->pause & MLO_PAUSE_RX) -- mcr_new |= PMCR_RX_FC_EN; -- } -- - if (mcr_new != mcr_cur) - mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); - } -@@ -1434,7 +1402,7 @@ static void mt7530_phylink_mac_link_down - { - struct mt7530_priv *priv = ds->priv; - -- mt7530_port_set_status(priv, port, 0); -+ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); - } - - static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port, -@@ -1445,8 +1413,31 @@ static void mt7530_phylink_mac_link_up(s - bool tx_pause, bool rx_pause) - { - struct mt7530_priv *priv = ds->priv; -+ u32 mcr; -+ -+ mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; -+ -+ switch (speed) { -+ case SPEED_1000: -+ mcr |= PMCR_FORCE_SPEED_1000; -+ if (priv->eee_enable & BIT(port)) -+ mcr_new |= PMCR_FORCE_EEE1G; -+ break; -+ case SPEED_100: -+ mcr |= PMCR_FORCE_SPEED_100; -+ if (priv->eee_enable & BIT(port)) -+ mcr_new |= PMCR_FORCE_EEE100; -+ break; -+ } -+ if (duplex == DUPLEX_FULL) { -+ mcr |= PMCR_FORCE_FDX; -+ if (tx_pause) -+ mcr |= PMCR_TX_FC_EN; -+ if (rx_pause) -+ mcr |= PMCR_RX_FC_EN; -+ } - -- mt7530_port_set_status(priv, port, 1); -+ mt7530_set(priv, MT7530_PMCR_P(port), mcr); - } - - static void mt7530_phylink_validate(struct dsa_switch *ds, int port, ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -222,6 +222,10 @@ enum mt7530_vlan_port_attr { - #define PMCR_FORCE_LNK BIT(0) - #define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ - PMCR_FORCE_SPEED_1000) -+#define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ -+ PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ -+ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ -+ PMCR_FORCE_FDX | PMCR_FORCE_LNK) - - #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) - #define PMSR_EEE1G BIT(7) diff --git a/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch deleted file mode 100644 index 718ed8ea2d..0000000000 --- a/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch +++ /dev/null @@ -1,458 +0,0 @@ -From: Landen Chao <landen.chao@mediatek.com> -Date: Fri, 4 Sep 2020 22:21:57 +0800 -Subject: [PATCH] net: dsa: mt7530: Extend device data ready for adding a - new hardware - -Add a structure holding required operations for each device such as device -initialization, PHY port read or write, a checker whether PHY interface is -supported on a certain port, MAC port setup for either bus pad or a -specific PHY interface. - -The patch is done for ready adding a new hardware MT7531, and keep the -same setup logic of existing hardware. - -Signed-off-by: Landen Chao <landen.chao@mediatek.com> -Signed-off-by: Sean Wang <sean.wang@mediatek.com> ---- - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -373,8 +373,9 @@ mt7530_fdb_write(struct mt7530_priv *pri - mt7530_write(priv, MT7530_ATA1 + (i * 4), reg[i]); - } - -+/* Setup TX circuit including relevant PAD and driving */ - static int --mt7530_pad_clk_setup(struct dsa_switch *ds, int mode) -+mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) - { - struct mt7530_priv *priv = ds->priv; - u32 ncpo1, ssc_delta, trgint, i, xtal; -@@ -388,7 +389,7 @@ mt7530_pad_clk_setup(struct dsa_switch * - return -EINVAL; - } - -- switch (mode) { -+ switch (interface) { - case PHY_INTERFACE_MODE_RGMII: - trgint = 0; - /* PLL frequency: 125MHz */ -@@ -410,7 +411,8 @@ mt7530_pad_clk_setup(struct dsa_switch * - } - break; - default: -- dev_err(priv->dev, "xMII mode %d not supported\n", mode); -+ dev_err(priv->dev, "xMII interface %d not supported\n", -+ interface); - return -EINVAL; - } - -@@ -1332,12 +1334,11 @@ mt7530_setup(struct dsa_switch *ds) - return 0; - } - --static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port, -- unsigned int mode, -- const struct phylink_link_state *state) -+static bool -+mt7530_phy_mode_supported(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state) - { - struct mt7530_priv *priv = ds->priv; -- u32 mcr_cur, mcr_new; - - switch (port) { - case 0: /* Internal phy */ -@@ -1346,33 +1347,114 @@ static void mt7530_phylink_mac_config(st - case 3: - case 4: - if (state->interface != PHY_INTERFACE_MODE_GMII) -- return; -+ goto unsupported; - break; - case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -- if (priv->p5_interface == state->interface) -- break; - if (!phy_interface_mode_is_rgmii(state->interface) && - state->interface != PHY_INTERFACE_MODE_MII && - state->interface != PHY_INTERFACE_MODE_GMII) -- return; -+ goto unsupported; -+ break; -+ case 6: /* 1st cpu port */ -+ if (state->interface != PHY_INTERFACE_MODE_RGMII && -+ state->interface != PHY_INTERFACE_MODE_TRGMII) -+ goto unsupported; -+ break; -+ default: -+ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, -+ port); -+ goto unsupported; -+ } -+ -+ return true; -+ -+unsupported: -+ return false; -+} -+ -+static bool -+mt753x_phy_mode_supported(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->phy_mode_supported(ds, port, state); -+} -+ -+static int -+mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->pad_setup(ds, state->interface); -+} -+ -+static int -+mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ /* Only need to setup port5. */ -+ if (port != 5) -+ return 0; -+ -+ mt7530_setup_port5(priv->ds, interface); -+ -+ return 0; -+} -+ -+static int -+mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->mac_port_config(ds, port, mode, state->interface); -+} -+ -+static void -+mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 mcr_cur, mcr_new; -+ -+ if (!mt753x_phy_mode_supported(ds, port, state)) -+ goto unsupported; -+ -+ switch (port) { -+ case 0: /* Internal phy */ -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ if (state->interface != PHY_INTERFACE_MODE_GMII) -+ goto unsupported; -+ break; -+ case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -+ if (priv->p5_interface == state->interface) -+ break; -+ -+ if (mt753x_mac_config(ds, port, mode, state) < 0) -+ goto unsupported; - -- mt7530_setup_port5(ds, state->interface); - break; - case 6: /* 1st cpu port */ - if (priv->p6_interface == state->interface) - break; - -- if (state->interface != PHY_INTERFACE_MODE_RGMII && -- state->interface != PHY_INTERFACE_MODE_TRGMII) -- return; -+ mt753x_pad_setup(ds, state); - -- /* Setup TX circuit incluing relevant PAD and driving */ -- mt7530_pad_clk_setup(ds, state->interface); -+ if (mt753x_mac_config(ds, port, mode, state) < 0) -+ goto unsupported; - - priv->p6_interface = state->interface; - break; - default: -- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); -+unsupported: -+ dev_err(ds->dev, "%s: unsupported %s port: %i\n", -+ __func__, phy_modes(state->interface), port); - return; - } - -@@ -1440,61 +1522,44 @@ static void mt7530_phylink_mac_link_up(s - mt7530_set(priv, MT7530_PMCR_P(port), mcr); - } - --static void mt7530_phylink_validate(struct dsa_switch *ds, int port, -- unsigned long *supported, -- struct phylink_link_state *state) -+static void -+mt7530_mac_port_validate(struct dsa_switch *ds, int port, -+ unsigned long *supported) - { -+ if (port == 5) -+ phylink_set(supported, 1000baseX_Full); -+} -+ -+static void -+mt753x_phylink_validate(struct dsa_switch *ds, int port, -+ unsigned long *supported, -+ struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; - __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; - -- switch (port) { -- case 0: /* Internal phy */ -- case 1: -- case 2: -- case 3: -- case 4: -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_GMII) -- goto unsupported; -- break; -- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ -- if (state->interface != PHY_INTERFACE_MODE_NA && -- !phy_interface_mode_is_rgmii(state->interface) && -- state->interface != PHY_INTERFACE_MODE_MII && -- state->interface != PHY_INTERFACE_MODE_GMII) -- goto unsupported; -- break; -- case 6: /* 1st cpu port */ -- if (state->interface != PHY_INTERFACE_MODE_NA && -- state->interface != PHY_INTERFACE_MODE_RGMII && -- state->interface != PHY_INTERFACE_MODE_TRGMII) -- goto unsupported; -- break; -- default: -- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); --unsupported: -+ if (state->interface != PHY_INTERFACE_MODE_NA && -+ !mt753x_phy_mode_supported(ds, port, state)) { - linkmode_zero(supported); - return; - } - - phylink_set_port_modes(mask); -- phylink_set(mask, Autoneg); - -- if (state->interface == PHY_INTERFACE_MODE_TRGMII) { -- phylink_set(mask, 1000baseT_Full); -- } else { -+ if (state->interface != PHY_INTERFACE_MODE_TRGMII) { - phylink_set(mask, 10baseT_Half); - phylink_set(mask, 10baseT_Full); - phylink_set(mask, 100baseT_Half); - phylink_set(mask, 100baseT_Full); -- -- if (state->interface != PHY_INTERFACE_MODE_MII) { -- /* This switch only supports 1G full-duplex. */ -- phylink_set(mask, 1000baseT_Full); -- if (port == 5) -- phylink_set(mask, 1000baseX_Full); -- } -+ phylink_set(mask, Autoneg); - } - -+ /* This switch only supports 1G full-duplex. */ -+ if (state->interface != PHY_INTERFACE_MODE_MII) -+ phylink_set(mask, 1000baseT_Full); -+ -+ priv->info->mac_port_validate(ds, port, mask); -+ - phylink_set(mask, Pause); - phylink_set(mask, Asym_Pause); - -@@ -1590,12 +1655,45 @@ static int mt7530_set_mac_eee(struct dsa - return 0; - } - -+static int -+mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, -+ struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->mac_port_get_state(ds, port, state); -+} -+ -+static int -+mt753x_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->sw_setup(ds); -+} -+ -+static int -+mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->phy_read(ds, port, regnum); -+} -+ -+static int -+mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return priv->info->phy_write(ds, port, regnum, val); -+} -+ - static const struct dsa_switch_ops mt7530_switch_ops = { - .get_tag_protocol = mtk_get_tag_protocol, -- .setup = mt7530_setup, -+ .setup = mt753x_setup, - .get_strings = mt7530_get_strings, -- .phy_read = mt7530_phy_read, -- .phy_write = mt7530_phy_write, -+ .phy_read = mt753x_phy_read, -+ .phy_write = mt753x_phy_write, - .get_ethtool_stats = mt7530_get_ethtool_stats, - .get_sset_count = mt7530_get_sset_count, - .port_enable = mt7530_port_enable, -@@ -1612,18 +1710,43 @@ static const struct dsa_switch_ops mt753 - .port_vlan_del = mt7530_port_vlan_del, - .port_mirror_add = mt7530_port_mirror_add, - .port_mirror_del = mt7530_port_mirror_del, -- .phylink_validate = mt7530_phylink_validate, -- .phylink_mac_link_state = mt7530_phylink_mac_link_state, -- .phylink_mac_config = mt7530_phylink_mac_config, -+ .phylink_validate = mt753x_phylink_validate, -+ .phylink_mac_link_state = mt753x_phylink_mac_link_state, -+ .phylink_mac_config = mt753x_phylink_mac_config, - .phylink_mac_link_down = mt7530_phylink_mac_link_down, - .phylink_mac_link_up = mt7530_phylink_mac_link_up, - .get_mac_eee = mt7530_get_mac_eee, - .set_mac_eee = mt7530_set_mac_eee, - }; - -+static const struct mt753x_info mt753x_table[] = { -+ [ID_MT7621] = { -+ .id = ID_MT7621, -+ .sw_setup = mt7530_setup, -+ .phy_read = mt7530_phy_read, -+ .phy_write = mt7530_phy_write, -+ .pad_setup = mt7530_pad_clk_setup, -+ .phy_mode_supported = mt7530_phy_mode_supported, -+ .mac_port_validate = mt7530_mac_port_validate, -+ .mac_port_get_state = mt7530_phylink_mac_link_state, -+ .mac_port_config = mt7530_mac_config, -+ }, -+ [ID_MT7530] = { -+ .id = ID_MT7530, -+ .sw_setup = mt7530_setup, -+ .phy_read = mt7530_phy_read, -+ .phy_write = mt7530_phy_write, -+ .pad_setup = mt7530_pad_clk_setup, -+ .phy_mode_supported = mt7530_phy_mode_supported, -+ .mac_port_validate = mt7530_mac_port_validate, -+ .mac_port_get_state = mt7530_phylink_mac_link_state, -+ .mac_port_config = mt7530_mac_config, -+ }, -+}; -+ - static const struct of_device_id mt7530_of_match[] = { -- { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, }, -- { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, }, -+ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, -+ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, - { /* sentinel */ }, - }; - MODULE_DEVICE_TABLE(of, mt7530_of_match); -@@ -1661,8 +1784,21 @@ mt7530_probe(struct mdio_device *mdiodev - /* Get the hardware identifier from the devicetree node. - * We will need it for some of the clock and regulator setup. - */ -- priv->id = (unsigned int)(unsigned long) -- of_device_get_match_data(&mdiodev->dev); -+ priv->info = of_device_get_match_data(&mdiodev->dev); -+ if (!priv->info) -+ return -EINVAL; -+ -+ /* Sanity check if these required device operations are filled -+ * properly. -+ */ -+ if (!priv->info->sw_setup || !priv->info->pad_setup || -+ !priv->info->phy_read || !priv->info->phy_write || -+ !priv->info->phy_mode_supported || -+ !priv->info->mac_port_validate || -+ !priv->info->mac_port_get_state || !priv->info->mac_port_config) -+ return -EINVAL; -+ -+ priv->id = priv->info->id; - - if (priv->id == ID_MT7530) { - priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -11,7 +11,7 @@ - #define MT7530_NUM_FDB_RECORDS 2048 - #define MT7530_ALL_MEMBERS 0xff - --enum { -+enum mt753x_id { - ID_MT7530 = 0, - ID_MT7621 = 1, - }; -@@ -451,6 +451,40 @@ static const char *p5_intf_modes(unsigne - } - } - -+/* struct mt753x_info - This is the main data structure for holding the specific -+ * part for each supported device -+ * @sw_setup: Holding the handler to a device initialization -+ * @phy_read: Holding the way reading PHY port -+ * @phy_write: Holding the way writing PHY port -+ * @pad_setup: Holding the way setting up the bus pad for a certain -+ * MAC port -+ * @phy_mode_supported: Check if the PHY type is being supported on a certain -+ * port -+ * @mac_port_validate: Holding the way to set addition validate type for a -+ * certan MAC port -+ * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain -+ * MAC port -+ * @mac_port_config: Holding the way setting up the PHY attribute to a -+ * certain MAC port -+ */ -+struct mt753x_info { -+ enum mt753x_id id; -+ -+ int (*sw_setup)(struct dsa_switch *ds); -+ int (*phy_read)(struct dsa_switch *ds, int port, int regnum); -+ int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); -+ int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); -+ bool (*phy_mode_supported)(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state); -+ void (*mac_port_validate)(struct dsa_switch *ds, int port, -+ unsigned long *supported); -+ int (*mac_port_get_state)(struct dsa_switch *ds, int port, -+ struct phylink_link_state *state); -+ int (*mac_port_config)(struct dsa_switch *ds, int port, -+ unsigned int mode, -+ phy_interface_t interface); -+}; -+ - /* struct mt7530_priv - This is the main data structure for holding the state - * of the driver - * @dev: The device pointer -@@ -476,6 +510,7 @@ struct mt7530_priv { - struct regulator *core_pwr; - struct regulator *io_pwr; - struct gpio_desc *reset; -+ const struct mt753x_info *info; - unsigned int id; - bool mcm; - phy_interface_t p6_interface; diff --git a/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch b/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch deleted file mode 100644 index 8ede862204..0000000000 --- a/target/linux/mediatek/patches-5.4/0604-net-dsa-mt7530-Add-the-support-of-MT7531-switch.patch +++ /dev/null @@ -1,1510 +0,0 @@ -From: Landen Chao <landen.chao@mediatek.com> -Date: Fri, 4 Sep 2020 22:21:59 +0800 -Subject: [PATCH] net: dsa: mt7530: Add the support of MT7531 switch - -Add new support for MT7531: - -MT7531 is the next generation of MT7530. It is also a 7-ports switch with -5 giga embedded phys, 2 cpu ports, and the same MAC logic of MT7530. Cpu -port 6 only supports SGMII interface. Cpu port 5 supports either RGMII -or SGMII in different HW sku, but cannot be muxed to PHY of port 0/4 like -mt7530. Due to SGMII interface support, pll, and pad setting are different -from MT7530. This patch adds different initial setting, and SGMII phylink -handlers of MT7531. - -MT7531 SGMII interface can be configured in following mode: -- 'SGMII AN mode' with in-band negotiation capability - which is compatible with PHY_INTERFACE_MODE_SGMII. -- 'SGMII force mode' without in-band negotiation - which is compatible with 10B/8B encoding of - PHY_INTERFACE_MODE_1000BASEX with fixed full-duplex and fixed pause. -- 2.5 times faster clocked 'SGMII force mode' without in-band negotiation - which is compatible with 10B/8B encoding of - PHY_INTERFACE_MODE_2500BASEX with fixed full-duplex and fixed pause. - -Signed-off-by: Landen Chao <landen.chao@mediatek.com> -Signed-off-by: Sean Wang <sean.wang@mediatek.com> ---- - ---- a/drivers/net/dsa/mt7530.c -+++ b/drivers/net/dsa/mt7530.c -@@ -235,6 +235,12 @@ mt7530_write(struct mt7530_priv *priv, u - } - - static u32 -+_mt7530_unlocked_read(struct mt7530_dummy_poll *p) -+{ -+ return mt7530_mii_read(p->priv, p->reg); -+} -+ -+static u32 - _mt7530_read(struct mt7530_dummy_poll *p) - { - struct mii_bus *bus = p->priv->bus; -@@ -482,6 +488,108 @@ mt7530_pad_clk_setup(struct dsa_switch * - return 0; - } - -+static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv) -+{ -+ u32 val; -+ -+ val = mt7530_read(priv, MT7531_TOP_SIG_SR); -+ -+ return (val & PAD_DUAL_SGMII_EN) != 0; -+} -+ -+static int -+mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 val; -+ u32 top_sig; -+ u32 hwstrap; -+ u32 xtal; -+ -+ if (mt7531_dual_sgmii_supported(priv)) -+ return 0; -+ -+ val = mt7530_read(priv, MT7531_CREV); -+ top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR); -+ hwstrap = mt7530_read(priv, MT7531_HWTRAP); -+ if ((val & CHIP_REV_M) > 0) -+ xtal = (top_sig & PAD_MCM_SMI_EN) ? HWTRAP_XTAL_FSEL_40MHZ : -+ HWTRAP_XTAL_FSEL_25MHZ; -+ else -+ xtal = hwstrap & HWTRAP_XTAL_FSEL_MASK; -+ -+ /* Step 1 : Disable MT7531 COREPLL */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val &= ~EN_COREPLL; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ /* Step 2: switch to XTAL output */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= SW_CLKSW; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_EN; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Step 3: disable PLLGP and enable program PLLGP */ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= SW_PLLGP; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ -+ /* Step 4: program COREPLL output frequency to 500MHz */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_POSDIV_M; -+ val |= 2 << RG_COREPLL_POSDIV_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ usleep_range(25, 35); -+ -+ switch (xtal) { -+ case HWTRAP_XTAL_FSEL_25MHZ: -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_M; -+ val |= 0x140000 << RG_COREPLL_SDM_PCW_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ break; -+ case HWTRAP_XTAL_FSEL_40MHZ: -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_M; -+ val |= 0x190000 << RG_COREPLL_SDM_PCW_S; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ break; -+ }; -+ -+ /* Set feedback divide ratio update signal to high */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val |= RG_COREPLL_SDM_PCW_CHG; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ /* Wait for at least 16 XTAL clocks */ -+ usleep_range(10, 20); -+ -+ /* Step 5: set feedback divide ratio update signal to low */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val &= ~RG_COREPLL_SDM_PCW_CHG; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ /* Enable 325M clock for SGMII */ -+ mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000); -+ -+ /* Enable 250SSC clock for RGMII */ -+ mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000); -+ -+ /* Step 6: Enable MT7531 PLL */ -+ val = mt7530_read(priv, MT7531_PLLGP_CR0); -+ val |= RG_COREPLL_EN; -+ mt7530_write(priv, MT7531_PLLGP_CR0, val); -+ -+ val = mt7530_read(priv, MT7531_PLLGP_EN); -+ val |= EN_COREPLL; -+ mt7530_write(priv, MT7531_PLLGP_EN, val); -+ usleep_range(25, 35); -+ -+ return 0; -+} -+ - static void - mt7530_mib_reset(struct dsa_switch *ds) - { -@@ -506,6 +614,217 @@ static int mt7530_phy_write(struct dsa_s - return mdiobus_write_nested(priv->bus, port, regnum, val); - } - -+static int -+mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, -+ int regnum) -+{ -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ u32 reg, val; -+ int ret; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) | -+ MT7531_MDIO_DEV_ADDR(devad) | regnum; -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MT7531_MDIO_CL45_READ | MT7531_MDIO_PHY_ADDR(port) | -+ MT7531_MDIO_DEV_ADDR(devad); -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ ret = val & MT7531_MDIO_RW_DATA_MASK; -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, -+ int regnum, u32 data) -+{ -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ u32 val, reg; -+ int ret; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MT7531_MDIO_CL45_ADDR | MT7531_MDIO_PHY_ADDR(port) | -+ MT7531_MDIO_DEV_ADDR(devad) | regnum; -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MT7531_MDIO_CL45_WRITE | MT7531_MDIO_PHY_ADDR(port) | -+ MT7531_MDIO_DEV_ADDR(devad) | data; -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum) -+{ -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ int ret; -+ u32 val; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(port) | -+ MT7531_MDIO_REG_ADDR(regnum); -+ -+ mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, -+ !(val & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ ret = val & MT7531_MDIO_RW_DATA_MASK; -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, -+ u16 data) -+{ -+ struct mii_bus *bus = priv->bus; -+ struct mt7530_dummy_poll p; -+ int ret; -+ u32 reg; -+ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, -+ !(reg & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+ reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(port) | -+ MT7531_MDIO_REG_ADDR(regnum) | data; -+ -+ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST); -+ -+ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, -+ !(reg & MT7531_PHY_ACS_ST), 20, 100000); -+ if (ret < 0) { -+ dev_err(priv->dev, "poll timeout\n"); -+ goto out; -+ } -+ -+out: -+ mutex_unlock(&bus->mdio_lock); -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int devad; -+ int ret; -+ -+ if (regnum & MII_ADDR_C45) { -+ devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f; -+ ret = mt7531_ind_c45_phy_read(priv, port, devad, -+ regnum & MII_REGADDR_C45_MASK); -+ } else { -+ ret = mt7531_ind_c22_phy_read(priv, port, regnum); -+ } -+ -+ return ret; -+} -+ -+static int -+mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, -+ u16 data) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int devad; -+ int ret; -+ -+ if (regnum & MII_ADDR_C45) { -+ devad = (regnum >> MII_DEVADDR_C45_SHIFT) & 0x1f; -+ ret = mt7531_ind_c45_phy_write(priv, port, devad, -+ regnum & MII_REGADDR_C45_MASK, -+ data); -+ } else { -+ ret = mt7531_ind_c22_phy_write(priv, port, regnum, data); -+ } -+ -+ return ret; -+} -+ - static void - mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, - uint8_t *data) -@@ -622,9 +941,14 @@ unlock_exit: - } - - static int --mt7530_cpu_port_enable(struct mt7530_priv *priv, -- int port) -+mt753x_cpu_port_enable(struct dsa_switch *ds, int port) - { -+ struct mt7530_priv *priv = ds->priv; -+ -+ /* Setup max capability of CPU port at first */ -+ if (priv->info->cpu_port_config) -+ priv->info->cpu_port_config(ds, port); -+ - /* Enable Mediatek header mode on the cpu port */ - mt7530_write(priv, MT7530_PVC_P(port), - PORT_SPEC_TAG); -@@ -637,7 +961,7 @@ mt7530_cpu_port_enable(struct mt7530_pri - mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); - - /* CPU port gets connected to all user ports of -- * the switch -+ * the switch. - */ - mt7530_write(priv, MT7530_PCR_P(port), - PCR_MATRIX(dsa_user_ports(priv->ds))); -@@ -1120,27 +1444,42 @@ mt7530_port_vlan_del(struct dsa_switch * - return 0; - } - --static int mt7530_port_mirror_add(struct dsa_switch *ds, int port, -+static int mt753x_mirror_port_get(unsigned int id, u32 val) -+{ -+ return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) : -+ MIRROR_PORT(val); -+} -+ -+static int mt753x_mirror_port_set(unsigned int id, u32 val) -+{ -+ return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) : -+ MIRROR_PORT(val); -+} -+ -+static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress) - { - struct mt7530_priv *priv = ds->priv; -+ int monitor_port; - u32 val; - - /* Check for existent entry */ - if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) - return -EEXIST; - -- val = mt7530_read(priv, MT7530_MFC); -+ val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id)); - - /* MT7530 only supports one monitor port */ -- if (val & MIRROR_EN && MIRROR_PORT(val) != mirror->to_local_port) -+ monitor_port = mt753x_mirror_port_get(priv->id, val); -+ if (val & MT753X_MIRROR_EN(priv->id) && -+ monitor_port != mirror->to_local_port) - return -EEXIST; - -- val |= MIRROR_EN; -- val &= ~MIRROR_MASK; -- val |= mirror->to_local_port; -- mt7530_write(priv, MT7530_MFC, val); -+ val |= MT753X_MIRROR_EN(priv->id); -+ val &= ~MT753X_MIRROR_MASK(priv->id); -+ val |= mt753x_mirror_port_set(priv->id, mirror->to_local_port); -+ mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val); - - val = mt7530_read(priv, MT7530_PCR_P(port)); - if (ingress) { -@@ -1155,7 +1494,7 @@ static int mt7530_port_mirror_add(struct - return 0; - } - --static void mt7530_port_mirror_del(struct dsa_switch *ds, int port, -+static void mt753x_port_mirror_del(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror) - { - struct mt7530_priv *priv = ds->priv; -@@ -1172,9 +1511,9 @@ static void mt7530_port_mirror_del(struc - mt7530_write(priv, MT7530_PCR_P(port), val); - - if (!priv->mirror_rx && !priv->mirror_tx) { -- val = mt7530_read(priv, MT7530_MFC); -- val &= ~MIRROR_EN; -- mt7530_write(priv, MT7530_MFC, val); -+ val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id)); -+ val &= ~MT753X_MIRROR_EN(priv->id); -+ mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val); - } - } - -@@ -1280,7 +1619,7 @@ mt7530_setup(struct dsa_switch *ds) - PCR_MATRIX_CLR); - - if (dsa_is_cpu_port(ds, i)) -- mt7530_cpu_port_enable(priv, i); -+ mt753x_cpu_port_enable(ds, i); - else - mt7530_port_disable(ds, i); - -@@ -1334,6 +1673,118 @@ mt7530_setup(struct dsa_switch *ds) - return 0; - } - -+static int -+mt7531_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct mt7530_dummy_poll p; -+ u32 val, id; -+ int ret, i; -+ -+ /* Reset whole chip through gpio pin or memory-mapped registers for -+ * different type of hardware -+ */ -+ if (priv->mcm) { -+ reset_control_assert(priv->rstc); -+ usleep_range(1000, 1100); -+ reset_control_deassert(priv->rstc); -+ } else { -+ gpiod_set_value_cansleep(priv->reset, 0); -+ usleep_range(1000, 1100); -+ gpiod_set_value_cansleep(priv->reset, 1); -+ } -+ -+ /* Waiting for MT7530 got to stable */ -+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_HWTRAP); -+ ret = readx_poll_timeout(_mt7530_read, &p, val, val != 0, -+ 20, 1000000); -+ if (ret < 0) { -+ dev_err(priv->dev, "reset timeout\n"); -+ return ret; -+ } -+ -+ id = mt7530_read(priv, MT7531_CREV); -+ id >>= CHIP_NAME_SHIFT; -+ -+ if (id != MT7531_ID) { -+ dev_err(priv->dev, "chip %x can't be supported\n", id); -+ return -ENODEV; -+ } -+ -+ /* Reset the switch through internal reset */ -+ mt7530_write(priv, MT7530_SYS_CTRL, -+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | -+ SYS_CTRL_REG_RST); -+ -+ if (mt7531_dual_sgmii_supported(priv)) { -+ priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII; -+ -+ /* Let ds->slave_mii_bus be able to access external phy. */ -+ mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO11_RG_RXD2_MASK, -+ MT7531_EXT_P_MDC_11); -+ mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO12_RG_RXD3_MASK, -+ MT7531_EXT_P_MDIO_12); -+ } else { -+ priv->p5_intf_sel = P5_INTF_SEL_GMAC5; -+ } -+ dev_dbg(ds->dev, "P5 support %s interface\n", -+ p5_intf_modes(priv->p5_intf_sel)); -+ -+ mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, -+ MT7531_GPIO0_INTERRUPT); -+ -+ /* Let phylink decide the interface later. */ -+ priv->p5_interface = PHY_INTERFACE_MODE_NA; -+ priv->p6_interface = PHY_INTERFACE_MODE_NA; -+ -+ /* Enable PHY core PLL, since phy_device has not yet been created -+ * provided for phy_[read,write]_mmd_indirect is called, we provide -+ * our own mt7531_ind_mmd_phy_[read,write] to complete this -+ * function. -+ */ -+ val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR, -+ MDIO_MMD_VEND2, CORE_PLL_GROUP4); -+ val |= MT7531_PHY_PLL_BYPASS_MODE; -+ val &= ~MT7531_PHY_PLL_OFF; -+ mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, -+ CORE_PLL_GROUP4, val); -+ -+ /* BPDU to CPU port */ -+ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, -+ BIT(MT7530_CPU_PORT)); -+ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, -+ MT753X_BPDU_CPU_ONLY); -+ -+ /* Enable and reset MIB counters */ -+ mt7530_mib_reset(ds); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ /* Disable forwarding by default on all ports */ -+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, -+ PCR_MATRIX_CLR); -+ -+ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); -+ -+ if (dsa_is_cpu_port(ds, i)) -+ mt753x_cpu_port_enable(ds, i); -+ else -+ mt7530_port_disable(ds, i); -+ -+ /* Enable consistent egress tag */ -+ mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, -+ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); -+ } -+ -+ ds->configure_vlan_while_not_filtering = true; -+ -+ /* Flush the FDB table */ -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ - static bool - mt7530_phy_mode_supported(struct dsa_switch *ds, int port, - const struct phylink_link_state *state) -@@ -1372,6 +1823,47 @@ unsupported: - return false; - } - -+static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) -+{ -+ return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); -+} -+ -+static bool -+mt7531_phy_supported(struct dsa_switch *ds, int port, -+ const struct phylink_link_state *state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ switch (port) { -+ case 0: /* Internal phy */ -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ if (state->interface != PHY_INTERFACE_MODE_GMII) -+ goto unsupported; -+ break; -+ case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ -+ if (mt7531_is_rgmii_port(priv, port)) -+ return phy_interface_mode_is_rgmii(state->interface); -+ fallthrough; -+ case 6: /* 1st cpu port supports sgmii/8023z only */ -+ if (state->interface != PHY_INTERFACE_MODE_SGMII && -+ !phy_interface_mode_is_8023z(state->interface)) -+ goto unsupported; -+ break; -+ default: -+ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, -+ port); -+ goto unsupported; -+ } -+ -+ return true; -+ -+unsupported: -+ return false; -+} -+ - static bool - mt753x_phy_mode_supported(struct dsa_switch *ds, int port, - const struct phylink_link_state *state) -@@ -1404,6 +1896,227 @@ mt7530_mac_config(struct dsa_switch *ds, - return 0; - } - -+static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port, -+ phy_interface_t interface, -+ struct phy_device *phydev) -+{ -+ u32 val; -+ -+ if (!mt7531_is_rgmii_port(priv, port)) { -+ dev_err(priv->dev, "RGMII mode is not available for port %d\n", -+ port); -+ return -EINVAL; -+ } -+ -+ val = mt7530_read(priv, MT7531_CLKGEN_CTRL); -+ val |= GP_CLK_EN; -+ val &= ~GP_MODE_MASK; -+ val |= GP_MODE(MT7531_GP_MODE_RGMII); -+ val &= ~CLK_SKEW_IN_MASK; -+ val |= CLK_SKEW_IN(MT7531_CLK_SKEW_NO_CHG); -+ val &= ~CLK_SKEW_OUT_MASK; -+ val |= CLK_SKEW_OUT(MT7531_CLK_SKEW_NO_CHG); -+ val |= TXCLK_NO_REVERSE | RXCLK_NO_DELAY; -+ -+ /* Do not adjust rgmii delay when vendor phy driver presents. */ -+ if (!phydev || phy_driver_is_genphy(phydev)) { -+ val &= ~(TXCLK_NO_REVERSE | RXCLK_NO_DELAY); -+ switch (interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ val |= TXCLK_NO_REVERSE; -+ val |= RXCLK_NO_DELAY; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ val |= TXCLK_NO_REVERSE; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ val |= RXCLK_NO_DELAY; -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ break; -+ default: -+ return -EINVAL; -+ } -+ } -+ mt7530_write(priv, MT7531_CLKGEN_CTRL, val); -+ -+ return 0; -+} -+ -+static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, -+ unsigned long *supported) -+{ -+ /* Port5 supports ethier RGMII or SGMII. -+ * Port6 supports SGMII only. -+ */ -+ switch (port) { -+ case 5: -+ if (mt7531_is_rgmii_port(priv, port)) -+ break; -+ fallthrough; -+ case 6: -+ phylink_set(supported, 1000baseX_Full); -+ phylink_set(supported, 2500baseX_Full); -+ phylink_set(supported, 2500baseT_Full); -+ } -+} -+ -+static void -+mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ unsigned int val; -+ -+ /* For adjusting speed and duplex of SGMII force mode. */ -+ if (interface != PHY_INTERFACE_MODE_SGMII || -+ phylink_autoneg_inband(mode)) -+ return; -+ -+ /* SGMII force mode setting */ -+ val = mt7530_read(priv, MT7531_SGMII_MODE(port)); -+ val &= ~MT7531_SGMII_IF_MODE_MASK; -+ -+ switch (speed) { -+ case SPEED_10: -+ val |= MT7531_SGMII_FORCE_SPEED_10; -+ break; -+ case SPEED_100: -+ val |= MT7531_SGMII_FORCE_SPEED_100; -+ break; -+ case SPEED_1000: -+ val |= MT7531_SGMII_FORCE_SPEED_1000; -+ break; -+ } -+ -+ /* MT7531 SGMII 1G force mode can only work in full duplex mode, -+ * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. -+ */ -+ if ((speed == SPEED_10 || speed == SPEED_100) && -+ duplex != DUPLEX_FULL) -+ val |= MT7531_SGMII_FORCE_HALF_DUPLEX; -+ -+ mt7530_write(priv, MT7531_SGMII_MODE(port), val); -+} -+ -+static bool mt753x_is_mac_port(u32 port) -+{ -+ return (port == 5 || port == 6); -+} -+ -+static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port, -+ phy_interface_t interface) -+{ -+ u32 val; -+ -+ if (!mt753x_is_mac_port(port)) -+ return -EINVAL; -+ -+ mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), -+ MT7531_SGMII_PHYA_PWD); -+ -+ val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port)); -+ val &= ~MT7531_RG_TPHY_SPEED_MASK; -+ /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B -+ * encoding. -+ */ -+ val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ? -+ MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G; -+ mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val); -+ -+ mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); -+ -+ /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex -+ * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. -+ */ -+ mt7530_rmw(priv, MT7531_SGMII_MODE(port), -+ MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS, -+ MT7531_SGMII_FORCE_SPEED_1000); -+ -+ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); -+ -+ return 0; -+} -+ -+static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port, -+ phy_interface_t interface) -+{ -+ if (!mt753x_is_mac_port(port)) -+ return -EINVAL; -+ -+ mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port), -+ MT7531_SGMII_PHYA_PWD); -+ -+ mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port), -+ MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G); -+ -+ mt7530_set(priv, MT7531_SGMII_MODE(port), -+ MT7531_SGMII_REMOTE_FAULT_DIS | -+ MT7531_SGMII_SPEED_DUPLEX_AN); -+ -+ mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port), -+ MT7531_SGMII_TX_CONFIG_MASK, 1); -+ -+ mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE); -+ -+ mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART); -+ -+ mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0); -+ -+ return 0; -+} -+ -+static void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 val; -+ -+ /* Only restart AN when AN is enabled */ -+ val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -+ if (val & MT7531_SGMII_AN_ENABLE) { -+ val |= MT7531_SGMII_AN_RESTART; -+ mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val); -+ } -+} -+ -+static int -+mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct phy_device *phydev; -+ const struct dsa_port *dp; -+ -+ if (!mt753x_is_mac_port(port)) { -+ dev_err(priv->dev, "port %d is not a MAC port\n", port); -+ return -EINVAL; -+ } -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ dp = dsa_to_port(ds, port); -+ phydev = dp->slave->phydev; -+ return mt7531_rgmii_setup(priv, port, interface, phydev); -+ case PHY_INTERFACE_MODE_SGMII: -+ return mt7531_sgmii_setup_mode_an(priv, port, interface); -+ case PHY_INTERFACE_MODE_NA: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ case PHY_INTERFACE_MODE_2500BASEX: -+ if (phylink_autoneg_inband(mode)) -+ return -EINVAL; -+ -+ return mt7531_sgmii_setup_mode_force(priv, port, interface); -+ default: -+ return -EINVAL; -+ } -+ -+ return -EINVAL; -+} -+ - static int - mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, - const struct phylink_link_state *state) -@@ -1439,6 +2152,8 @@ mt753x_phylink_mac_config(struct dsa_swi - if (mt753x_mac_config(ds, port, mode, state) < 0) - goto unsupported; - -+ if (priv->p5_intf_sel != P5_DISABLED) -+ priv->p5_interface = state->interface; - break; - case 6: /* 1st cpu port */ - if (priv->p6_interface == state->interface) -@@ -1458,7 +2173,8 @@ unsupported: - return; - } - -- if (phylink_autoneg_inband(mode)) { -+ if (phylink_autoneg_inband(mode) && -+ state->interface != PHY_INTERFACE_MODE_SGMII) { - dev_err(ds->dev, "%s: in-band negotiation unsupported\n", - __func__); - return; -@@ -1468,7 +2184,7 @@ unsupported: - mcr_new = mcr_cur; - mcr_new &= ~PMCR_LINK_SETTINGS_MASK; - mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | -- PMCR_BACKPR_EN | PMCR_FORCE_MODE; -+ PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id); - - /* Are we connected to external phy */ - if (port == 5 && dsa_is_user_port(ds, 5)) -@@ -1478,7 +2194,18 @@ unsupported: - mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); - } - --static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port, -+static void -+mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (!priv->info->mac_pcs_an_restart) -+ return; -+ -+ priv->info->mac_pcs_an_restart(ds, port); -+} -+ -+static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface) - { -@@ -1487,7 +2214,19 @@ static void mt7530_phylink_mac_link_down - mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); - } - --static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port, -+static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (!priv->info->mac_pcs_link_up) -+ return; -+ -+ priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex); -+} -+ -+static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface, - struct phy_device *phydev, -@@ -1497,18 +2236,29 @@ static void mt7530_phylink_mac_link_up(s - struct mt7530_priv *priv = ds->priv; - u32 mcr; - -+ mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex); -+ - mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; - -+ /* MT753x MAC works in 1G full duplex mode for all up-clocked -+ * variants. -+ */ -+ if (interface == PHY_INTERFACE_MODE_TRGMII || -+ (phy_interface_mode_is_8023z(interface))) { -+ speed = SPEED_1000; -+ duplex = DUPLEX_FULL; -+ } -+ - switch (speed) { - case SPEED_1000: - mcr |= PMCR_FORCE_SPEED_1000; - if (priv->eee_enable & BIT(port)) -- mcr_new |= PMCR_FORCE_EEE1G; -+ mcr |= PMCR_FORCE_EEE1G; - break; - case SPEED_100: - mcr |= PMCR_FORCE_SPEED_100; - if (priv->eee_enable & BIT(port)) -- mcr_new |= PMCR_FORCE_EEE100; -+ mcr |= PMCR_FORCE_EEE100; - break; - } - if (duplex == DUPLEX_FULL) { -@@ -1522,6 +2272,45 @@ static void mt7530_phylink_mac_link_up(s - mt7530_set(priv, MT7530_PMCR_P(port), mcr); - } - -+static int -+mt7531_cpu_port_config(struct dsa_switch *ds, int port) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ phy_interface_t interface; -+ int speed; -+ -+ switch (port) { -+ case 5: -+ if (mt7531_is_rgmii_port(priv, port)) -+ interface = PHY_INTERFACE_MODE_RGMII; -+ else -+ interface = PHY_INTERFACE_MODE_2500BASEX; -+ -+ priv->p5_interface = interface; -+ break; -+ case 6: -+ interface = PHY_INTERFACE_MODE_2500BASEX; -+ -+ mt7531_pad_setup(ds, interface); -+ -+ priv->p6_interface = interface; -+ break; -+ }; -+ -+ if (interface == PHY_INTERFACE_MODE_2500BASEX) -+ speed = SPEED_2500; -+ else -+ speed = SPEED_1000; -+ -+ mt7531_mac_config(ds, port, MLO_AN_FIXED, interface); -+ mt7530_write(priv, MT7530_PMCR_P(port), -+ PMCR_CPU_PORT_SETTING(priv->id)); -+ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, -+ speed, DUPLEX_FULL, true, true); -+ -+ return 0; -+} -+ - static void - mt7530_mac_port_validate(struct dsa_switch *ds, int port, - unsigned long *supported) -@@ -1530,6 +2319,14 @@ mt7530_mac_port_validate(struct dsa_swit - phylink_set(supported, 1000baseX_Full); - } - -+static void mt7531_mac_port_validate(struct dsa_switch *ds, int port, -+ unsigned long *supported) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ mt7531_sgmii_validate(priv, port, supported); -+} -+ - static void - mt753x_phylink_validate(struct dsa_switch *ds, int port, - unsigned long *supported, -@@ -1546,7 +2343,8 @@ mt753x_phylink_validate(struct dsa_switc - - phylink_set_port_modes(mask); - -- if (state->interface != PHY_INTERFACE_MODE_TRGMII) { -+ if (state->interface != PHY_INTERFACE_MODE_TRGMII || -+ !phy_interface_mode_is_8023z(state->interface)) { - phylink_set(mask, 10baseT_Half); - phylink_set(mask, 10baseT_Full); - phylink_set(mask, 100baseT_Half); -@@ -1565,6 +2363,11 @@ mt753x_phylink_validate(struct dsa_switc - - linkmode_and(supported, supported, mask); - linkmode_and(state->advertising, state->advertising, mask); -+ -+ /* We can only operate at 2500BaseX or 1000BaseX. If requested -+ * to advertise both, only report advertising at 2500BaseX. -+ */ -+ phylink_helper_basex_speed(state); - } - - static int -@@ -1655,6 +2458,63 @@ static int mt7530_set_mac_eee(struct dsa - return 0; - } - -+#ifdef notyet -+static int -+mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port, -+ struct phylink_link_state *state) -+{ -+ u32 status, val; -+ u16 config_reg; -+ -+ status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port)); -+ state->link = !!(status & MT7531_SGMII_LINK_STATUS); -+ if (state->interface == PHY_INTERFACE_MODE_SGMII && -+ (status & MT7531_SGMII_AN_ENABLE)) { -+ val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port)); -+ config_reg = val >> 16; -+ -+ switch (config_reg & LPA_SGMII_SPD_MASK) { -+ case LPA_SGMII_1000: -+ state->speed = SPEED_1000; -+ break; -+ case LPA_SGMII_100: -+ state->speed = SPEED_100; -+ break; -+ case LPA_SGMII_10: -+ state->speed = SPEED_10; -+ break; -+ default: -+ dev_err(priv->dev, "invalid sgmii PHY speed\n"); -+ state->link = false; -+ return -EINVAL; -+ } -+ -+ if (config_reg & LPA_SGMII_FULL_DUPLEX) -+ state->duplex = DUPLEX_FULL; -+ else -+ state->duplex = DUPLEX_HALF; -+ } -+ -+ return 0; -+} -+#endif -+ -+static int -+mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port, -+ struct phylink_link_state *state) -+{ -+#ifdef notyet -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (state->interface == PHY_INTERFACE_MODE_SGMII) -+ return mt7531_sgmii_pcs_get_state_an(priv, port, state); -+#else -+ return mt7530_phylink_mac_link_state(ds, port, state); -+#endif -+ -+ return -EOPNOTSUPP; -+} -+ - static int - mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, - struct phylink_link_state *state) -@@ -1708,13 +2568,14 @@ static const struct dsa_switch_ops mt753 - .port_vlan_prepare = mt7530_port_vlan_prepare, - .port_vlan_add = mt7530_port_vlan_add, - .port_vlan_del = mt7530_port_vlan_del, -- .port_mirror_add = mt7530_port_mirror_add, -- .port_mirror_del = mt7530_port_mirror_del, -+ .port_mirror_add = mt753x_port_mirror_add, -+ .port_mirror_del = mt753x_port_mirror_del, - .phylink_validate = mt753x_phylink_validate, - .phylink_mac_link_state = mt753x_phylink_mac_link_state, - .phylink_mac_config = mt753x_phylink_mac_config, -- .phylink_mac_link_down = mt7530_phylink_mac_link_down, -- .phylink_mac_link_up = mt7530_phylink_mac_link_up, -+ .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, -+ .phylink_mac_link_down = mt753x_phylink_mac_link_down, -+ .phylink_mac_link_up = mt753x_phylink_mac_link_up, - .get_mac_eee = mt7530_get_mac_eee, - .set_mac_eee = mt7530_set_mac_eee, - }; -@@ -1742,11 +2603,26 @@ static const struct mt753x_info mt753x_t - .mac_port_get_state = mt7530_phylink_mac_link_state, - .mac_port_config = mt7530_mac_config, - }, -+ [ID_MT7531] = { -+ .id = ID_MT7531, -+ .sw_setup = mt7531_setup, -+ .phy_read = mt7531_ind_phy_read, -+ .phy_write = mt7531_ind_phy_write, -+ .pad_setup = mt7531_pad_setup, -+ .cpu_port_config = mt7531_cpu_port_config, -+ .phy_mode_supported = mt7531_phy_supported, -+ .mac_port_validate = mt7531_mac_port_validate, -+ .mac_port_get_state = mt7531_phylink_mac_link_state, -+ .mac_port_config = mt7531_mac_config, -+ .mac_pcs_an_restart = mt7531_sgmii_restart_an, -+ .mac_pcs_link_up = mt7531_sgmii_link_up_force, -+ }, - }; - - static const struct of_device_id mt7530_of_match[] = { - { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, - { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, -+ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, - { /* sentinel */ }, - }; - MODULE_DEVICE_TABLE(of, mt7530_of_match); ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -14,6 +14,7 @@ - enum mt753x_id { - ID_MT7530 = 0, - ID_MT7621 = 1, -+ ID_MT7531 = 2, - }; - - #define NUM_TRGMII_CTRL 5 -@@ -41,6 +42,33 @@ enum mt753x_id { - #define MIRROR_PORT(x) ((x) & 0x7) - #define MIRROR_MASK 0x7 - -+/* Registers for CPU forward control */ -+#define MT7531_CFC 0x4 -+#define MT7531_MIRROR_EN BIT(19) -+#define MT7531_MIRROR_MASK (MIRROR_MASK << 16) -+#define MT7531_MIRROR_PORT_GET(x) (((x) >> 16) & MIRROR_MASK) -+#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16) -+#define MT7531_CPU_PMAP_MASK GENMASK(7, 0) -+ -+#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \ -+ MT7531_CFC : MT7530_MFC) -+#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \ -+ MT7531_MIRROR_EN : MIRROR_EN) -+#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \ -+ MT7531_MIRROR_MASK : MIRROR_MASK) -+ -+/* Registers for BPDU and PAE frame control*/ -+#define MT753X_BPC 0x24 -+#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0) -+ -+enum mt753x_bpdu_port_fw { -+ MT753X_BPDU_FOLLOW_MFC, -+ MT753X_BPDU_CPU_EXCLUDE = 4, -+ MT753X_BPDU_CPU_INCLUDE = 5, -+ MT753X_BPDU_CPU_ONLY = 6, -+ MT753X_BPDU_DROP = 7, -+}; -+ - /* Registers for address table access */ - #define MT7530_ATA1 0x74 - #define STATIC_EMP 0 -@@ -222,10 +250,30 @@ enum mt7530_vlan_port_attr { - #define PMCR_FORCE_LNK BIT(0) - #define PMCR_SPEED_MASK (PMCR_FORCE_SPEED_100 | \ - PMCR_FORCE_SPEED_1000) -+#define MT7531_FORCE_LNK BIT(31) -+#define MT7531_FORCE_SPD BIT(30) -+#define MT7531_FORCE_DPX BIT(29) -+#define MT7531_FORCE_RX_FC BIT(28) -+#define MT7531_FORCE_TX_FC BIT(27) -+#define MT7531_FORCE_MODE (MT7531_FORCE_LNK | \ -+ MT7531_FORCE_SPD | \ -+ MT7531_FORCE_DPX | \ -+ MT7531_FORCE_RX_FC | \ -+ MT7531_FORCE_TX_FC) -+#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \ -+ MT7531_FORCE_MODE : \ -+ PMCR_FORCE_MODE) - #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ - PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ - PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ - PMCR_FORCE_FDX | PMCR_FORCE_LNK) -+#define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \ -+ PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ -+ PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ -+ PMCR_TX_EN | PMCR_RX_EN | \ -+ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ -+ PMCR_FORCE_SPEED_1000 | \ -+ PMCR_FORCE_FDX | PMCR_FORCE_LNK) - - #define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) - #define PMSR_EEE1G BIT(7) -@@ -245,6 +293,10 @@ enum mt7530_vlan_port_attr { - #define LPI_THRESH(x) ((x & 0xFFF) << 4) - #define LPI_MODE_EN BIT(0) - -+/* Register for port debug count */ -+#define MT7531_DBG_CNT(x) (0x3018 + (x) * 0x100) -+#define MT7531_DIS_CLR BIT(31) -+ - /* Register for MIB */ - #define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100) - #define MT7530_MIB_CCR 0x4fe0 -@@ -262,12 +314,118 @@ enum mt7530_vlan_port_attr { - CCR_RX_OCT_CNT_BAD | \ - CCR_TX_OCT_CNT_GOOD | \ - CCR_TX_OCT_CNT_BAD) -+ -+/* MT7531 SGMII register group */ -+#define MT7531_SGMII_REG_BASE 0x5000 -+#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \ -+ ((p) - 5) * 0x1000 + (r)) -+ -+/* Register forSGMII PCS_CONTROL_1 */ -+#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00) -+#define MT7531_SGMII_LINK_STATUS BIT(18) -+#define MT7531_SGMII_AN_ENABLE BIT(12) -+#define MT7531_SGMII_AN_RESTART BIT(9) -+ -+/* Register for SGMII PCS_SPPED_ABILITY */ -+#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08) -+#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0) -+#define MT7531_SGMII_TX_CONFIG BIT(0) -+ -+/* Register for SGMII_MODE */ -+#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20) -+#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8) -+#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1) -+#define MT7531_SGMII_FORCE_DUPLEX BIT(4) -+#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2) -+#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3) -+#define MT7531_SGMII_FORCE_SPEED_100 BIT(2) -+#define MT7531_SGMII_FORCE_SPEED_10 0 -+#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1) -+ -+enum mt7531_sgmii_force_duplex { -+ MT7531_SGMII_FORCE_FULL_DUPLEX = 0, -+ MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10, -+}; -+ -+/* Fields of QPHY_PWR_STATE_CTRL */ -+#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8) -+#define MT7531_SGMII_PHYA_PWD BIT(4) -+ -+/* Values of SGMII SPEED */ -+#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128) -+#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3)) -+#define MT7531_RG_TPHY_SPEED_1_25G 0x0 -+#define MT7531_RG_TPHY_SPEED_3_125G BIT(2) -+ - /* Register for system reset */ - #define MT7530_SYS_CTRL 0x7000 - #define SYS_CTRL_PHY_RST BIT(2) - #define SYS_CTRL_SW_RST BIT(1) - #define SYS_CTRL_REG_RST BIT(0) - -+/* Register for PHY Indirect Access Control */ -+#define MT7531_PHY_IAC 0x701C -+#define MT7531_PHY_ACS_ST BIT(31) -+#define MT7531_MDIO_REG_ADDR_MASK (0x1f << 25) -+#define MT7531_MDIO_PHY_ADDR_MASK (0x1f << 20) -+#define MT7531_MDIO_CMD_MASK (0x3 << 18) -+#define MT7531_MDIO_ST_MASK (0x3 << 16) -+#define MT7531_MDIO_RW_DATA_MASK (0xffff) -+#define MT7531_MDIO_REG_ADDR(x) (((x) & 0x1f) << 25) -+#define MT7531_MDIO_DEV_ADDR(x) (((x) & 0x1f) << 25) -+#define MT7531_MDIO_PHY_ADDR(x) (((x) & 0x1f) << 20) -+#define MT7531_MDIO_CMD(x) (((x) & 0x3) << 18) -+#define MT7531_MDIO_ST(x) (((x) & 0x3) << 16) -+ -+enum mt7531_phy_iac_cmd { -+ MT7531_MDIO_ADDR = 0, -+ MT7531_MDIO_WRITE = 1, -+ MT7531_MDIO_READ = 2, -+ MT7531_MDIO_READ_CL45 = 3, -+}; -+ -+/* MDIO_ST: MDIO start field */ -+enum mt7531_mdio_st { -+ MT7531_MDIO_ST_CL45 = 0, -+ MT7531_MDIO_ST_CL22 = 1, -+}; -+ -+#define MT7531_MDIO_CL22_READ (MT7531_MDIO_ST(MT7531_MDIO_ST_CL22) | \ -+ MT7531_MDIO_CMD(MT7531_MDIO_READ)) -+#define MT7531_MDIO_CL22_WRITE (MT7531_MDIO_ST(MT7531_MDIO_ST_CL22) | \ -+ MT7531_MDIO_CMD(MT7531_MDIO_WRITE)) -+#define MT7531_MDIO_CL45_ADDR (MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \ -+ MT7531_MDIO_CMD(MT7531_MDIO_ADDR)) -+#define MT7531_MDIO_CL45_READ (MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \ -+ MT7531_MDIO_CMD(MT7531_MDIO_READ)) -+#define MT7531_MDIO_CL45_WRITE (MT7531_MDIO_ST(MT7531_MDIO_ST_CL45) | \ -+ MT7531_MDIO_CMD(MT7531_MDIO_WRITE)) -+ -+/* Register for RGMII clock phase */ -+#define MT7531_CLKGEN_CTRL 0x7500 -+#define CLK_SKEW_OUT(x) (((x) & 0x3) << 8) -+#define CLK_SKEW_OUT_MASK GENMASK(9, 8) -+#define CLK_SKEW_IN(x) (((x) & 0x3) << 6) -+#define CLK_SKEW_IN_MASK GENMASK(7, 6) -+#define RXCLK_NO_DELAY BIT(5) -+#define TXCLK_NO_REVERSE BIT(4) -+#define GP_MODE(x) (((x) & 0x3) << 1) -+#define GP_MODE_MASK GENMASK(2, 1) -+#define GP_CLK_EN BIT(0) -+ -+enum mt7531_gp_mode { -+ MT7531_GP_MODE_RGMII = 0, -+ MT7531_GP_MODE_MII = 1, -+ MT7531_GP_MODE_REV_MII = 2 -+}; -+ -+enum mt7531_clk_skew { -+ MT7531_CLK_SKEW_NO_CHG = 0, -+ MT7531_CLK_SKEW_DLY_100PPS = 1, -+ MT7531_CLK_SKEW_DLY_200PPS = 2, -+ MT7531_CLK_SKEW_REVERSE = 3, -+}; -+ - /* Register for hw trap status */ - #define MT7530_HWTRAP 0x7800 - #define HWTRAP_XTAL_MASK (BIT(10) | BIT(9)) -@@ -275,6 +433,16 @@ enum mt7530_vlan_port_attr { - #define HWTRAP_XTAL_40MHZ (BIT(10)) - #define HWTRAP_XTAL_20MHZ (BIT(9)) - -+#define MT7531_HWTRAP 0x7800 -+#define HWTRAP_XTAL_FSEL_MASK BIT(7) -+#define HWTRAP_XTAL_FSEL_25MHZ BIT(7) -+#define HWTRAP_XTAL_FSEL_40MHZ 0 -+/* Unique fields of (M)HWSTRAP for MT7531 */ -+#define XTAL_FSEL_S 7 -+#define XTAL_FSEL_M BIT(7) -+#define PHY_EN BIT(6) -+#define CHG_STRAP BIT(8) -+ - /* Register for hw trap modification */ - #define MT7530_MHWTRAP 0x7804 - #define MHWTRAP_PHY0_SEL BIT(20) -@@ -289,14 +457,37 @@ enum mt7530_vlan_port_attr { - #define MT7530_TOP_SIG_CTRL 0x7808 - #define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16)) - -+#define MT7531_TOP_SIG_SR 0x780c -+#define PAD_DUAL_SGMII_EN BIT(1) -+#define PAD_MCM_SMI_EN BIT(0) -+ - #define MT7530_IO_DRV_CR 0x7810 - #define P5_IO_CLK_DRV(x) ((x) & 0x3) - #define P5_IO_DATA_DRV(x) (((x) & 0x3) << 4) - -+#define MT7531_CHIP_REV 0x781C -+ -+#define MT7531_PLLGP_EN 0x7820 -+#define EN_COREPLL BIT(2) -+#define SW_CLKSW BIT(1) -+#define SW_PLLGP BIT(0) -+ - #define MT7530_P6ECR 0x7830 - #define P6_INTF_MODE_MASK 0x3 - #define P6_INTF_MODE(x) ((x) & 0x3) - -+#define MT7531_PLLGP_CR0 0x78a8 -+#define RG_COREPLL_EN BIT(22) -+#define RG_COREPLL_POSDIV_S 23 -+#define RG_COREPLL_POSDIV_M 0x3800000 -+#define RG_COREPLL_SDM_PCW_S 1 -+#define RG_COREPLL_SDM_PCW_M 0x3ffffe -+#define RG_COREPLL_SDM_PCW_CHG BIT(0) -+ -+/* Registers for RGMII and SGMII PLL clock */ -+#define MT7531_ANA_PLLGP_CR2 0x78b0 -+#define MT7531_ANA_PLLGP_CR5 0x78bc -+ - /* Registers for TRGMII on the both side */ - #define MT7530_TRGMII_RCK_CTRL 0x7a00 - #define RX_RST BIT(31) -@@ -335,10 +526,25 @@ enum mt7530_vlan_port_attr { - #define MT7530_P5RGMIITXCR 0x7b04 - #define CSR_RGMII_TXC_CFG(x) ((x) & 0x1f) - -+/* Registers for GPIO mode */ -+#define MT7531_GPIO_MODE0 0x7c0c -+#define MT7531_GPIO0_MASK GENMASK(3, 0) -+#define MT7531_GPIO0_INTERRUPT 1 -+ -+#define MT7531_GPIO_MODE1 0x7c10 -+#define MT7531_GPIO11_RG_RXD2_MASK GENMASK(15, 12) -+#define MT7531_EXT_P_MDC_11 (2 << 12) -+#define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16) -+#define MT7531_EXT_P_MDIO_12 (2 << 16) -+ - #define MT7530_CREV 0x7ffc - #define CHIP_NAME_SHIFT 16 - #define MT7530_ID 0x7530 - -+#define MT7531_CREV 0x781C -+#define CHIP_REV_M 0x0f -+#define MT7531_ID 0x7531 -+ - /* Registers for core PLL access through mmd indirect */ - #define CORE_PLL_GROUP2 0x401 - #define RG_SYSPLL_EN_NORMAL BIT(15) -@@ -355,6 +561,10 @@ enum mt7530_vlan_port_attr { - #define RG_SYSPLL_DDSFBK_EN BIT(12) - #define RG_SYSPLL_BIAS_EN BIT(11) - #define RG_SYSPLL_BIAS_LPF_EN BIT(10) -+#define MT7531_PHY_PLL_OFF BIT(5) -+#define MT7531_PHY_PLL_BYPASS_MODE BIT(4) -+ -+#define MT753X_CTRL_PHY_ADDR 0 - - #define CORE_PLL_GROUP5 0x404 - #define RG_LCDDS_PCW_NCPO1(x) ((x) & 0xffff) -@@ -433,6 +643,7 @@ enum p5_interface_select { - P5_INTF_SEL_PHY_P0, - P5_INTF_SEL_PHY_P4, - P5_INTF_SEL_GMAC5, -+ P5_INTF_SEL_GMAC5_SGMII, - }; - - static const char *p5_intf_modes(unsigned int p5_interface) -@@ -446,6 +657,8 @@ static const char *p5_intf_modes(unsigne - return "PHY P4"; - case P5_INTF_SEL_GMAC5: - return "GMAC5"; -+ case P5_INTF_SEL_GMAC5_SGMII: -+ return "GMAC5_SGMII"; - default: - return "unknown"; - } -@@ -466,6 +679,10 @@ static const char *p5_intf_modes(unsigne - * MAC port - * @mac_port_config: Holding the way setting up the PHY attribute to a - * certain MAC port -+ * @mac_pcs_an_restart Holding the way restarting PCS autonegotiation for a -+ * certain MAC port -+ * @mac_pcs_link_up: Holding the way setting up the PHY attribute to the pcs -+ * of the certain MAC port - */ - struct mt753x_info { - enum mt753x_id id; -@@ -474,6 +691,7 @@ struct mt753x_info { - int (*phy_read)(struct dsa_switch *ds, int port, int regnum); - int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); - int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); -+ int (*cpu_port_config)(struct dsa_switch *ds, int port); - bool (*phy_mode_supported)(struct dsa_switch *ds, int port, - const struct phylink_link_state *state); - void (*mac_port_validate)(struct dsa_switch *ds, int port, -@@ -483,6 +701,10 @@ struct mt753x_info { - int (*mac_port_config)(struct dsa_switch *ds, int port, - unsigned int mode, - phy_interface_t interface); -+ void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port); -+ void (*mac_pcs_link_up)(struct dsa_switch *ds, int port, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex); - }; - - /* struct mt7530_priv - This is the main data structure for holding the state diff --git a/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch b/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch deleted file mode 100644 index 8c3fe52089..0000000000 --- a/target/linux/mediatek/patches-5.4/0605-arm64-dts-mt7622-add-mt7531-dsa-to-bananapi-bpi-r64-board.patch +++ /dev/null @@ -1,71 +0,0 @@ -From: Landen Chao <landen.chao@mediatek.com> -Subject: [PATCH net-next 6/6] arm64: dts: mt7622: add mt7531 dsa to - bananapi-bpi-r64 board -Date: Tue, 10 Dec 2019 16:14:42 +0800 - -Add mt7531 dsa to bananapi-bpi-r64 board for 5 giga Ethernet ports support. - -Signed-off-by: Landen Chao <landen.chao@mediatek.com> ---- - .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 50 +++++++++++++++++++ - 1 file changed, 50 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -150,6 +150,56 @@ - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; -+ -+ switch@0 { -+ compatible = "mediatek,mt7531"; -+ reg = <0>; -+ reset-gpios = <&pio 54 0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "wan"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan0"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan1"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan2"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "lan3"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ }; -+ }; -+ - }; - }; - diff --git a/target/linux/mediatek/patches-5.4/0900-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-5.4/0900-bt-mtk-serial-fix.patch deleted file mode 100644 index 872b2bad45..0000000000 --- a/target/linux/mediatek/patches-5.4/0900-bt-mtk-serial-fix.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- a/drivers/tty/serial/8250/8250.h -+++ b/drivers/tty/serial/8250/8250.h -@@ -82,6 +82,7 @@ struct serial8250_config { - #define UART_CAP_MINI (1 << 17) /* Mini UART on BCM283X family lacks: - * STOP PARITY EPAR SPAR WLEN5 WLEN6 - */ -+#define UART_CAP_NMOD (1 << 18) /* UART doesn't do termios */ - - #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ - #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -290,7 +290,7 @@ static const struct serial8250_config ua - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, -- .flags = UART_CAP_FIFO, -+ .flags = UART_CAP_FIFO | UART_CAP_NMOD, - }, - [PORT_NPCM] = { - .name = "Nuvoton 16550", -@@ -2597,6 +2597,11 @@ serial8250_do_set_termios(struct uart_po - unsigned long flags; - unsigned int baud, quot, frac = 0; - -+ if (up->capabilities & UART_CAP_NMOD) { -+ termios->c_cflag = 0; -+ return; -+ } -+ - if (up->capabilities & UART_CAP_MINI) { - termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); - if ((termios->c_cflag & CSIZE) == CS5 || diff --git a/target/linux/mediatek/patches-5.4/0990-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-5.4/0990-gsw-rtl8367s-mt7622-support.patch deleted file mode 100644 index a3d49e903e..0000000000 --- a/target/linux/mediatek/patches-5.4/0990-gsw-rtl8367s-mt7622-support.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -42,6 +42,12 @@ config MDIO_BCM_IPROC - This module provides a driver for the MDIO busses found in the - Broadcom iProc SoC's. - -+config RTL8367S_GSW -+ tristate "rtl8367 Gigabit Switch support for mt7622" -+ depends on NET_VENDOR_MEDIATEK -+ help -+ This driver supports rtl8367s in mt7622 -+ - config MDIO_BCM_UNIMAC - tristate "Broadcom UniMAC MDIO bus controller" - depends on HAS_IOMEM ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -110,4 +110,5 @@ obj-$(CONFIG_TERANETICS_PHY) += teraneti - obj-$(CONFIG_VITESSE_PHY) += vitesse.o - obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o - obj-$(CONFIG_MT753X_GSW) += mtk/mt753x/ -+obj-$(CONFIG_RTL8367S_GSW) += rtk/ - diff --git a/target/linux/mediatek/patches-5.4/0991-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch b/target/linux/mediatek/patches-5.4/0991-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch deleted file mode 100644 index 02e4c130ea..0000000000 --- a/target/linux/mediatek/patches-5.4/0991-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch +++ /dev/null @@ -1,415 +0,0 @@ -From patchwork Thu May 28 06:16:45 2020 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com> -X-Patchwork-Id: 11574793 -Return-Path: - <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org> -Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org - [172.30.200.123]) - by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 391201392 - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:20:27 +0000 (UTC) -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by mail.kernel.org (Postfix) with ESMTPS id 104F620657 - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:20:27 +0000 (UTC) -Authentication-Results: mail.kernel.org; - dkim=pass (2048-bit key) header.d=lists.infradead.org - header.i=@lists.infradead.org header.b="raZHaWxs"; - dkim=fail reason="signature verification failed" (1024-bit key) - header.d=mediatek.com header.i=@mediatek.com header.b="YztrByG/" -DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 104F620657 -Authentication-Results: mail.kernel.org; - dmarc=fail (p=none dis=none) header.from=mediatek.com -Authentication-Results: mail.kernel.org; - spf=none - smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20170209; h=Sender: - Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=aVtKU+Ey8KEM97+S66fz9ZMo+H8BP570jhAAvaRsNWc=; b=raZHaWxsfCxsrd - Byn/w1oLN/J82ApnNdBBXixq9Qj0uXIU2tBVqkiQ9lG6QDk7uguxQSJLeTqrsI/uxQmCI/PGQtZdP - sH0oboi2sbQSqJ/1ud4uL2pPaiLRJCxINF5oWjoZMsjn/b2fWvn52P6vTr/dxDTaabiVhY0HL0J+X - 7YGc1aYtO76HZHE2ke3puR42QkI8hE9E2cEhiLWeuUiLdUBegNM5MdYftu4nJTcCXnAeJjp/wIpYG - 7X737N9cmanDf6Bxr2bNPgaYzH+m7JK6eGxuAvWo0+PE9OX7MLrXY3KjixcjD/b0he0mfEM++gBAq - KBYKl5wh1mnlR2WIWXew==; -Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeBtx-0005JC-DJ; Thu, 28 May 2020 06:20:25 +0000 -Received: from mailgw01.mediatek.com ([216.200.240.184]) - by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeBtW-0002f2-75; Thu, 28 May 2020 06:20:01 +0000 -X-UUID: d5cb6d96c2a5421796c2f8a284ff3670-20200527 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; - s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=EqjC+5cHgv6eykN7FPf2mtwK9UivJ3XSCE0jEvb8h+8=; - b=YztrByG/Ia304l9KDPBwoHFYkFCN6qBXPqwZgg56CA9VitadAg2+K1VgfEU+oHqsqcsGAMdZTRMQh17tpm4bJParw6MMzAQ28te2TcxvQMV8PZMkerJdZyyYblI7ybauPWuofAQgQMtuwSKVii8eTRJbf99OZ9vDGJP3zo2j1wU=; -X-UUID: d5cb6d96c2a5421796c2f8a284ff3670-20200527 -Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by - mailgw01.mediatek.com - (envelope-from <chuanjia.liu@mediatek.com>) - (musrelay.mediatek.com ESMTP with TLS) - with ESMTP id 681958707; Wed, 27 May 2020 22:20:16 -0800 -Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by - MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Wed, 27 May 2020 23:18:52 -0700 -Received: from mtkcas07.mediatek.inc (172.21.101.84) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Thu, 28 May 2020 14:18:49 +0800 -Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend - Transport; Thu, 28 May 2020 14:18:47 +0800 -From: <chuanjia.liu@mediatek.com> -To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com> -Subject: [PATCH v2 1/4] dt-bindings: PCI: Mediatek: Update PCIe binding -Date: Thu, 28 May 2020 14:16:45 +0800 -Message-ID: <20200528061648.32078-2-chuanjia.liu@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -References: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20200527_231958_261064_608CC03E -X-CRM114-Status: GOOD ( 13.95 ) -X-Spam-Score: -0.2 (/) -X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: - Content analysis details: (-0.2 points) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64 - encoding - -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from - author's domain - 0.1 DKIM_SIGNED Message has a DKIM or DK signature, - not necessarily - valid - -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature - -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from - envelope-from domain - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.29 -Precedence: list -List-Id: <linux-mediatek.lists.infradead.org> -List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe> -List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/> -List-Post: <mailto:linux-mediatek@lists.infradead.org> -List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help> -List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe> -Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com, - srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>, - linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, - jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org, - yong.wu@mediatek.com, bhelgaas@google.com, - linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk -Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org> -Errors-To: - linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org - -From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com> - -There are two independent PCIe controllers in MT2712/MT7622 platform, -and each of them should contain an independent MSI domain. - -In current architecture, MSI domain will be inherited from the root -bridge, and all of the devices will share the same MSI domain. -Hence that, the PCIe devices will not work properly if the irq number -which required is more than 32. - -Split the PCIe node for MT2712/MT7622 platform to fix MSI issue and -comply with the hardware design. - -Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com> ---- - .../bindings/pci/mediatek-pcie-cfg.yaml | 38 +++++ - .../devicetree/bindings/pci/mediatek-pcie.txt | 144 +++++++++++------- - 2 files changed, 129 insertions(+), 53 deletions(-) - create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie-cfg.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-cfg.yaml -@@ -0,0 +1,38 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/pci/mediatek-pcie-cfg.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Mediatek PCIECFG controller -+ -+maintainers: -+ - Chuanjia Liu <chuanjia.liu@mediatek.com> -+ - Jianjun Wang <jianjun.wang@mediatek.com> -+ -+description: | -+ The MediaTek PCIECFG controller controls some feature about -+ LTSSM, ASPM and so on. -+ -+properties: -+ compatible: -+ items: -+ - enum: -+ - mediatek,mt7622-pciecfg -+ - mediatek,mt7629-pciecfg -+ - const: syscon -+ -+ reg: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ -+examples: -+ - | -+ pciecfg: pciecfg@1a140000 { -+ compatible = "mediatek,mt7622-pciecfg", "syscon"; -+ reg = <0 0x1a140000 0 0x1000>; -+ }; -+... ---- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt -+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt -@@ -8,7 +8,7 @@ Required properties: - "mediatek,mt7623-pcie" - "mediatek,mt7629-pcie" - - device_type: Must be "pci" --- reg: Base addresses and lengths of the PCIe subsys and root ports. -+- reg: Base addresses and lengths of the root ports. - - reg-names: Names of the above areas to use during resource lookup. - - #address-cells: Address representation for root ports (must be 3) - - #size-cells: Size representation for root ports (must be 2) -@@ -19,10 +19,10 @@ Required properties: - - sys_ckN :transaction layer and data link layer clock - Required entries for MT2701/MT7623: - - free_ck :for reference clock of PCIe subsys -- Required entries for MT2712/MT7622: -+ Required entries for MT2712/MT7622/MT7629: - - ahb_ckN :AHB slave interface operating clock for CSR access and RC - initiated MMIO access -- Required entries for MT7622: -+ Required entries for MT7622/MT7629: - - axi_ckN :application layer MMIO channel operating clock - - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when - pcie_mac_ck/pcie_pipe_ck is turned off -@@ -47,10 +47,13 @@ Required properties for MT7623/MT2701: - - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the - number of root ports. - --Required properties for MT2712/MT7622: -+Required properties for MT2712/MT7622/MT7629: - -interrupts: A list of interrupt outputs of the controller, must have one - entry for each PCIe port - -+Required properties for MT7622/MT7629: -+- mediatek,pcie-subsys: Should be a phandle of the pciecfg node. -+ - In addition, the device tree node must have sub-nodes describing each - PCIe port interface, having the following mandatory properties: - -@@ -143,56 +146,73 @@ Examples for MT7623: - - Examples for MT2712: - -- pcie: pcie@11700000 { -+ pcie1: pcie@112ff000 { - compatible = "mediatek,mt2712-pcie"; - device_type = "pci"; -- reg = <0 0x11700000 0 0x1000>, -- <0 0x112ff000 0 0x1000>; -- reg-names = "port0", "port1"; -+ reg = <0 0x112ff000 0 0x1000>; -+ reg-names = "port1"; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, -- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; -- clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, -- <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, -- <&pericfg CLK_PERI_PCIE0>, -+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "pcie_irq"; -+ clocks = <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, - <&pericfg CLK_PERI_PCIE1>; -- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1"; -- phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>; -- phy-names = "pcie-phy0", "pcie-phy1"; -+ clock-names = "sys_ck1", "ahb_ck1"; -+ phys = <&u3port1 PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy1"; - bus-range = <0x00 0xff>; -- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ ranges = <0x82000000 0 0x11400000 0x0 0x11400000 0 0x300000>; -+ status = "disabled"; - -- pcie0: pcie@0,0 { -- reg = <0x0000 0 0 0 0>; -+ slot1: pcie@1,0 { -+ reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc0 0>, -- <0 0 0 2 &pcie_intc0 1>, -- <0 0 0 3 &pcie_intc0 2>, -- <0 0 0 4 &pcie_intc0 3>; -- pcie_intc0: interrupt-controller { -+ interrupt-map = <0 0 0 1 &pcie_intc1 0>, -+ <0 0 0 2 &pcie_intc1 1>, -+ <0 0 0 3 &pcie_intc1 2>, -+ <0 0 0 4 &pcie_intc1 3>; -+ pcie_intc1: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - }; -+ }; - -- pcie1: pcie@1,0 { -- reg = <0x0800 0 0 0 0>; -+ pcie0: pcie@11700000 { -+ compatible = "mediatek,mt2712-pcie"; -+ device_type = "pci"; -+ reg = <0 0x11700000 0 0x1000>; -+ reg-names = "port0"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "pcie_irq"; -+ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, -+ <&pericfg CLK_PERI_PCIE0>; -+ clock-names = "sys_ck0", "ahb_ck0"; -+ phys = <&u3port0 PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy0"; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ status = "disabled"; -+ -+ slot0: pcie@0,0 { -+ reg = <0x0000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc1 0>, -- <0 0 0 2 &pcie_intc1 1>, -- <0 0 0 3 &pcie_intc1 2>, -- <0 0 0 4 &pcie_intc1 3>; -- pcie_intc1: interrupt-controller { -+ interrupt-map = <0 0 0 1 &pcie_intc0 0>, -+ <0 0 0 2 &pcie_intc0 1>, -+ <0 0 0 3 &pcie_intc0 2>, -+ <0 0 0 4 &pcie_intc0 3>; -+ pcie_intc0: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; -@@ -202,39 +222,31 @@ Examples for MT2712: - - Examples for MT7622: - -- pcie: pcie@1a140000 { -+ pcie0: pcie@1a143000 { - compatible = "mediatek,mt7622-pcie"; - device_type = "pci"; -- reg = <0 0x1a140000 0 0x1000>, -- <0 0x1a143000 0 0x1000>, -- <0 0x1a145000 0 0x1000>; -- reg-names = "subsys", "port0", "port1"; -+ reg = <0 0x1a143000 0 0x1000>; -+ reg-names = "port0"; -+ mediatek,pcie-cfg = <&pciecfg>; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>, -- <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "pcie_irq"; - clocks = <&pciesys CLK_PCIE_P0_MAC_EN>, -- <&pciesys CLK_PCIE_P1_MAC_EN>, - <&pciesys CLK_PCIE_P0_AHB_EN>, -- <&pciesys CLK_PCIE_P1_AHB_EN>, - <&pciesys CLK_PCIE_P0_AUX_EN>, -- <&pciesys CLK_PCIE_P1_AUX_EN>, - <&pciesys CLK_PCIE_P0_AXI_EN>, -- <&pciesys CLK_PCIE_P1_AXI_EN>, - <&pciesys CLK_PCIE_P0_OBFF_EN>, -- <&pciesys CLK_PCIE_P1_OBFF_EN>, -- <&pciesys CLK_PCIE_P0_PIPE_EN>, -- <&pciesys CLK_PCIE_P1_PIPE_EN>; -- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1", -- "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1", -- "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1"; -- phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>; -- phy-names = "pcie-phy0", "pcie-phy1"; -+ <&pciesys CLK_PCIE_P0_PIPE_EN>; -+ clock-names = "sys_ck0", "ahb_ck0", "aux_ck0", -+ "axi_ck0", "obff_ck0", "pipe_ck0"; -+ - power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; - bus-range = <0x00 0xff>; -- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ ranges = <0x82000000 0 0x20000000 0 0x20000000 0 0x8000000>; -+ status = "disabled"; - -- pcie0: pcie@0,0 { -+ slot0: pcie@0,0 { - reg = <0x0000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; -@@ -251,8 +263,34 @@ Examples for MT7622: - #interrupt-cells = <1>; - }; - }; -+ }; -+ -+ pcie1: pcie@1a145000 { -+ compatible = "mediatek,mt7622-pcie"; -+ device_type = "pci"; -+ reg = <0 0x1a145000 0 0x1000>; -+ reg-names = "port1"; -+ mediatek,pcie-cfg = <&pciecfg>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "pcie_irq"; -+ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, -+ /* designer has connect RC1 with p0_ahb clock */ -+ <&pciesys CLK_PCIE_P0_AHB_EN>, -+ <&pciesys CLK_PCIE_P1_AUX_EN>, -+ <&pciesys CLK_PCIE_P1_AXI_EN>, -+ <&pciesys CLK_PCIE_P1_OBFF_EN>, -+ <&pciesys CLK_PCIE_P1_PIPE_EN>; -+ clock-names = "sys_ck1", "ahb_ck1", "aux_ck1", -+ "axi_ck1", "obff_ck1", "pipe_ck1"; -+ -+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0 0x28000000 0 0x28000000 0 0x8000000>; -+ status = "disabled"; - -- pcie1: pcie@1,0 { -+ slot1: pcie@1,0 { - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; diff --git a/target/linux/mediatek/patches-5.4/0992-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch b/target/linux/mediatek/patches-5.4/0992-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch deleted file mode 100644 index 3e4d44f59e..0000000000 --- a/target/linux/mediatek/patches-5.4/0992-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch +++ /dev/null @@ -1,217 +0,0 @@ -From patchwork Thu May 28 06:16:46 2020 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com> -X-Patchwork-Id: 11574781 -Return-Path: - <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org> -Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org - [172.30.200.123]) - by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0A99B60D - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:19:04 +0000 (UTC) -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by mail.kernel.org (Postfix) with ESMTPS id DCC99208FE - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:19:03 +0000 (UTC) -Authentication-Results: mail.kernel.org; - dkim=pass (2048-bit key) header.d=lists.infradead.org - header.i=@lists.infradead.org header.b="SpOi0ueF"; - dkim=fail reason="signature verification failed" (1024-bit key) - header.d=mediatek.com header.i=@mediatek.com header.b="UGIBoIEG" -DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DCC99208FE -Authentication-Results: mail.kernel.org; - dmarc=fail (p=none dis=none) header.from=mediatek.com -Authentication-Results: mail.kernel.org; - spf=none - smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20170209; h=Sender: - Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=LIr5poLUT/UdH6/akh/pnICGGa3rUBkN+4FhE1DyOrU=; b=SpOi0ueFcoJ/ka - 4esa6cDd5oU4fp0z684ZVPaVvvhm/azSZBBMYinHaAW6EvzKcMNYIX9grP8eg/728lEPNTKVq0I8H - PQZ9KvD4uTu8Opo1hD8LsRSLr+YLpNKt3KPOY/4gpwQ97uU9rI5PwkuAxPBgR949Vh5EiG0Vaww1H - Ep+I5BFRn2LVVQZP1Z7U0A0VUcOTLJ4znoWRLEXxtM9/Wd4hwQsrEPQszeDFti/RbwGfJ5efOb5UL - fhwBzSxELEzAAgH7env/XD2sSSpVf2Qsn6WO8D3ZepMtWrRtARiaRKSNxSBQTg2SSHcjmBSJSzcX+ - w8wqWaUMs0crlBuZWS1g==; -Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeBsc-0001tI-88; Thu, 28 May 2020 06:19:02 +0000 -Received: from mailgw01.mediatek.com ([216.200.240.184]) - by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeBsZ-0001rp-6g; Thu, 28 May 2020 06:19:01 +0000 -X-UUID: beeaf5765357439c91eab1f67ca7ef43-20200527 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; - s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=+IjWjsF/DhknqZB+lLSZ50cyvxDap+8w4tvqhp8Dv68=; - b=UGIBoIEGJUuq5pEvYEad1HVGpiv6yma+94hva83D2gD8lYmihRWkpJxB2yn+dVtNm7ZXXoQBf+jvvULOmslJgs1HZTLJTnjpdvLmQqo42OXRXSVpTE49HdRkJZDAIWIAReBfOEkFgNxcIX3uedrtnww/NLJ2lagrYPG5ET4lI2E=; -X-UUID: beeaf5765357439c91eab1f67ca7ef43-20200527 -Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com - (envelope-from <chuanjia.liu@mediatek.com>) - (musrelay.mediatek.com ESMTP with TLS) - with ESMTP id 603406343; Wed, 27 May 2020 22:19:17 -0800 -Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by - MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Wed, 27 May 2020 23:18:47 -0700 -Received: from mtkcas07.mediatek.inc (172.21.101.84) by - mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Thu, 28 May 2020 14:18:51 +0800 -Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend - Transport; Thu, 28 May 2020 14:18:49 +0800 -From: <chuanjia.liu@mediatek.com> -To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com> -Subject: [PATCH v2 2/4] PCI: mediatek: Use regmap to get shared pcie-cfg base -Date: Thu, 28 May 2020 14:16:46 +0800 -Message-ID: <20200528061648.32078-3-chuanjia.liu@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -References: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20200527_231859_251275_BED2B1E2 -X-CRM114-Status: GOOD ( 11.62 ) -X-Spam-Score: -0.2 (/) -X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: - Content analysis details: (-0.2 points) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64 - encoding - -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from - author's domain - 0.1 DKIM_SIGNED Message has a DKIM or DK signature, - not necessarily - valid - -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature - -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from - envelope-from domain - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.29 -Precedence: list -List-Id: <linux-mediatek.lists.infradead.org> -List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe> -List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/> -List-Post: <mailto:linux-mediatek@lists.infradead.org> -List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help> -List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe> -Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com, - srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>, - linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, - jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org, - yong.wu@mediatek.com, bhelgaas@google.com, - linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk -Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org> -Errors-To: - linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org - -From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com> - -Use regmap to get shared pcie-cfg base and change -the method to get pcie irq. - -Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com> ---- - drivers/pci/controller/pcie-mediatek.c | 25 ++++++++++++++++++------- - 1 file changed, 18 insertions(+), 7 deletions(-) - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -14,6 +14,7 @@ - #include <linux/irqchip/chained_irq.h> - #include <linux/irqdomain.h> - #include <linux/kernel.h> -+#include <linux/mfd/syscon.h> - #include <linux/msi.h> - #include <linux/module.h> - #include <linux/of_address.h> -@@ -23,6 +24,7 @@ - #include <linux/phy/phy.h> - #include <linux/platform_device.h> - #include <linux/pm_runtime.h> -+#include <linux/regmap.h> - #include <linux/reset.h> - - #include "../pci.h" -@@ -205,6 +207,7 @@ struct mtk_pcie_port { - * struct mtk_pcie - PCIe host information - * @dev: pointer to PCIe device - * @base: IO mapped register base -+ * @cfg: IO mapped register map for PCIe config - * @free_ck: free-run reference clock - * @mem: non-prefetchable memory resource - * @ports: pointer to PCIe port information -@@ -214,6 +217,7 @@ struct mtk_pcie_port { - struct mtk_pcie { - struct device *dev; - void __iomem *base; -+ struct regmap *cfg; - struct clk *free_ck; - - struct resource mem; -@@ -651,7 +655,7 @@ static int mtk_pcie_setup_irq(struct mtk - return err; - } - -- port->irq = platform_get_irq(pdev, port->slot); -+ port->irq = platform_get_irq_byname(pdev, "pcie_irq"); - irq_set_chained_handler_and_data(port->irq, - mtk_pcie_intr_handler, port); - -@@ -666,12 +670,11 @@ static int mtk_pcie_startup_port_v2(stru - u32 val; - int err; - -- /* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */ -- if (pcie->base) { -- val = readl(pcie->base + PCIE_SYS_CFG_V2); -- val |= PCIE_CSR_LTSSM_EN(port->slot) | -- PCIE_CSR_ASPM_L1_EN(port->slot); -- writel(val, pcie->base + PCIE_SYS_CFG_V2); -+ /* MT7622/MT7629 platforms need to enable LTSSM and ASPM. */ -+ if (pcie->cfg) { -+ val = PCIE_CSR_LTSSM_EN(port->slot) | -+ PCIE_CSR_ASPM_L1_EN(port->slot); -+ regmap_update_bits(pcie->cfg, PCIE_SYS_CFG_V2, val, val); - } - - /* Assert all reset signals */ -@@ -977,6 +980,7 @@ static int mtk_pcie_subsys_powerup(struc - struct device *dev = pcie->dev; - struct platform_device *pdev = to_platform_device(dev); - struct resource *regs; -+ struct device_node *cfg_node; - int err; - - /* get shared registers, which are optional */ -@@ -989,6 +993,13 @@ static int mtk_pcie_subsys_powerup(struc - } - } - -+ cfg_node = of_parse_phandle(dev->of_node, "mediatek,pcie-cfg", 0); -+ if (cfg_node) { -+ pcie->cfg = syscon_node_to_regmap(cfg_node); -+ if (IS_ERR(pcie->cfg)) -+ return PTR_ERR(pcie->cfg); -+ } -+ - pcie->free_ck = devm_clk_get(dev, "free_ck"); - if (IS_ERR(pcie->free_ck)) { - if (PTR_ERR(pcie->free_ck) == -EPROBE_DEFER) diff --git a/target/linux/mediatek/patches-5.4/0993-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch b/target/linux/mediatek/patches-5.4/0993-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch deleted file mode 100644 index 3c5558b606..0000000000 --- a/target/linux/mediatek/patches-5.4/0993-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch +++ /dev/null @@ -1,417 +0,0 @@ -From patchwork Thu May 28 06:16:47 2020 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com> -X-Patchwork-Id: 11574785 -Return-Path: - <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org> -Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org - [172.30.200.123]) - by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 933301391 - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:19:16 +0000 (UTC) -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by mail.kernel.org (Postfix) with ESMTPS id D19F02078C - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:19:15 +0000 (UTC) -Authentication-Results: mail.kernel.org; - dkim=pass (2048-bit key) header.d=lists.infradead.org - header.i=@lists.infradead.org header.b="s8K7t7DF"; - dkim=fail reason="signature verification failed" (1024-bit key) - header.d=mediatek.com header.i=@mediatek.com header.b="RhX81Iqp" -DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D19F02078C -Authentication-Results: mail.kernel.org; - dmarc=fail (p=none dis=none) header.from=mediatek.com -Authentication-Results: mail.kernel.org; - spf=none - smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20170209; h=Sender: - Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=NHyHqNMcE7LW10MwduOJoKiWe8cv+XayY+L6WDZeSu0=; b=s8K7t7DFh1iQ5w - eGvuMRgXEQv/YWRuSZRyX8lx8R2H9IuawEIgkhO6lEo6xv0VdsRuj8SptfoWg5afCItMhih373M21 - 6sUy3tEiuKGgklfxLU0reLEkaATkKRGLJDY3eSSs1mvZDrydKuZLDTka+YDGaiESlOhqMr95Nm6YM - yK8O00qTwSRPJUILRsBv1e/Kz8NRCmYhs56snABJkKeJ51NRAkb20R6qGTEd6UyBlz3jTVYwluLgF - bdqzywDT6+BNg/Agh6Zd+v2PpO4cmwCpGm62+3UUyZkfi/aQ4qZ/AFAfSQI+3ZBAgsKMC1PGifOi/ - FgGxIvAUk6atBy7DAHuw==; -Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeBsn-00025C-EF; Thu, 28 May 2020 06:19:13 +0000 -Received: from mailgw01.mediatek.com ([216.200.240.184]) - by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeBsZ-0001s4-6j; Thu, 28 May 2020 06:19:01 +0000 -X-UUID: c6210e6371fa445db0ae40a8b8a7a0a1-20200527 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; - s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=X9AwTdbhpWmlWY4LjTm8KLq4Cca3YI9UnyCX3O0BAak=; - b=RhX81Iqp0mWhBDyMQMFSEtt23+DGAWoin1SrFGP1bzp6GEtu38b2pK5RJVBshJtuxi/a1uMXZjeDsHJn02VGdNA07FrzZ7jq6YYEL+8cJs2DnhySmNElZazXPv2vKu9TWygfilTT24h/u8V/eszuRuhkdoUKWol8LwDlPl9gskg=; -X-UUID: c6210e6371fa445db0ae40a8b8a7a0a1-20200527 -Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com - (envelope-from <chuanjia.liu@mediatek.com>) - (musrelay.mediatek.com ESMTP with TLS) - with ESMTP id 7561992; Wed, 27 May 2020 22:19:17 -0800 -Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by - MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Wed, 27 May 2020 23:18:47 -0700 -Received: from mtkcas07.mediatek.inc (172.21.101.84) by - mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Thu, 28 May 2020 14:18:52 +0800 -Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend - Transport; Thu, 28 May 2020 14:18:51 +0800 -From: <chuanjia.liu@mediatek.com> -To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com> -Subject: [PATCH v2 3/4] arm64: dts: mediatek: Split PCIe node for - MT2712/MT7622 -Date: Thu, 28 May 2020 14:16:47 +0800 -Message-ID: <20200528061648.32078-4-chuanjia.liu@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -References: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20200527_231859_253529_B6751C5A -X-CRM114-Status: GOOD ( 12.20 ) -X-Spam-Score: -0.2 (/) -X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: - Content analysis details: (-0.2 points) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64 - encoding - -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from - author's domain - 0.1 DKIM_SIGNED Message has a DKIM or DK signature, - not necessarily - valid - -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature - -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from - envelope-from domain - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.29 -Precedence: list -List-Id: <linux-mediatek.lists.infradead.org> -List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe> -List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/> -List-Post: <mailto:linux-mediatek@lists.infradead.org> -List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help> -List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe> -Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com, - srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>, - linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, - jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org, - yong.wu@mediatek.com, bhelgaas@google.com, - linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk -Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org> -Errors-To: - linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org - -From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com> - -There are two independent PCIe controllers in MT2712/MT7622 platform, -and each of them should contain an independent MSI domain. - -In current architecture, MSI domain will be inherited from the root -bridge, and all of the devices will share the same MSI domain. -Hence that, the PCIe devices will not work properly if the irq number -which required is more than 32. - -Split the PCIe node for MT2712/MT7622 platform to fix MSI issue and -comply with the hardware design. - -Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com> ---- - arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 75 +++++++++++-------- - .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 16 ++-- - arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 6 +- - arch/arm64/boot/dts/mediatek/mt7622.dtsi | 68 +++++++++++------ - 4 files changed, 96 insertions(+), 69 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi -@@ -791,60 +791,73 @@ - }; - }; - -- pcie: pcie@11700000 { -+ pcie1: pcie@112ff000 { - compatible = "mediatek,mt2712-pcie"; - device_type = "pci"; -- reg = <0 0x11700000 0 0x1000>, -- <0 0x112ff000 0 0x1000>; -- reg-names = "port0", "port1"; -+ reg = <0 0x112ff000 0 0x1000>; -+ reg-names = "port1"; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, -- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; -- clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, -- <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, -- <&pericfg CLK_PERI_PCIE0>, -+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "pcie_irq"; -+ clocks = <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, - <&pericfg CLK_PERI_PCIE1>; -- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1"; -- phys = <&u3port0 PHY_TYPE_PCIE>, <&u3port1 PHY_TYPE_PCIE>; -- phy-names = "pcie-phy0", "pcie-phy1"; -+ clock-names = "sys_ck1", "ahb_ck1"; -+ phys = <&u3port1 PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy1"; - bus-range = <0x00 0xff>; -- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ ranges = <0x82000000 0 0x11400000 0x0 0x11400000 0 0x300000>; -+ status = "disabled"; - -- pcie0: pcie@0,0 { -- device_type = "pci"; -- status = "disabled"; -- reg = <0x0000 0 0 0 0>; -+ slot1: pcie@1,0 { -+ reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc0 0>, -- <0 0 0 2 &pcie_intc0 1>, -- <0 0 0 3 &pcie_intc0 2>, -- <0 0 0 4 &pcie_intc0 3>; -- pcie_intc0: interrupt-controller { -+ interrupt-map = <0 0 0 1 &pcie_intc1 0>, -+ <0 0 0 2 &pcie_intc1 1>, -+ <0 0 0 3 &pcie_intc1 2>, -+ <0 0 0 4 &pcie_intc1 3>; -+ pcie_intc1: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - }; -+ }; - -- pcie1: pcie@1,0 { -- device_type = "pci"; -- status = "disabled"; -- reg = <0x0800 0 0 0 0>; -+ pcie0: pcie@11700000 { -+ compatible = "mediatek,mt2712-pcie"; -+ device_type = "pci"; -+ reg = <0 0x11700000 0 0x1000>; -+ reg-names = "port0"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "pcie_irq"; -+ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, -+ <&pericfg CLK_PERI_PCIE0>; -+ clock-names = "sys_ck0", "ahb_ck0"; -+ phys = <&u3port0 PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy0"; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ status = "disabled"; -+ -+ slot0: pcie@0,0 { -+ reg = <0x0000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc1 0>, -- <0 0 0 2 &pcie_intc1 1>, -- <0 0 0 3 &pcie_intc1 2>, -- <0 0 0 4 &pcie_intc1 3>; -- pcie_intc1: interrupt-controller { -+ interrupt-map = <0 0 0 1 &pcie_intc0 0>, -+ <0 0 0 2 &pcie_intc0 1>, -+ <0 0 0 3 &pcie_intc0 2>, -+ <0 0 0 4 &pcie_intc0 3>; -+ pcie_intc0: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -294,18 +294,16 @@ - }; - }; - --&pcie { -+&pcie0 { - pinctrl-names = "default"; -- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; -+ pinctrl-0 = <&pcie0_pins>; - status = "okay"; -+}; - -- pcie@0,0 { -- status = "okay"; -- }; -- -- pcie@1,0 { -- status = "okay"; -- }; -+&pcie1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie1_pins>; -+ status = "okay"; - }; - - &pio { ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -794,45 +794,41 @@ - #reset-cells = <1>; - }; - -- pcie: pcie@1a140000 { -+ pciecfg: pciecfg@1a140000 { -+ compatible = "mediatek,mt7622-pciecfg", "syscon"; -+ reg = <0 0x1a140000 0 0x1000>; -+ }; -+ -+ pcie0: pcie@1a143000 { - compatible = "mediatek,mt7622-pcie"; - device_type = "pci"; -- reg = <0 0x1a140000 0 0x1000>, -- <0 0x1a143000 0 0x1000>, -- <0 0x1a145000 0 0x1000>; -- reg-names = "subsys", "port0", "port1"; -+ reg = <0 0x1a143000 0 0x1000>; -+ reg-names = "port0"; -+ mediatek,pcie-cfg = <&pciecfg>; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>, -- <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "pcie_irq"; - clocks = <&pciesys CLK_PCIE_P0_MAC_EN>, -- <&pciesys CLK_PCIE_P1_MAC_EN>, -- <&pciesys CLK_PCIE_P0_AHB_EN>, - <&pciesys CLK_PCIE_P0_AHB_EN>, - <&pciesys CLK_PCIE_P0_AUX_EN>, -- <&pciesys CLK_PCIE_P1_AUX_EN>, - <&pciesys CLK_PCIE_P0_AXI_EN>, -- <&pciesys CLK_PCIE_P1_AXI_EN>, - <&pciesys CLK_PCIE_P0_OBFF_EN>, -- <&pciesys CLK_PCIE_P1_OBFF_EN>, -- <&pciesys CLK_PCIE_P0_PIPE_EN>, -- <&pciesys CLK_PCIE_P1_PIPE_EN>; -- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1", -- "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1", -- "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1"; -+ <&pciesys CLK_PCIE_P0_PIPE_EN>; -+ clock-names = "sys_ck0", "ahb_ck0", "aux_ck0", -+ "axi_ck0", "obff_ck0", "pipe_ck0"; -+ - power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; - bus-range = <0x00 0xff>; -- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; - status = "disabled"; - -- pcie0: pcie@0,0 { -+ slot0: pcie@0,0 { - reg = <0x0000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; -- status = "disabled"; -- - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc0 0>, - <0 0 0 2 &pcie_intc0 1>, -@@ -844,15 +840,39 @@ - #interrupt-cells = <1>; - }; - }; -+ }; - -- pcie1: pcie@1,0 { -+ pcie1: pcie@1a145000 { -+ compatible = "mediatek,mt7622-pcie"; -+ device_type = "pci"; -+ reg = <0 0x1a145000 0 0x1000>; -+ reg-names = "port1"; -+ mediatek,pcie-cfg = <&pciecfg>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "pcie_irq"; -+ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, -+ /* designer has connect RC1 with p0_ahb clock */ -+ <&pciesys CLK_PCIE_P0_AHB_EN>, -+ <&pciesys CLK_PCIE_P1_AUX_EN>, -+ <&pciesys CLK_PCIE_P1_AXI_EN>, -+ <&pciesys CLK_PCIE_P1_OBFF_EN>, -+ <&pciesys CLK_PCIE_P1_PIPE_EN>; -+ clock-names = "sys_ck1", "ahb_ck1", "aux_ck1", -+ "axi_ck1", "obff_ck1", "pipe_ck1"; -+ -+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; -+ status = "disabled"; -+ -+ slot1: pcie@1,0 { - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; -- status = "disabled"; -- - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc1 0>, - <0 0 0 2 &pcie_intc1 1>, ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -254,18 +254,16 @@ - }; - }; - --&pcie { -+&pcie0 { - pinctrl-names = "default"; -- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; -+ pinctrl-0 = <&pcie0_pins>; - status = "okay"; -+}; - -- pcie@0,0 { -- status = "okay"; -- }; -- -- pcie@1,0 { -- status = "okay"; -- }; -+&pcie1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie1_pins>; -+ status = "okay"; - }; - - &pio { diff --git a/target/linux/mediatek/patches-5.4/0994-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch b/target/linux/mediatek/patches-5.4/0994-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch deleted file mode 100644 index f166aa75de..0000000000 --- a/target/linux/mediatek/patches-5.4/0994-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch +++ /dev/null @@ -1,203 +0,0 @@ -From patchwork Thu May 28 06:16:48 2020 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com> -X-Patchwork-Id: 11574797 -Return-Path: - <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org> -Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org - [172.30.200.123]) - by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30A5E1392 - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:29:05 +0000 (UTC) -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by mail.kernel.org (Postfix) with ESMTPS id 08B6320721 - for <patchwork-linux-mediatek@patchwork.kernel.org>; - Thu, 28 May 2020 06:29:05 +0000 (UTC) -Authentication-Results: mail.kernel.org; - dkim=pass (2048-bit key) header.d=lists.infradead.org - header.i=@lists.infradead.org header.b="auhxDafY"; - dkim=fail reason="signature verification failed" (1024-bit key) - header.d=mediatek.com header.i=@mediatek.com header.b="Kj09Arxb" -DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 08B6320721 -Authentication-Results: mail.kernel.org; - dmarc=fail (p=none dis=none) header.from=mediatek.com -Authentication-Results: mail.kernel.org; - spf=none - smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20170209; h=Sender: - Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=+QPxF1vlOH7StIZYuXJa3V40x8QVDxCLF9AFXHblB9M=; b=auhxDafYBeaUZO - aYp2KVO8Aie0v4tYtRwBon7hF+x55JwD78SAxQR2RsSvrlOo9cMYYby+ToUWflVUWQ60FapAl+w+l - nkEjIOrLBErHwxNOcsD8T5kjyCBMqlz4OMAQYUDNJ3fSugRlGhOtxkjCGd9ebB8N2Rvu6/U8P1A9n - P15mEQoc+RLonR1+9mBgwTEXErjsraxkimTD4Txsp4IvMs3UdsMkP+r3OT5S/p+Uj6O9ES0h7xIon - aL79KaVqRLHrfZxnrVwuGiecAiTp8qLy9clHuJU32NA6ZcXH1OnWipKApgp8Ck7ys80WPKaMrat9B - XuskJ63w13DZAbCVvuGQ==; -Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeC2J-00014n-M9; Thu, 28 May 2020 06:29:03 +0000 -Received: from mailgw02.mediatek.com ([216.200.240.185]) - by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeC2H-00013t-Li; Thu, 28 May 2020 06:29:03 +0000 -X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; - s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=CIwcBFK1x0LbOjDt1BG6/knHFxDHRiqj8ov/jWEZDBY=; - b=Kj09ArxbnLVTc9bpaVPT3jQrIVjhL87sSYyVF9dFypS976k78Ce9gZd0f4K3zAZbYZHYoQtuyOQ9TOeufQfgD+Cr+j5VR7pTdO2E1iXHFs/eQAz5gAjvjlK01z1JiunrLnn9dvIr6c1gEkjQHny0VpuZ1duxx79jwYusg/Nw6Wc=; -X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527 -Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by - mailgw02.mediatek.com - (envelope-from <chuanjia.liu@mediatek.com>) - (musrelay.mediatek.com ESMTP with TLS) - with ESMTP id 899663677; Wed, 27 May 2020 22:29:21 -0800 -Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by - MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Wed, 27 May 2020 23:18:50 -0700 -Received: from mtkcas07.mediatek.inc (172.21.101.84) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Thu, 28 May 2020 14:18:54 +0800 -Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend - Transport; Thu, 28 May 2020 14:18:52 +0800 -From: <chuanjia.liu@mediatek.com> -To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com> -Subject: [PATCH v2 4/4] ARM: dts: mediatek: Update mt7629 PCIe node -Date: Thu, 28 May 2020 14:16:48 +0800 -Message-ID: <20200528061648.32078-5-chuanjia.liu@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -References: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20200527_232901_719172_E5A99C62 -X-CRM114-Status: GOOD ( 11.61 ) -X-Spam-Score: -0.2 (/) -X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: - Content analysis details: (-0.2 points) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64 - encoding - -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from - author's domain - 0.1 DKIM_SIGNED Message has a DKIM or DK signature, - not necessarily - valid - -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature - -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from - envelope-from domain - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.29 -Precedence: list -List-Id: <linux-mediatek.lists.infradead.org> -List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe> -List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/> -List-Post: <mailto:linux-mediatek@lists.infradead.org> -List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help> -List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>, - <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe> -Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com, - srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>, - linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, - jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org, - yong.wu@mediatek.com, bhelgaas@google.com, - linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk -Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org> -Errors-To: - linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org - -From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com> - -Remove unused property and add pciecfg node. - -Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com> ---- - arch/arm/boot/dts/mt7629-rfb.dts | 3 ++- - arch/arm/boot/dts/mt7629.dtsi | 23 +++++++++++++---------- - 2 files changed, 15 insertions(+), 11 deletions(-) - ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -176,9 +176,10 @@ - }; - }; - --&pcie { -+&pcie1 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; -+ status = "okay"; - }; - - &pciephy1 { ---- a/arch/arm/boot/dts/mt7629.dtsi -+++ b/arch/arm/boot/dts/mt7629.dtsi -@@ -368,16 +368,21 @@ - #reset-cells = <1>; - }; - -- pcie: pcie@1a140000 { -+ pciecfg: pciecfg@1a140000 { -+ compatible = "mediatek,mt7629-pciecfg", "syscon"; -+ reg = <0x1a140000 0x1000>; -+ }; -+ -+ pcie1: pcie@1a145000 { - compatible = "mediatek,mt7629-pcie"; - device_type = "pci"; -- reg = <0x1a140000 0x1000>, -- <0x1a145000 0x1000>; -- reg-names = "subsys","port1"; -+ reg = <0x1a145000 0x1000>; -+ reg-names = "port1"; -+ mediatek,pcie-cfg = <&pciecfg>; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_LOW>, -- <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "pcie_irq"; - clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, - <&pciesys CLK_PCIE_P0_AHB_EN>, - <&pciesys CLK_PCIE_P1_AUX_EN>, -@@ -398,21 +403,19 @@ - power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>; -+ status = "disabled"; - -- pcie1: pcie@1,0 { -- device_type = "pci"; -+ slot1: pcie@1,0 { - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; -- num-lanes = <1>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc1 0>, - <0 0 0 2 &pcie_intc1 1>, - <0 0 0 3 &pcie_intc1 2>, - <0 0 0 4 &pcie_intc1 3>; -- - pcie_intc1: interrupt-controller { - interrupt-controller; - #address-cells = <0>; diff --git a/target/linux/mediatek/patches-5.4/1003-dts-mt7622-rfb-change-to-ax-mtd-layout.patch b/target/linux/mediatek/patches-5.4/1003-dts-mt7622-rfb-change-to-ax-mtd-layout.patch deleted file mode 100644 index 74a294f098..0000000000 --- a/target/linux/mediatek/patches-5.4/1003-dts-mt7622-rfb-change-to-ax-mtd-layout.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -589,17 +589,17 @@ - - factory: partition@1c0000 { - label = "Factory"; -- reg = <0x1c0000 0x0040000>; -+ reg = <0x1c0000 0x0100000>; - }; - - partition@200000 { - label = "firmware"; -- reg = <0x200000 0x2000000>; -+ reg = <0x2c0000 0x2000000>; - }; - - partition@2200000 { - label = "User_data"; -- reg = <0x2200000 0x4000000>; -+ reg = <0x22c0000 0x4000000>; - }; - }; - }; diff --git a/target/linux/mediatek/patches-5.4/1010-pcie-mediatek-fix-clearing-interrupt-status.patch b/target/linux/mediatek/patches-5.4/1010-pcie-mediatek-fix-clearing-interrupt-status.patch deleted file mode 100644 index d3ef78dc72..0000000000 --- a/target/linux/mediatek/patches-5.4/1010-pcie-mediatek-fix-clearing-interrupt-status.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Felix Fietkau <nbd@nbd.name> -Date: Fri, 4 Sep 2020 18:33:27 +0200 -Subject: [PATCH] pcie-mediatek: fix clearing interrupt status - -Clearing the status needs to happen after running the handler, otherwise -we will get an extra spurious interrupt after the cause has been cleared - -Signed-off-by: Felix Fietkau <nbd@nbd.name> ---- - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -616,10 +616,10 @@ static void mtk_pcie_intr_handler(struct - if (status & INTX_MASK) { - for_each_set_bit_from(bit, &status, PCI_NUM_INTX + INTX_SHIFT) { - /* Clear the INTx */ -- writel(1 << bit, port->base + PCIE_INT_STATUS); - virq = irq_find_mapping(port->irq_domain, - bit - INTX_SHIFT); - generic_handle_irq(virq); -+ writel(1 << bit, port->base + PCIE_INT_STATUS); - } - } - diff --git a/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch b/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch deleted file mode 100644 index 3f7660b14b..0000000000 --- a/target/linux/mediatek/patches-5.4/1011-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch +++ /dev/null @@ -1,85 +0,0 @@ -From: Felix Fietkau <nbd@nbd.name> -Date: Fri, 4 Sep 2020 18:36:06 +0200 -Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for coherent DMA - -It improves performance by eliminating the need for a cache flush on rx and tx - -Signed-off-by: Felix Fietkau <nbd@nbd.name> ---- - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -357,7 +357,7 @@ - }; - - cci_control2: slave-if@5000 { -- compatible = "arm,cci-400-ctrl-if"; -+ compatible = "arm,cci-400-ctrl-if", "syscon"; - interface-type = "ace"; - reg = <0x5000 0x1000>; - }; -@@ -969,6 +969,8 @@ - power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys>; -+ mediatek,cci-control = <&cci_control2>; -+ dma-coherent; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -9,6 +9,7 @@ - #include <linux/of_device.h> - #include <linux/of_mdio.h> - #include <linux/of_net.h> -+#include <linux/of_address.h> - #include <linux/mfd/syscon.h> - #include <linux/regmap.h> - #include <linux/clk.h> -@@ -2506,6 +2507,13 @@ static int mtk_hw_init(struct mtk_eth *e - if (ret) - goto err_disable_pm; - -+ if (of_dma_is_coherent(eth->dev->of_node)) { -+ u32 mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | -+ ETHSYS_DMA_AG_MAP_PPE; -+ -+ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, mask, mask); -+ } -+ - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { - ret = device_reset(eth->dev); - if (ret) { -@@ -3101,6 +3109,16 @@ static int mtk_probe(struct platform_dev - } - } - -+ if (of_dma_is_coherent(pdev->dev.of_node)) { -+ struct regmap *cci; -+ -+ cci = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, -+ "mediatek,cci-control"); -+ /* enable CPU/bus coherency */ -+ if (!IS_ERR(cci)) -+ regmap_write(cci, 0, 3); -+ } -+ - if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { - eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii), - GFP_KERNEL); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -448,6 +448,12 @@ - #define RSTCTRL_FE BIT(6) - #define RSTCTRL_PPE BIT(31) - -+/* ethernet dma channel agent map */ -+#define ETHSYS_DMA_AG_MAP 0x408 -+#define ETHSYS_DMA_AG_MAP_PDMA BIT(0) -+#define ETHSYS_DMA_AG_MAP_QDMA BIT(1) -+#define ETHSYS_DMA_AG_MAP_PPE BIT(2) -+ - /* SGMII subsystem config registers */ - /* Register to auto-negotiation restart */ - #define SGMSYS_PCS_CONTROL_1 0x0 diff --git a/target/linux/mediatek/patches-5.4/1012-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-5.4/1012-pci-pcie-mediatek-add-support-for-coherent-DMA.patch deleted file mode 100644 index 20a67676e3..0000000000 --- a/target/linux/mediatek/patches-5.4/1012-pci-pcie-mediatek-add-support-for-coherent-DMA.patch +++ /dev/null @@ -1,108 +0,0 @@ -From: Felix Fietkau <nbd@nbd.name> -Date: Fri, 4 Sep 2020 18:42:42 +0200 -Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA - -It improves performance by eliminating the need for a cache flush for DMA on -attached devices - -Signed-off-by: Felix Fietkau <nbd@nbd.name> ---- - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -805,6 +805,8 @@ - reg = <0 0x1a143000 0 0x1000>; - reg-names = "port0"; - mediatek,pcie-cfg = <&pciecfg>; -+ mediatek,hifsys = <&hifsys>; -+ mediatek,cci-control = <&cci_control2>; - #address-cells = <3>; - #size-cells = <2>; - interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>; -@@ -822,6 +824,7 @@ - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; - status = "disabled"; -+ dma-coherent; - - slot0: pcie@0,0 { - reg = <0x0000 0 0 0 0>; -@@ -848,6 +851,8 @@ - reg = <0 0x1a145000 0 0x1000>; - reg-names = "port1"; - mediatek,pcie-cfg = <&pciecfg>; -+ mediatek,hifsys = <&hifsys>; -+ mediatek,cci-control = <&cci_control2>; - #address-cells = <3>; - #size-cells = <2>; - interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; -@@ -866,6 +871,7 @@ - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; - status = "disabled"; -+ dma-coherent; - - slot1: pcie@1,0 { - reg = <0x0800 0 0 0 0>; -@@ -925,6 +931,11 @@ - }; - }; - -+ hifsys: syscon@1af00000 { -+ compatible = "mediatek,mt7622-hifsys", "syscon"; -+ reg = <0 0x1af00000 0 0x70>; -+ }; -+ - ethsys: syscon@1b000000 { - compatible = "mediatek,mt7622-ethsys", - "syscon"; ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -20,6 +20,7 @@ - #include <linux/of_address.h> - #include <linux/of_pci.h> - #include <linux/of_platform.h> -+#include <linux/of_address.h> - #include <linux/pci.h> - #include <linux/phy/phy.h> - #include <linux/platform_device.h> -@@ -139,6 +140,11 @@ - #define PCIE_LINK_STATUS_V2 0x804 - #define PCIE_PORT_LINKUP_V2 BIT(10) - -+/* DMA channel mapping */ -+#define HIFSYS_DMA_AG_MAP 0x008 -+#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0) -+#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1) -+ - struct mtk_pcie_port; - - /** -@@ -1068,6 +1074,27 @@ static int mtk_pcie_setup(struct mtk_pci - } - } - -+ if (of_dma_is_coherent(node)) { -+ struct regmap *con; -+ u32 mask; -+ -+ con = syscon_regmap_lookup_by_phandle(node, -+ "mediatek,cci-control"); -+ /* enable CPU/bus coherency */ -+ if (!IS_ERR(con)) -+ regmap_write(con, 0, 3); -+ -+ con = syscon_regmap_lookup_by_phandle(node, -+ "mediatek,hifsys"); -+ if (IS_ERR(con)) { -+ dev_err(dev, "missing hifsys node\n"); -+ return PTR_ERR(con); -+ } -+ -+ mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1; -+ regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask); -+ } -+ - for_each_available_child_of_node(node, child) { - int slot; - diff --git a/target/linux/mediatek/patches-5.4/1020-spi-nor-w25q512jv.patch b/target/linux/mediatek/patches-5.4/1020-spi-nor-w25q512jv.patch deleted file mode 100644 index a234555556..0000000000 --- a/target/linux/mediatek/patches-5.4/1020-spi-nor-w25q512jv.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: David Bauer <mail@david-bauer.net> -Date: Thu, 11 Feb 2021 19:57:26 +0100 -Subject: [PATCH] mtd: spi-nor: add support for Winbond W25Q512 - -The Winbond W25Q512 is a 512mb SPI-NOR chip. It supports 4K sectors as -well as block protection and Dual-/Quad-read. - -Tested on: Ubiquiti UniFi 6 LR - -Signed-off-by: David Bauer <mail@david-bauer.net> - -Ref: https://patchwork.ozlabs.org/project/linux-mtd/patch/20210213151047.11700-1-mail@david-bauer.net/ - ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2552,6 +2552,9 @@ static const struct flash_info spi_nor_i - .fixups = &w25q256_fixups }, - { "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512, - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25q512jv", INFO(0xef4020, 0, 64 * 1024, 1024, -+ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ | -+ SPI_NOR_HAS_TB | SPI_NOR_HAS_LOCK) }, - { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, - SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, - diff --git a/target/linux/mediatek/patches-5.4/1021-ubnt-ledbar-driver.patch b/target/linux/mediatek/patches-5.4/1021-ubnt-ledbar-driver.patch deleted file mode 100644 index 41ab094e9f..0000000000 --- a/target/linux/mediatek/patches-5.4/1021-ubnt-ledbar-driver.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -824,6 +824,16 @@ config LEDS_LM36274 - Say Y to enable the LM36274 LED driver for TI LMU devices. - This supports the LED device LM36274. - -+config LEDS_UBNT_LEDBAR -+ tristate "LED support for Ubiquiti UniFi 6 LR" -+ depends on LEDS_CLASS && I2C && OF -+ help -+ This option enables support for the Ubiquiti LEDBAR -+ LED driver. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called leds-ubnt-ledbar. -+ - comment "LED Triggers" - source "drivers/leds/trigger/Kconfig" - ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -85,6 +85,7 @@ obj-$(CONFIG_LEDS_LM3601X) += leds-lm36 - obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o - obj-$(CONFIG_LEDS_LM3697) += leds-lm3697.o - obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o -+obj-$(CONFIG_LEDS_UBNT_LEDBAR) += leds-ubnt-ledbar.o - - # LED SPI Drivers - obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o diff --git a/target/linux/mediatek/patches-5.4/115-dts-bpi64-add-snand-support.patch b/target/linux/mediatek/patches-5.4/115-dts-bpi64-add-snand-support.patch deleted file mode 100644 index 4d369cefef..0000000000 --- a/target/linux/mediatek/patches-5.4/115-dts-bpi64-add-snand-support.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -108,7 +108,7 @@ - }; - - &bch { -- status = "disabled"; -+ status = "okay"; - }; - - &btif { -@@ -283,14 +283,40 @@ - status = "disabled"; - }; - --&nor_flash { -+&snfi { - pinctrl-names = "default"; -- pinctrl-0 = <&spi_nor_pins>; -- status = "disabled"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; - -- flash@0 { -- compatible = "jedec,spi-nor"; -+ snand: spi_nand@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "spi-nand"; -+ spi-max-frequency = <104000000>; - reg = <0>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "fip"; -+ reg = <0x80000 0x200000>; -+ read-only; -+ }; -+ -+ partition@280000 { -+ label = "ubi"; -+ reg = <0x280000 0x7d80000>; -+ }; -+ }; - }; - }; - |