Hi Neil, On 18/04/2024 23:47, Neil Armstrong wrote: > Add Support for the Qualcomm Generic Interface (GENI) I2C interface > found on newer Qualcomm SoCs.
\o/ > > The Generic Interface (GENI) is a firmware based Qualcomm Universal > Peripherals (QUP) Serial Engine (SE) Wrapper which can support multiple > bus protocols depending on the firmware type loaded at early boot time > based on system configuration. > > It also supports the "I2C Master Hub" which is a single function Wrapper > that only FIFO mode I2C. > > It replaces the fixed-function QUP Wrapper found on older SoCs. > > The geni-se.h containing the generic GENI Serial Engine registers defines > is imported from Linux. > > Only FIFO mode is implemented, nor SE DMA nor GPI DMA is implemented. nit: "neither SE DMA nor GPI DMA are implemented" A few minor things below, but otherwise LGTM! > > Signed-off-by: Neil Armstrong <neil.armstr...@linaro.org> > --- > drivers/i2c/Kconfig | 10 + > drivers/i2c/Makefile | 1 + > drivers/i2c/geni_i2c.c | 576 > +++++++++++++++++++++++++++++++++++++++++++++ > include/soc/qcom/geni-se.h | 265 +++++++++++++++++++++ > 4 files changed, 852 insertions(+) > [...] > diff --git a/drivers/i2c/geni_i2c.c b/drivers/i2c/geni_i2c.c > new file mode 100644 > index 00000000000..8c3ed3bef89 > --- /dev/null > +++ b/drivers/i2c/geni_i2c.c > @@ -0,0 +1,576 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. > + * Copyright (c) 2024, Linaro Limited > + * Author: Neil Armstrong <neil.armstr...@linaro.org> > + * > + * Based on Linux driver: drivers/i2c/busses/i2c-qcom-geni.c > + */ > + [...] > +static int geni_i2c_fifo_tx_fill(struct geni_i2c_priv *geni, struct i2c_msg > *msg) > +{ > + ulong start = get_timer(0); > + ulong cur_xfer = 0; > + int i; > + > + while (get_timer(start) < I2C_TIMEOUT_MS) { > + u32 status = readl(geni->base + SE_GENI_M_IRQ_STATUS); > + > + if (status & (M_CMD_ABORT_EN | > + M_CMD_OVERRUN_EN | > + M_ILLEGAL_CMD_EN | > + M_CMD_FAILURE_EN | > + M_GP_IRQ_1_EN | > + M_GP_IRQ_3_EN | > + M_GP_IRQ_4_EN)) { > + debug("%s:%d cmd err\n", __func__, __LINE__); How likely are we to hit this? Would it make sense to promote it to a pr_warn()? Please drop the __LINE__ and (if it makes sense to?) print the value of status. > + writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); > + writel(0, geni->base + SE_GENI_TX_WATERMARK_REG); > + return -EREMOTEIO; > + } > + > + if ((status & M_TX_FIFO_WATERMARK_EN) == 0) { > + udelay(1); > + goto skip_fill; > + } > + > + for (i = 0; i < geni->tx_wm; i++) { > + u32 temp, tx = 0; > + unsigned int p = 0; > + > + while (cur_xfer < msg->len && p < sizeof(tx)) { > + temp = msg->buf[cur_xfer++]; > + tx |= temp << (p * 8); > + p++; > + } > + > + writel(tx, geni->base + SE_GENI_TX_FIFOn); > + > + if (cur_xfer == msg->len) { > + writel(0, geni->base + > SE_GENI_TX_WATERMARK_REG); > + break; > + } > + } > + > +skip_fill: > + writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); > + > + if (status & M_CMD_DONE_EN) > + return 0; > + } > + > + return -ETIMEDOUT; > +} > + > +static int geni_i2c_fifo_rx_drain(struct geni_i2c_priv *geni, struct i2c_msg > *msg) > +{ > + ulong start = get_timer(0); > + ulong cur_xfer = 0; > + int i; > + > + while (get_timer(start) < I2C_TIMEOUT_MS) { > + u32 status = readl(geni->base + SE_GENI_M_IRQ_STATUS); > + u32 rxstatus = readl(geni->base + SE_GENI_RX_FIFO_STATUS); > + u32 rxcnt = rxstatus & RX_FIFO_WC_MSK; > + > + if (status & (M_CMD_ABORT_EN | > + M_CMD_FAILURE_EN | > + M_CMD_OVERRUN_EN | > + M_ILLEGAL_CMD_EN | > + M_GP_IRQ_1_EN | > + M_GP_IRQ_3_EN | > + M_GP_IRQ_4_EN)) { > + debug("%s:%d cmd err\n", __func__, __LINE__); Ditto > + writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); > + return -EIO; > + } > + > + if ((status & (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) == > 0) { > + udelay(1); > + goto skip_drain; > + } > + > + for (i = 0; cur_xfer < msg->len && i < rxcnt; i++) { > + u32 rx = readl(geni->base + SE_GENI_RX_FIFOn); > + unsigned int p = 0; > + > + while (cur_xfer < msg->len && p < sizeof(rx)) { > + msg->buf[cur_xfer++] = rx & 0xff; > + rx >>= 8; > + p++; > + } > + } > + > +skip_drain: > + writel(status, geni->base + SE_GENI_M_IRQ_CLEAR); > + > + if (status & M_CMD_DONE_EN) > + return 0; > + } > + > + return -ETIMEDOUT; > +} > + > +static int geni_i2c_xfer_tx(struct geni_i2c_priv *geni, struct i2c_msg *msg, > u32 params) > +{ > + writel(msg->len, geni->base + SE_I2C_TX_TRANS_LEN); > + geni_i2c_setup_m_cmd(geni, I2C_WRITE, params); > + writel(1, geni->base + SE_GENI_TX_WATERMARK_REG); > + > + return geni_i2c_fifo_tx_fill(geni, msg); > +} > + > +static int geni_i2c_xfer_rx(struct geni_i2c_priv *geni, struct i2c_msg *msg, > u32 params) > +{ > + writel(msg->len, geni->base + SE_I2C_RX_TRANS_LEN); > + geni_i2c_setup_m_cmd(geni, I2C_READ, params); > + > + return geni_i2c_fifo_rx_drain(geni, msg); > +} > + > +static int geni_i2c_xfer(struct udevice *bus, struct i2c_msg msgs[], int num) > +{ > + struct geni_i2c_priv *geni = dev_get_priv(bus); > + int i, ret; > + > + qcom_geni_i2c_conf(geni); > + > + for (i = 0; i < num; i++) { > + struct i2c_msg *msg = &msgs[i]; > + u32 m_param = i < (num - 1) ? STOP_STRETCH : 0; > + > + m_param |= ((msg->addr << SLV_ADDR_SHFT) & SLV_ADDR_MSK); > + > + if (msg->flags & I2C_M_RD) > + ret = geni_i2c_xfer_rx(geni, msg, m_param); > + else > + ret = geni_i2c_xfer_tx(geni, msg, m_param); > + > + if (ret) > + break; > + } > + > + if (ret) { > + if (ret == -ETIMEDOUT) { > + u32 status; > + > + writel(M_GENI_CMD_ABORT, geni->base + > SE_GENI_M_CMD_CTRL_REG); > + > + /* Wait until Abort has finished */ > + do { > + status = readl(geni->base + > SE_GENI_M_IRQ_STATUS); > + } while ((status & M_CMD_ABORT_EN) == 0); > + > + writel(status, geni->base + SE_GENI_M_IRQ_STATUS); > + } > + > + return ret; > + } > + > + return 0; > +} > + > +static int geni_i2c_enable_clocks(struct udevice *dev, struct geni_i2c_priv > *geni) > +{ > + int ret; > + > + if (geni->is_master_hub) { > + ret = clk_enable(&geni->core); > + if (ret) { > + dev_err(dev, "clk_enable core failed %d\n", ret); > + return ret; > + } > + } > + > + ret = clk_enable(&geni->se); > + if (ret) { > + dev_err(dev, "clk_enable se failed %d\n", ret); > + return ret; > + } > + > + return 0; > +} > + > +static int geni_i2c_disable_clocks(struct udevice *dev, struct geni_i2c_priv > *geni) > +{ > + int ret; > + > + if (geni->is_master_hub) { > + ret = clk_disable(&geni->core); > + if (ret) { > + dev_err(dev, "clk_enable core failed %d\n", ret); > + return ret; > + } > + } > + > + ret = clk_disable(&geni->se); > + if (ret) { > + dev_err(dev, "clk_enable se failed %d\n", ret); > + return ret; > + } > + > + return 0; > +} > + > +#define NUM_PACKING_VECTORS 4 > +#define PACKING_START_SHIFT 5 > +#define PACKING_DIR_SHIFT 4 > +#define PACKING_LEN_SHIFT 1 > +#define PACKING_STOP_BIT BIT(0) > +#define PACKING_VECTOR_SHIFT 10 > +void geni_i2c_config_packing(struct geni_i2c_priv *geni, int bpw, int > pack_words, > + bool msb_to_lsb, bool tx_cfg, bool rx_cfg) > +{ > + u32 cfg0, cfg1, cfg[NUM_PACKING_VECTORS] = {0}; > + int len; > + int temp_bpw = bpw; > + int idx_start = msb_to_lsb ? bpw - 1 : 0; > + int idx = idx_start; > + int idx_delta = msb_to_lsb ? -BITS_PER_BYTE : BITS_PER_BYTE; > + int ceil_bpw = ALIGN(bpw, BITS_PER_BYTE); > + int iter = (ceil_bpw * pack_words) / BITS_PER_BYTE; > + int i; > + > + if (iter <= 0 || iter > NUM_PACKING_VECTORS) > + return; > + > + for (i = 0; i < iter; i++) { > + len = min_t(int, temp_bpw, BITS_PER_BYTE) - 1; > + cfg[i] = idx << PACKING_START_SHIFT; > + cfg[i] |= msb_to_lsb << PACKING_DIR_SHIFT; > + cfg[i] |= len << PACKING_LEN_SHIFT; > + > + if (temp_bpw <= BITS_PER_BYTE) { > + idx = ((i + 1) * BITS_PER_BYTE) + idx_start; > + temp_bpw = bpw; > + } else { > + idx = idx + idx_delta; > + temp_bpw = temp_bpw - BITS_PER_BYTE; > + } > + } > + cfg[iter - 1] |= PACKING_STOP_BIT; > + cfg0 = cfg[0] | (cfg[1] << PACKING_VECTOR_SHIFT); > + cfg1 = cfg[2] | (cfg[3] << PACKING_VECTOR_SHIFT); > + > + if (tx_cfg) { > + writel(cfg0, geni->base + SE_GENI_TX_PACKING_CFG0); > + writel(cfg1, geni->base + SE_GENI_TX_PACKING_CFG1); > + } > + if (rx_cfg) { > + writel(cfg0, geni->base + SE_GENI_RX_PACKING_CFG0); > + writel(cfg1, geni->base + SE_GENI_RX_PACKING_CFG1); > + } > + > + /* > + * Number of protocol words in each FIFO entry > + * 0 - 4x8, four words in each entry, max word size of 8 bits > + * 1 - 2x16, two words in each entry, max word size of 16 bits > + * 2 - 1x32, one word in each entry, max word size of 32 bits > + * 3 - undefined > + */ > + if (pack_words || bpw == 32) > + writel(bpw / 16, geni->base + SE_GENI_BYTE_GRAN); > +} > + > +static void geni_i2c_init(struct geni_i2c_priv *geni, unsigned int tx_depth) > +{ > + u32 val; > + > + writel(0, geni->base + SE_GSI_EVENT_EN); > + writel(0xffffffff, geni->base + SE_GENI_M_IRQ_CLEAR); > + writel(0xffffffff, geni->base + SE_GENI_S_IRQ_CLEAR); > + writel(0xffffffff, geni->base + SE_IRQ_EN); > + > + val = readl(geni->base + GENI_CGC_CTRL); > + val |= DEFAULT_CGC_EN; > + writel(val, geni->base + GENI_CGC_CTRL); > + > + writel(DEFAULT_IO_OUTPUT_CTRL_MSK, geni->base + GENI_OUTPUT_CTRL); > + writel(FORCE_DEFAULT, geni->base + GENI_FORCE_DEFAULT_REG); > + > + val = readl(geni->base + SE_IRQ_EN); > + val |= GENI_M_IRQ_EN | GENI_S_IRQ_EN; > + writel(val, geni->base + SE_IRQ_EN); > + > + val = readl(geni->base + SE_GENI_DMA_MODE_EN); > + val &= ~GENI_DMA_MODE_EN; > + writel(val, geni->base + SE_GENI_DMA_MODE_EN); > + > + writel(0, geni->base + SE_GSI_EVENT_EN); > + > + writel(tx_depth - 1, geni->base + SE_GENI_RX_WATERMARK_REG); > + writel(tx_depth, geni->base + SE_GENI_RX_RFR_WATERMARK_REG); > + > + val = readl(geni->base + SE_GENI_M_IRQ_EN); > + val |= M_COMMON_GENI_M_IRQ_EN; > + val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; > + val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; > + writel(val, geni->base + SE_GENI_M_IRQ_EN); > + > + val = readl(geni->base + SE_GENI_S_IRQ_EN); > + val |= S_COMMON_GENI_S_IRQ_EN; > + writel(val, geni->base + SE_GENI_S_IRQ_EN); > +} > + > +static u32 geni_i2c_get_tx_fifo_depth(struct geni_i2c_priv *geni) > +{ > + u32 val, hw_version, hw_major, hw_minor, tx_fifo_depth_mask; > + > + hw_version = readl(geni->wrapper + QUP_HW_VER_REG); > + hw_major = GENI_SE_VERSION_MAJOR(hw_version); > + hw_minor = GENI_SE_VERSION_MINOR(hw_version); > + > + if ((hw_major == 3 && hw_minor >= 10) || hw_major > 3) > + tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK_256_BYTES; > + else > + tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK; > + > + val = readl(geni->base + SE_HW_PARAM_0); > + > + return (val & tx_fifo_depth_mask) >> TX_FIFO_DEPTH_SHFT; > +} > + > +static int geni_i2c_probe(struct udevice *dev) > +{ > + ofnode parent_node = ofnode_get_parent(dev_ofnode(dev)); > + struct geni_i2c_priv *geni = dev_get_priv(dev); > + u32 proto, tx_depth, fifo_disable; > + int ret; > + > + geni->is_master_hub = dev_get_driver_data(dev) & GENI_I2C_IS_MASTER_HUB; > + > + geni->wrapper = ofnode_get_addr(parent_node); > + if (geni->wrapper == FDT_ADDR_T_NONE) > + return -EINVAL; > + > + geni->base = (phys_addr_t)dev_read_addr_ptr(dev); > + if (!geni->base) > + return -EINVAL; > + > + if (geni->is_master_hub) { > + ret = clk_get_by_name(dev, "core", &geni->core); > + if (ret) { > + pr_err("clk_get_by_name(core) failed: %d\n", ret); In other places you used dev_err(), but here it's pr_err() (even though dev is available), and below it's pr_err() with __func__ as the prefix. Please make these consistent. > + return ret; > + } > + } > + > + ret = clk_get_by_name(dev, "se", &geni->se); > + if (ret) { > + pr_err("clk_get_by_name(iface) failed: %d\n", ret); > + return ret; > + } > + > + geni_i2c_enable_clocks(dev, geni); > + > + proto = readl(geni->base + GENI_FW_REVISION_RO); > + proto &= FW_REV_PROTOCOL_MSK; > + proto >>= FW_REV_PROTOCOL_SHFT; > + > + if (proto != GENI_SE_I2C) { > + pr_err("%s: Invalid proto %d\n", __func__, proto); > + geni_i2c_disable_clocks(dev, geni); > + return -ENXIO; > + } > + > + fifo_disable = readl(geni->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE; > + if (fifo_disable) { > + geni_i2c_disable_clocks(dev, geni); > + pr_err("%s: FIFO mode disabled, DMA mode unsupported\n", > __func__); > + return -ENXIO; > + } > + > + if (!geni->is_master_hub) { > + tx_depth = geni_i2c_get_tx_fifo_depth(geni); > + if (!tx_depth) { > + geni_i2c_disable_clocks(dev, geni); > + pr_err("%s: Invalid TX FIFO depth\n", __func__); > + return -ENXIO; > + } > + } else { > + tx_depth = 16; > + } > + geni->tx_wm = tx_depth - 1; > + > + geni_i2c_init(geni, tx_depth); > + geni_i2c_config_packing(geni, BITS_PER_BYTE, > + PACKING_BYTES_PW, true, true, true); > + > + /* Setup for standard rate */ > + return geni_i2c_clk_map_idx(geni, I2C_SPEED_STANDARD_RATE); > +} > + > +static int geni_i2c_set_bus_speed(struct udevice *dev, unsigned int clk_freq) > +{ > + struct geni_i2c_priv *geni = dev_get_priv(dev); > + > + return geni_i2c_clk_map_idx(geni, clk_freq); > +} > + > +static const struct dm_i2c_ops geni_i2c_ops = { > + .xfer = geni_i2c_xfer, > + .set_bus_speed = geni_i2c_set_bus_speed, > +}; > + > +static const struct udevice_id geni_i2c_ids[] = { > + { .compatible = "qcom,geni-i2c" }, > + { .compatible = "qcom,geni-i2c-master-hub", .data = > GENI_I2C_IS_MASTER_HUB}, > + {} > +}; > + > +U_BOOT_DRIVER(i2c_geni) = { > + .name = "i2c_geni", > + .id = UCLASS_I2C, > + .of_match = geni_i2c_ids, > + .probe = geni_i2c_probe, > + .priv_auto = sizeof(struct geni_i2c_priv), > + .ops = &geni_i2c_ops, > +}; > + > +static const struct udevice_id geni_i2c_master_hub_ids[] = { > + { .compatible = "qcom,geni-se-i2c-master-hub" }, > + { } > +}; > + > +U_BOOT_DRIVER(geni_i2c_master_hub) = { > + .name = "geni-se-master-hub", > + .id = UCLASS_NOP, > + .of_match = geni_i2c_master_hub_ids, > + .bind = dm_scan_fdt_dev, > + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, > +}; > diff --git a/include/soc/qcom/geni-se.h b/include/soc/qcom/geni-se.h > new file mode 100644 > index 00000000000..698a9256d26 > --- /dev/null > +++ b/include/soc/qcom/geni-se.h > @@ -0,0 +1,265 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. > + */ > + > +#ifndef _QCOM_GENI_SE > +#define _QCOM_GENI_SE > + > +/* Protocols supported by GENI Serial Engines */ > +enum geni_se_protocol_type { > + GENI_SE_NONE, > + GENI_SE_SPI, > + GENI_SE_UART, > + GENI_SE_I2C, > + GENI_SE_I3C, > + GENI_SE_SPI_SLAVE, > +}; > + > +#define QUP_HW_VER_REG 0x4 > + > +/* Common SE registers */ > +#define GENI_INIT_CFG_REVISION 0x0 > +#define GENI_S_INIT_CFG_REVISION 0x4 > +#define GENI_FORCE_DEFAULT_REG 0x20 > +#define GENI_OUTPUT_CTRL 0x24 > +#define GENI_CGC_CTRL 0x28 > +#define SE_GENI_STATUS 0x40 > +#define GENI_SER_M_CLK_CFG 0x48 > +#define GENI_SER_S_CLK_CFG 0x4c > +#define GENI_IF_DISABLE_RO 0x64 > +#define GENI_FW_REVISION_RO 0x68 > +#define SE_GENI_CLK_SEL 0x7c > +#define SE_GENI_CFG_SEQ_START 0x84 > +#define SE_GENI_BYTE_GRAN 0x254 > +#define SE_GENI_DMA_MODE_EN 0x258 > +#define SE_GENI_TX_PACKING_CFG0 0x260 > +#define SE_GENI_TX_PACKING_CFG1 0x264 > +#define SE_GENI_RX_PACKING_CFG0 0x284 > +#define SE_GENI_RX_PACKING_CFG1 0x288 > +#define SE_GENI_M_CMD0 0x600 > +#define SE_GENI_M_CMD_CTRL_REG 0x604 > +#define SE_GENI_M_IRQ_STATUS 0x610 > +#define SE_GENI_M_IRQ_EN 0x614 > +#define SE_GENI_M_IRQ_CLEAR 0x618 > +#define SE_GENI_S_CMD0 0x630 > +#define SE_GENI_S_CMD_CTRL_REG 0x634 > +#define SE_GENI_S_IRQ_STATUS 0x640 > +#define SE_GENI_S_IRQ_EN 0x644 > +#define SE_GENI_S_IRQ_CLEAR 0x648 > +#define SE_GENI_TX_FIFOn 0x700 > +#define SE_GENI_RX_FIFOn 0x780 > +#define SE_GENI_TX_FIFO_STATUS 0x800 > +#define SE_GENI_RX_FIFO_STATUS 0x804 > +#define SE_GENI_TX_WATERMARK_REG 0x80c > +#define SE_GENI_RX_WATERMARK_REG 0x810 > +#define SE_GENI_RX_RFR_WATERMARK_REG 0x814 > +#define SE_GENI_IOS 0x908 > +#define SE_DMA_TX_IRQ_STAT 0xc40 > +#define SE_DMA_TX_IRQ_CLR 0xc44 > +#define SE_DMA_TX_FSM_RST 0xc58 > +#define SE_DMA_RX_IRQ_STAT 0xd40 > +#define SE_DMA_RX_IRQ_CLR 0xd44 > +#define SE_DMA_RX_LEN_IN 0xd54 > +#define SE_DMA_RX_FSM_RST 0xd58 > +#define SE_GSI_EVENT_EN 0xe18 > +#define SE_IRQ_EN 0xe1c > +#define SE_HW_PARAM_0 0xe24 > +#define SE_HW_PARAM_1 0xe28 > + > +/* GENI_FORCE_DEFAULT_REG fields */ > +#define FORCE_DEFAULT BIT(0) > + > +/* GENI_OUTPUT_CTRL fields */ > +#define GENI_IO_MUX_0_EN BIT(0) > +#define DEFAULT_IO_OUTPUT_CTRL_MSK GENMASK(6, 0) > + > +/* GENI_CGC_CTRL fields */ > +#define CFG_AHB_CLK_CGC_ON BIT(0) > +#define CFG_AHB_WR_ACLK_CGC_ON BIT(1) > +#define DATA_AHB_CLK_CGC_ON BIT(2) > +#define SCLK_CGC_ON BIT(3) > +#define TX_CLK_CGC_ON BIT(4) > +#define RX_CLK_CGC_ON BIT(5) > +#define EXT_CLK_CGC_ON BIT(6) > +#define PROG_RAM_HCLK_OFF BIT(8) > +#define PROG_RAM_SCLK_OFF BIT(9) > +#define DEFAULT_CGC_EN GENMASK(6, 0) > + > +/* GENI_STATUS fields */ > +#define M_GENI_CMD_ACTIVE BIT(0) > +#define S_GENI_CMD_ACTIVE BIT(12) > + > +/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */ > +#define SER_CLK_EN BIT(0) > +#define CLK_DIV_MSK GENMASK(15, 4) > +#define CLK_DIV_SHFT 4 > + > +/* GENI_IF_DISABLE_RO fields */ > +#define FIFO_IF_DISABLE (BIT(0)) > + > +/* GENI_FW_REVISION_RO fields */ > +#define FW_REV_PROTOCOL_MSK GENMASK(15, 8) > +#define FW_REV_PROTOCOL_SHFT 8 > + > +/* GENI_CLK_SEL fields */ > +#define CLK_SEL_MSK GENMASK(2, 0) > + > +/* SE_GENI_CFG_SEQ_START fields */ > +#define START_TRIGGER BIT(0) > + > +/* SE_IRQ_EN fields */ > +#define DMA_RX_IRQ_EN BIT(0) > +#define DMA_TX_IRQ_EN BIT(1) > +#define GENI_M_IRQ_EN BIT(2) > +#define GENI_S_IRQ_EN BIT(3) > + > +/* SE_GENI_DMA_MODE_EN */ > +#define GENI_DMA_MODE_EN BIT(0) > + > +/* GENI_M_CMD0 fields */ > +#define M_OPCODE_MSK GENMASK(31, 27) > +#define M_OPCODE_SHFT 27 > +#define M_PARAMS_MSK GENMASK(26, 0) > + > +/* GENI_M_CMD_CTRL_REG */ > +#define M_GENI_CMD_CANCEL BIT(2) > +#define M_GENI_CMD_ABORT BIT(1) > +#define M_GENI_DISABLE BIT(0) > + > +/* GENI_S_CMD0 fields */ > +#define S_OPCODE_MSK GENMASK(31, 27) > +#define S_OPCODE_SHFT 27 > +#define S_PARAMS_MSK GENMASK(26, 0) > + > +/* GENI_S_CMD_CTRL_REG */ > +#define S_GENI_CMD_CANCEL BIT(2) > +#define S_GENI_CMD_ABORT BIT(1) > +#define S_GENI_DISABLE BIT(0) > + > +/* GENI_M_IRQ_EN fields */ > +#define M_CMD_DONE_EN BIT(0) > +#define M_CMD_OVERRUN_EN BIT(1) > +#define M_ILLEGAL_CMD_EN BIT(2) > +#define M_CMD_FAILURE_EN BIT(3) > +#define M_CMD_CANCEL_EN BIT(4) > +#define M_CMD_ABORT_EN BIT(5) > +#define M_TIMESTAMP_EN BIT(6) > +#define M_RX_IRQ_EN BIT(7) > +#define M_GP_SYNC_IRQ_0_EN BIT(8) > +#define M_GP_IRQ_0_EN BIT(9) > +#define M_GP_IRQ_1_EN BIT(10) > +#define M_GP_IRQ_2_EN BIT(11) > +#define M_GP_IRQ_3_EN BIT(12) > +#define M_GP_IRQ_4_EN BIT(13) > +#define M_GP_IRQ_5_EN BIT(14) > +#define M_TX_FIFO_NOT_EMPTY_EN BIT(21) > +#define M_IO_DATA_DEASSERT_EN BIT(22) > +#define M_IO_DATA_ASSERT_EN BIT(23) > +#define M_RX_FIFO_RD_ERR_EN BIT(24) > +#define M_RX_FIFO_WR_ERR_EN BIT(25) > +#define M_RX_FIFO_WATERMARK_EN BIT(26) > +#define M_RX_FIFO_LAST_EN BIT(27) > +#define M_TX_FIFO_RD_ERR_EN BIT(28) > +#define M_TX_FIFO_WR_ERR_EN BIT(29) > +#define M_TX_FIFO_WATERMARK_EN BIT(30) > +#define M_SEC_IRQ_EN BIT(31) > +#define M_COMMON_GENI_M_IRQ_EN (GENMASK(6, 1) | \ > + M_IO_DATA_DEASSERT_EN | \ > + M_IO_DATA_ASSERT_EN | M_RX_FIFO_RD_ERR_EN | \ > + M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | \ > + M_TX_FIFO_WR_ERR_EN) > + > +/* GENI_S_IRQ_EN fields */ > +#define S_CMD_DONE_EN BIT(0) > +#define S_CMD_OVERRUN_EN BIT(1) > +#define S_ILLEGAL_CMD_EN BIT(2) > +#define S_CMD_FAILURE_EN BIT(3) > +#define S_CMD_CANCEL_EN BIT(4) > +#define S_CMD_ABORT_EN BIT(5) > +#define S_GP_SYNC_IRQ_0_EN BIT(8) > +#define S_GP_IRQ_0_EN BIT(9) > +#define S_GP_IRQ_1_EN BIT(10) > +#define S_GP_IRQ_2_EN BIT(11) > +#define S_GP_IRQ_3_EN BIT(12) > +#define S_GP_IRQ_4_EN BIT(13) > +#define S_GP_IRQ_5_EN BIT(14) > +#define S_IO_DATA_DEASSERT_EN BIT(22) > +#define S_IO_DATA_ASSERT_EN BIT(23) > +#define S_RX_FIFO_RD_ERR_EN BIT(24) > +#define S_RX_FIFO_WR_ERR_EN BIT(25) > +#define S_RX_FIFO_WATERMARK_EN BIT(26) > +#define S_RX_FIFO_LAST_EN BIT(27) > +#define S_COMMON_GENI_S_IRQ_EN (GENMASK(5, 1) | GENMASK(13, 9) | \ > + S_RX_FIFO_RD_ERR_EN | S_RX_FIFO_WR_ERR_EN) > + > +/* GENI_/TX/RX/RX_RFR/_WATERMARK_REG fields */ > +#define WATERMARK_MSK GENMASK(5, 0) > + > +/* GENI_TX_FIFO_STATUS fields */ > +#define TX_FIFO_WC GENMASK(27, 0) > + > +/* GENI_RX_FIFO_STATUS fields */ > +#define RX_LAST BIT(31) > +#define RX_LAST_BYTE_VALID_MSK GENMASK(30, 28) > +#define RX_LAST_BYTE_VALID_SHFT 28 > +#define RX_FIFO_WC_MSK GENMASK(24, 0) > + > +/* SE_GENI_IOS fields */ > +#define IO2_DATA_IN BIT(1) > +#define RX_DATA_IN BIT(0) > + > +/* SE_DMA_TX_IRQ_STAT Register fields */ > +#define TX_DMA_DONE BIT(0) > +#define TX_EOT BIT(1) > +#define TX_SBE BIT(2) > +#define TX_RESET_DONE BIT(3) > + > +/* SE_DMA_RX_IRQ_STAT Register fields */ > +#define RX_DMA_DONE BIT(0) > +#define RX_EOT BIT(1) > +#define RX_SBE BIT(2) > +#define RX_RESET_DONE BIT(3) > +#define RX_FLUSH_DONE BIT(4) > +#define RX_DMA_PARITY_ERR BIT(5) > +#define RX_DMA_BREAK GENMASK(8, 7) > +#define RX_GENI_GP_IRQ GENMASK(10, 5) > +#define RX_GENI_CANCEL_IRQ BIT(11) > +#define RX_GENI_GP_IRQ_EXT GENMASK(13, 12) > + > +/* SE_HW_PARAM_0 fields */ > +#define TX_FIFO_WIDTH_MSK GENMASK(29, 24) > +#define TX_FIFO_WIDTH_SHFT 24 > +/* > + * For QUP HW Version >= 3.10 Tx fifo depth support is increased > + * to 256bytes and corresponding bits are 16 to 23 > + */ > +#define TX_FIFO_DEPTH_MSK_256_BYTES GENMASK(23, 16) > +#define TX_FIFO_DEPTH_MSK GENMASK(21, 16) > +#define TX_FIFO_DEPTH_SHFT 16 > + > +/* SE_HW_PARAM_1 fields */ > +#define RX_FIFO_WIDTH_MSK GENMASK(29, 24) > +#define RX_FIFO_WIDTH_SHFT 24 > +/* > + * For QUP HW Version >= 3.10 Rx fifo depth support is increased > + * to 256bytes and corresponding bits are 16 to 23 > + */ > +#define RX_FIFO_DEPTH_MSK_256_BYTES GENMASK(23, 16) > +#define RX_FIFO_DEPTH_MSK GENMASK(21, 16) > +#define RX_FIFO_DEPTH_SHFT 16 > + > +#define HW_VER_MAJOR_MASK GENMASK(31, 28) > +#define HW_VER_MAJOR_SHFT 28 > +#define HW_VER_MINOR_MASK GENMASK(27, 16) > +#define HW_VER_MINOR_SHFT 16 > +#define HW_VER_STEP_MASK GENMASK(15, 0) > + > +#define GENI_SE_VERSION_MAJOR(ver) ((ver & HW_VER_MAJOR_MASK) >> > HW_VER_MAJOR_SHFT) > +#define GENI_SE_VERSION_MINOR(ver) ((ver & HW_VER_MINOR_MASK) >> > HW_VER_MINOR_SHFT) > +#define GENI_SE_VERSION_STEP(ver) (ver & HW_VER_STEP_MASK) > + > +/* QUP SE VERSION value for major number 2 and minor number 5 */ > +#define QUP_SE_VERSION_2_5 0x20050000 > + > +#endif > -- // Caleb (they/them)