diff --git a/src/cndm/modules/cndm/cndm.h b/src/cndm/modules/cndm/cndm.h index b05a65e..faa530a 100644 --- a/src/cndm/modules/cndm/cndm.h +++ b/src/cndm/modules/cndm/cndm.h @@ -58,6 +58,45 @@ struct cndm_dev { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; u64 ptp_nom_period; + + // config + u16 cfg_page_max; + u32 cmd_ver; + + // FW ID + u32 fpga_id; + u32 fw_id; + u32 fw_ver; + u32 board_id; + u32 board_ver; + u32 build_date; + u32 git_hash; + u32 release_info; + char build_date_str[32]; + + // HW config + u16 sys_clk_per_ns_num; + u16 sys_clk_per_ns_den; + u16 ptp_clk_per_ns_num; + u16 ptp_clk_per_ns_den; + + // Resources + u8 log_max_eq; + u8 log_max_eq_sz; + u8 eq_pool; + u8 eqe_ver; + u8 log_max_cq; + u8 log_max_cq_sz; + u8 cq_pool; + u8 cqe_ver; + u8 log_max_sq; + u8 log_max_sq_sz; + u8 sq_pool; + u8 sqe_ver; + u8 log_max_rq; + u8 log_max_rq_sz; + u8 rq_pool; + u8 rqe_ver; }; struct cndm_tx_info { diff --git a/src/cndm/modules/cndm/cndm_hw.h b/src/cndm/modules/cndm/cndm_hw.h index 352f2fc..1b7c68d 100644 --- a/src/cndm/modules/cndm/cndm_hw.h +++ b/src/cndm/modules/cndm/cndm_hw.h @@ -15,6 +15,8 @@ Authors: #define CNDM_CMD_OP_NOP 0x0000 +#define CNDM_CMD_OP_CFG 0x0100 + #define CNDM_CMD_OP_ACCESS_REG 0x0180 #define CNDM_CMD_OP_PTP 0x0190 @@ -43,28 +45,68 @@ Authors: #define CNDM_CMD_OP_QUERY_QP 0x0242 #define CNDM_CMD_OP_DESTROY_QP 0x0243 -struct cndm_cmd_queue { +struct cndm_cmd_cfg { __le16 rsvd; union { __le16 opcode; __le16 status; }; __le32 flags; - __le32 port; - __le32 qn; + struct { + __le16 cfg_page; + __le16 cfg_page_max; + }; + __le32 cmd_ver; - __le32 qn2; - __le32 pd; - __le32 size; - __le32 dboffs; + __le32 fw_ver; + __u8 port_count; + __u8 rsvd2[3]; + __le32 rsvd3[2]; - __le64 ptr1; - __le64 ptr2; - - __le32 dw12; - __le32 dw13; - __le32 dw14; - __le32 dw15; + union { + struct { + // Page 0: FW ID + __le32 fpga_id; + __le32 fw_id; + __le32 fw_ver; + __le32 board_id; + __le32 board_ver; + __le32 build_date; + __le32 git_hash; + __le32 release_info; + } p0; + struct { + // Page 1: HW config + __le16 port_count; + __le16 rsvd1; + __le32 rsvd2[3]; + __le16 sys_clk_per_ns_den; + __le16 sys_clk_per_ns_num; + __le16 ptp_clk_per_ns_den; + __le16 ptp_clk_per_ns_num; + __le32 rsvd3[2]; + } p1; + struct { + // Page 2: Resources + __u8 log_max_eq; + __u8 log_max_eq_sz; + __u8 eq_pool; + __u8 eqe_ver; + __u8 log_max_cq; + __u8 log_max_cq_sz; + __u8 cq_pool; + __u8 cqe_ver; + __u8 log_max_sq; + __u8 log_max_sq_sz; + __u8 sq_pool; + __u8 sqe_ver; + __u8 log_max_rq; + __u8 log_max_rq_sz; + __u8 rq_pool; + __u8 rqe_ver; + __le32 rsvd[4]; + } p2; + }; }; #define CNDM_CMD_REG_FLG_WRITE 0x00000001 @@ -77,21 +119,11 @@ struct cndm_cmd_reg { __le16 status; }; __le32 flags; - __le32 dw2; - __le32 dw3; - - __le32 dw4; - __le32 dw5; - __le32 dw6; + __le32 rsvd1[5]; __le32 reg_addr; - __le64 write_val; __le64 read_val; - - __le32 dw12; - __le32 dw13; - __le32 dw14; - __le32 dw15; + __le32 rsvd2[4]; }; #define CNDM_CMD_PTP_FLG_SET_TOD 0x00000001 @@ -118,6 +150,29 @@ struct cndm_cmd_ptp { __le64 nom_period; __le64 period; + __le32 rsvd2[2]; +}; + +struct cndm_cmd_queue { + __le16 rsvd; + union { + __le16 opcode; + __le16 status; + }; + __le32 flags; + __le32 port; + __le32 qn; + + __le32 qn2; + __le32 pd; + __le32 size; + __le32 dboffs; + + __le64 ptr1; + __le64 ptr2; + + __le32 prod; + __le32 cons; __le32 dw14; __le32 dw15; }; diff --git a/src/cndm/modules/cndm/cndm_main.c b/src/cndm/modules/cndm/cndm_main.c index f894cb7..f25380e 100644 --- a/src/cndm/modules/cndm/cndm_main.c +++ b/src/cndm/modules/cndm/cndm_main.c @@ -9,9 +9,9 @@ Authors: */ #include "cndm.h" -#include "cndm_hw.h" -#include #include +#include +#include #include MODULE_DESCRIPTION("Corundum device driver"); @@ -44,9 +44,13 @@ static int cndm_common_probe(struct cndm_dev *cdev) { struct devlink *devlink = priv_to_devlink(cdev); struct device *dev = cdev->dev; + struct rtc_time tm; int ret = 0; int k; + struct cndm_cmd_cfg cmd; + struct cndm_cmd_cfg rsp; + mutex_init(&cdev->mbox_lock); #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) @@ -55,9 +59,125 @@ static int cndm_common_probe(struct cndm_dev *cdev) devlink_register(devlink, dev); #endif - cdev->port_count = ioread32(cdev->hw_addr + 0x0100); + // Read config page 0 + cmd.opcode = CNDM_CMD_OP_CFG; + cmd.flags = 0x00000000; + cmd.cfg_page = 0; + + cndm_exec_cmd(cdev, &cmd, &rsp); + + cdev->cfg_page_max = rsp.cfg_page_max; + cdev->cmd_ver = rsp.cmd_ver; + + dev_info(dev, "Config pages: %d", cdev->cfg_page_max+1); + dev_info(dev, "Command version: %d.%d.%d", cdev->cmd_ver >> 20, + (cdev->cmd_ver >> 12) & 0xff, + cdev->cmd_ver & 0xfff); + + // FW ID + cdev->fpga_id = rsp.p0.fpga_id; + cdev->fw_id = rsp.p0.fw_id; + cdev->fw_ver = rsp.p0.fw_ver; + cdev->board_id = rsp.p0.board_id; + cdev->board_ver = rsp.p0.board_ver; + cdev->build_date = rsp.p0.build_date; + cdev->git_hash = rsp.p0.git_hash; + cdev->release_info = rsp.p0.release_info; + + rtc_time64_to_tm(cdev->build_date, &tm); + + dev_info(dev, "FPGA ID: 0x%08x", cdev->fpga_id); + dev_info(dev, "FW ID: 0x%08x", cdev->fw_id); + dev_info(dev, "FW version: %d.%d.%d", cdev->fw_ver >> 20, + (cdev->fw_ver >> 12) & 0xff, + cdev->fw_ver & 0xfff); + dev_info(dev, "Board ID: 0x%08x", cdev->board_id); + dev_info(dev, "Board version: %d.%d.%d", cdev->board_ver >> 20, + (cdev->board_ver >> 12) & 0xff, + cdev->board_ver & 0xfff); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) + snprintf(cdev->build_date_str, sizeof(cdev->build_date_str), "%ptRd %ptRt", &tm, &tm); +#else + snprintf(cdev->build_date_str, sizeof(cdev->build_date_str), "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); +#endif + dev_info(dev, "Build date: %s UTC (raw: 0x%08x)", cdev->build_date_str, cdev->build_date); + dev_info(dev, "Git hash: %08x", cdev->git_hash); + dev_info(dev, "Release info: %08x", cdev->release_info); + + // Read config page 1 + cmd.opcode = CNDM_CMD_OP_CFG; + cmd.flags = 0x00000000; + cmd.cfg_page = 1; + + cndm_exec_cmd(cdev, &cmd, &rsp); + + // HW config + cdev->port_count = rsp.p1.port_count; + cdev->sys_clk_per_ns_num = rsp.p1.sys_clk_per_ns_num; + cdev->sys_clk_per_ns_den = rsp.p1.sys_clk_per_ns_den; + cdev->ptp_clk_per_ns_num = rsp.p1.ptp_clk_per_ns_num; + cdev->ptp_clk_per_ns_den = rsp.p1.ptp_clk_per_ns_den; dev_info(dev, "Port count: %d", cdev->port_count); + if (cdev->sys_clk_per_ns_num != 0) { + u64 a, b, c; + a = (u64)cdev->sys_clk_per_ns_den * 1000; + b = a / cdev->sys_clk_per_ns_num; + c = a - (b * cdev->sys_clk_per_ns_num); + c = (c * 1000000000) / cdev->sys_clk_per_ns_num; + dev_info(dev, "Sys clock freq: %lld.%09lld MHz (raw %d/%d ns)", b, c, cdev->sys_clk_per_ns_num, cdev->sys_clk_per_ns_den); + } + if (cdev->ptp_clk_per_ns_num != 0) { + u64 a, b, c; + a = (u64)cdev->ptp_clk_per_ns_den * 1000; + b = a / cdev->ptp_clk_per_ns_num; + c = a - (b * cdev->ptp_clk_per_ns_num); + c = (c * 1000000000) / cdev->ptp_clk_per_ns_num; + dev_info(dev, "PTP clock freq: %lld.%09lld MHz (raw %d/%d ns)", b, c, cdev->ptp_clk_per_ns_num, cdev->ptp_clk_per_ns_den); + } + + // Read config page 2 + cmd.opcode = CNDM_CMD_OP_CFG; + cmd.flags = 0x00000000; + cmd.cfg_page = 2; + + cndm_exec_cmd(cdev, &cmd, &rsp); + + // Resources + cdev->log_max_eq = rsp.p2.log_max_eq; + cdev->log_max_eq_sz = rsp.p2.log_max_eq_sz; + cdev->eq_pool = rsp.p2.eq_pool; + cdev->eqe_ver = rsp.p2.eqe_ver; + cdev->log_max_cq = rsp.p2.log_max_cq; + cdev->log_max_cq_sz = rsp.p2.log_max_cq_sz; + cdev->cq_pool = rsp.p2.cq_pool; + cdev->cqe_ver = rsp.p2.cqe_ver; + cdev->log_max_sq = rsp.p2.log_max_sq; + cdev->log_max_sq_sz = rsp.p2.log_max_sq_sz; + cdev->sq_pool = rsp.p2.sq_pool; + cdev->sqe_ver = rsp.p2.sqe_ver; + cdev->log_max_rq = rsp.p2.log_max_rq; + cdev->log_max_rq_sz = rsp.p2.log_max_rq_sz; + cdev->rq_pool = rsp.p2.rq_pool; + cdev->rqe_ver = rsp.p2.rqe_ver; + + dev_info(dev, "Max EQ count: %d (log %d)", 1 << cdev->log_max_eq, cdev->log_max_eq); + dev_info(dev, "Max EQ size: %d (log %d)", 1 << cdev->log_max_eq_sz, cdev->log_max_eq_sz); + dev_info(dev, "EQ pool: %d", cdev->eq_pool); + dev_info(dev, "EQE version: %d", cdev->eqe_ver); + dev_info(dev, "Max CQ count: %d (log %d)", 1 << cdev->log_max_cq, cdev->log_max_cq); + dev_info(dev, "Max CQ size: %d (log %d)", 1 << cdev->log_max_cq_sz, cdev->log_max_cq_sz); + dev_info(dev, "CQ pool: %d", cdev->cq_pool); + dev_info(dev, "CQE version: %d", cdev->cqe_ver); + dev_info(dev, "Max SQ count: %d (log %d)", 1 << cdev->log_max_sq, cdev->log_max_sq); + dev_info(dev, "Max SQ size: %d (log %d)", 1 << cdev->log_max_sq_sz, cdev->log_max_sq_sz); + dev_info(dev, "SQ pool: %d", cdev->sq_pool); + dev_info(dev, "SQE version: %d", cdev->sqe_ver); + dev_info(dev, "Max RQ count: %d (log %d)", 1 << cdev->log_max_rq, cdev->log_max_rq); + dev_info(dev, "Max RQ size: %d (log %d)", 1 << cdev->log_max_rq_sz, cdev->log_max_rq_sz); + dev_info(dev, "RQ pool: %d", cdev->rq_pool); + dev_info(dev, "RQE version: %d", cdev->rqe_ver); if (cdev->port_count > ARRAY_SIZE(cdev->ndev)) cdev->port_count = ARRAY_SIZE(cdev->ndev);