// SPDX-License-Identifier: GPL-2.0
/*
* ARM Message Handling Unit Version 3 (MHUv3) driver.
*
* Copyright (C) 2024 ARM Ltd.
*
* Based on ARM MHUv2 driver.
*/
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/types.h>
/* ====== MHUv3 Registers ====== */
/* Maximum number of Doorbell channel windows */
#define MHUV3_DBCW_MAX 128
/* Number of DBCH combined interrupt status registers */
#define MHUV3_DBCH_CMB_INT_ST_REG_CNT 4
/* Number of FFCH combined interrupt status registers */
#define MHUV3_FFCH_CMB_INT_ST_REG_CNT 2
#define MHUV3_FLAG_BITS 32
/* Not a typo ... */
#define MHUV3_MAJOR_VERSION 2
enum {
MHUV3_MBOX_CELL_TYPE,
MHUV3_MBOX_CELL_CHWN,
MHUV3_MBOX_CELL_PARAM,
MHUV3_MBOX_CELLS
};
/* Padding bitfields/fields represents hole in the regs MMIO */
/* CTRL_Page */
struct blk_id {
#define id GENMASK(3, 0)
u32 val;
} __packed;
struct feat_spt0 {
#define dbe_spt GENMASK(3, 0)
#define fe_spt GENMASK(7, 4)
#define fce_spt GENMASK(11, 8)
u32 val;
} __packed;
struct feat_spt1 {
#define auto_op_spt GENMASK(3, 0)
u32 val;
} __packed;
struct dbch_cfg0 {
#define num_dbch GENMASK(7, 0)
u32 val;
} __packed;
struct ffch_cfg0 {
#define num_ffch GENMASK(7, 0)
#define x8ba_spt BIT(8)
#define x16ba_spt BIT(9)
#define x32ba_spt BIT(10)
#define x64ba_spt BIT(11)
#define ffch_depth GENMASK(25, 16)
u32 val;
} __packed;
struct fch_cfg0 {
#define num_fch GENMASK(9, 0)
#define fcgi_spt BIT(10) // MBX-only
#define num_fcg GENMASK(15, 11)
#define num_fch_per_grp GENMASK(20, 16)
#define fch_ws GENMASK(28, 21)
u32 val;
} __packed;
struct ctrl {
#define op_req BIT(0)
#define ch_op_mask BIT(1)
u32 val;
} __packed;
struct fch_ctrl {
#define _int_en BIT(2)
u32 val;
} __packed;
struct iidr {
#define implementer GENMASK(11, 0)
#define revision GENMASK(15, 12)
#define variant GENMASK(19, 16)
#define product_id GENMASK(31, 20)
u32 val;
} __packed;
struct aidr {
#define arch_minor_rev GENMASK(3, 0)
#define arch_major_rev GENMASK(7, 4)
u32 val;
} __packed;
struct ctrl_page {
struct blk_id blk_id;
u8 pad[12];
struct feat_spt0 feat_spt0;
struct feat_spt1 feat_spt1;
u8 pad1[8];
struct dbch_cfg0 dbch_cfg0;
u8 pad2[12];
struct ffch_cfg0 ffch_cfg0;
u8 pad3[12];
struct fch_cfg0 fch_cfg0;
u8 pad4[188];
struct ctrl x_ctrl;
/*-- MBX-only registers --*/
u8 pad5[60];
struct fch_ctrl fch_ctrl;
u32 fcg_int_en;
u8 pad6[696];
/*-- End of MBX-only ---- */
u32 dbch_int_st[MHUV3_DBCH_CMB_INT_ST_REG_CNT];
u32 ffch_int_st[MHUV3_FFCH_CMB_INT_ST_REG_CNT];
/*-- MBX-only registers --*/
u8 pad7[88];
u32 fcg_int_st;
u8 pad8[12];
u32 fcg_grp_int_st[32];
u8 pad9[2760];
/*-- End of MBX-only ---- */
struct iidr iidr;
struct aidr aidr;
u32 imp_def_id[12];
} __packed;
/* DBCW_Page */
struct xbcw_ctrl {
#define comb_en BIT(0)
u32 val;
} __packed;
struct pdbcw_int {
#define tfr_ack BIT(0)
u32 val;
} __packed;
struct pdbcw_page {
u32 st;
u8 pad[8];
u32 set;
struct pdbcw_int int_st;
struct pdbcw_int int_clr;
struct pdbcw_int int_en;
struct xbcw_ctrl ctrl;
} __packed;
struct mdbcw_page {
u32 st;
u32 st_msk;
u32 clr;
u8 pad[4];
u32 msk_st;
u32 msk_set;
u32 msk_clr;
struct xbcw_ctrl ctrl;
} __packed;
struct dummy_page {
u8 pad[SZ_4K];
} __packed;
struct mhu3_pbx_frame_reg {
struct ctrl_page ctrl;
struct pdbcw_page dbcw[MHUV3_DBCW_MAX];
struct dummy_page ffcw;
struct dummy_page fcw;
u8 pad[SZ_4K *