14543534cSDong Yibo // SPDX-License-Identifier: GPL-2.0 24543534cSDong Yibo /* Copyright(c) 2022 - 2025 Mucse Corporation. */ 34543534cSDong Yibo 44543534cSDong Yibo #include <linux/errno.h> 54543534cSDong Yibo #include <linux/bitfield.h> 64543534cSDong Yibo #include <linux/iopoll.h> 74543534cSDong Yibo 84543534cSDong Yibo #include "rnpgbe_mbx.h" 94543534cSDong Yibo 104543534cSDong Yibo /** 114543534cSDong Yibo * mbx_data_rd32 - Reads reg with base mbx->fwpf_shm_base 124543534cSDong Yibo * @mbx: pointer to the MBX structure 134543534cSDong Yibo * @reg: register offset 144543534cSDong Yibo * 154543534cSDong Yibo * Return: register value 164543534cSDong Yibo **/ 174543534cSDong Yibo static u32 mbx_data_rd32(struct mucse_mbx_info *mbx, u32 reg) 184543534cSDong Yibo { 194543534cSDong Yibo struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 204543534cSDong Yibo 214543534cSDong Yibo return readl(hw->hw_addr + mbx->fwpf_shm_base + reg); 224543534cSDong Yibo } 234543534cSDong Yibo 244543534cSDong Yibo /** 254543534cSDong Yibo * mbx_data_wr32 - Writes value to reg with base mbx->fwpf_shm_base 264543534cSDong Yibo * @mbx: pointer to the MBX structure 274543534cSDong Yibo * @reg: register offset 284543534cSDong Yibo * @value: value to be written 294543534cSDong Yibo * 304543534cSDong Yibo **/ 314543534cSDong Yibo static void mbx_data_wr32(struct mucse_mbx_info *mbx, u32 reg, u32 value) 324543534cSDong Yibo { 334543534cSDong Yibo struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 344543534cSDong Yibo 354543534cSDong Yibo writel(value, hw->hw_addr + mbx->fwpf_shm_base + reg); 364543534cSDong Yibo } 374543534cSDong Yibo 384543534cSDong Yibo /** 394543534cSDong Yibo * mbx_ctrl_rd32 - Reads reg with base mbx->fwpf_ctrl_base 404543534cSDong Yibo * @mbx: pointer to the MBX structure 414543534cSDong Yibo * @reg: register offset 424543534cSDong Yibo * 434543534cSDong Yibo * Return: register value 444543534cSDong Yibo **/ 454543534cSDong Yibo static u32 mbx_ctrl_rd32(struct mucse_mbx_info *mbx, u32 reg) 464543534cSDong Yibo { 474543534cSDong Yibo struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 484543534cSDong Yibo 494543534cSDong Yibo return readl(hw->hw_addr + mbx->fwpf_ctrl_base + reg); 504543534cSDong Yibo } 514543534cSDong Yibo 524543534cSDong Yibo /** 534543534cSDong Yibo * mbx_ctrl_wr32 - Writes value to reg with base mbx->fwpf_ctrl_base 544543534cSDong Yibo * @mbx: pointer to the MBX structure 554543534cSDong Yibo * @reg: register offset 564543534cSDong Yibo * @value: value to be written 574543534cSDong Yibo * 584543534cSDong Yibo **/ 594543534cSDong Yibo static void mbx_ctrl_wr32(struct mucse_mbx_info *mbx, u32 reg, u32 value) 604543534cSDong Yibo { 614543534cSDong Yibo struct mucse_hw *hw = container_of(mbx, struct mucse_hw, mbx); 624543534cSDong Yibo 634543534cSDong Yibo writel(value, hw->hw_addr + mbx->fwpf_ctrl_base + reg); 644543534cSDong Yibo } 654543534cSDong Yibo 664543534cSDong Yibo /** 674543534cSDong Yibo * mucse_mbx_get_lock_pf - Write ctrl and read back lock status 684543534cSDong Yibo * @hw: pointer to the HW structure 694543534cSDong Yibo * 704543534cSDong Yibo * Return: register value after write 714543534cSDong Yibo **/ 724543534cSDong Yibo static u32 mucse_mbx_get_lock_pf(struct mucse_hw *hw) 734543534cSDong Yibo { 744543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 754543534cSDong Yibo u32 reg = MUCSE_MBX_PF2FW_CTRL(mbx); 764543534cSDong Yibo 774543534cSDong Yibo mbx_ctrl_wr32(mbx, reg, MUCSE_MBX_PFU); 784543534cSDong Yibo 794543534cSDong Yibo return mbx_ctrl_rd32(mbx, reg); 804543534cSDong Yibo } 814543534cSDong Yibo 824543534cSDong Yibo /** 834543534cSDong Yibo * mucse_obtain_mbx_lock_pf - Obtain mailbox lock 844543534cSDong Yibo * @hw: pointer to the HW structure 854543534cSDong Yibo * 864543534cSDong Yibo * Pair with mucse_release_mbx_lock_pf() 874543534cSDong Yibo * This function maybe used in an irq handler. 884543534cSDong Yibo * 894543534cSDong Yibo * Return: 0 on success, negative errno on failure 904543534cSDong Yibo **/ 914543534cSDong Yibo static int mucse_obtain_mbx_lock_pf(struct mucse_hw *hw) 924543534cSDong Yibo { 934543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 944543534cSDong Yibo u32 val; 954543534cSDong Yibo 964543534cSDong Yibo return read_poll_timeout_atomic(mucse_mbx_get_lock_pf, 974543534cSDong Yibo val, val & MUCSE_MBX_PFU, 984543534cSDong Yibo mbx->delay_us, 994543534cSDong Yibo mbx->timeout_us, 1004543534cSDong Yibo false, hw); 1014543534cSDong Yibo } 1024543534cSDong Yibo 1034543534cSDong Yibo /** 1044543534cSDong Yibo * mucse_release_mbx_lock_pf - Release mailbox lock 1054543534cSDong Yibo * @hw: pointer to the HW structure 1064543534cSDong Yibo * @req: send a request or not 1074543534cSDong Yibo * 1084543534cSDong Yibo * Pair with mucse_obtain_mbx_lock_pf(): 1094543534cSDong Yibo * - Releases the mailbox lock by clearing MUCSE_MBX_PFU bit 1104543534cSDong Yibo * - Simultaneously sends the request by setting MUCSE_MBX_REQ bit 1114543534cSDong Yibo * if req is true 1124543534cSDong Yibo * (Both bits are in the same mailbox control register, 1134543534cSDong Yibo * so operations are combined) 1144543534cSDong Yibo **/ 1154543534cSDong Yibo static void mucse_release_mbx_lock_pf(struct mucse_hw *hw, bool req) 1164543534cSDong Yibo { 1174543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 1184543534cSDong Yibo u32 reg = MUCSE_MBX_PF2FW_CTRL(mbx); 1194543534cSDong Yibo 1204543534cSDong Yibo mbx_ctrl_wr32(mbx, reg, req ? MUCSE_MBX_REQ : 0); 1214543534cSDong Yibo } 1224543534cSDong Yibo 1234543534cSDong Yibo /** 1244543534cSDong Yibo * mucse_mbx_get_fwreq - Read fw req from reg 1254543534cSDong Yibo * @mbx: pointer to the mbx structure 1264543534cSDong Yibo * 1274543534cSDong Yibo * Return: the fwreq value 1284543534cSDong Yibo **/ 1294543534cSDong Yibo static u16 mucse_mbx_get_fwreq(struct mucse_mbx_info *mbx) 1304543534cSDong Yibo { 1314543534cSDong Yibo u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT); 1324543534cSDong Yibo 1334543534cSDong Yibo return FIELD_GET(GENMASK_U32(15, 0), val); 1344543534cSDong Yibo } 1354543534cSDong Yibo 1364543534cSDong Yibo /** 1374543534cSDong Yibo * mucse_mbx_inc_pf_ack - Increase ack 1384543534cSDong Yibo * @hw: pointer to the HW structure 1394543534cSDong Yibo * 1404543534cSDong Yibo * mucse_mbx_inc_pf_ack reads pf_ack from hw, then writes 1414543534cSDong Yibo * new value back after increase 1424543534cSDong Yibo **/ 1434543534cSDong Yibo static void mucse_mbx_inc_pf_ack(struct mucse_hw *hw) 1444543534cSDong Yibo { 1454543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 1464543534cSDong Yibo u16 ack; 1474543534cSDong Yibo u32 val; 1484543534cSDong Yibo 1494543534cSDong Yibo val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT); 1504543534cSDong Yibo ack = FIELD_GET(GENMASK_U32(31, 16), val); 1514543534cSDong Yibo ack++; 1524543534cSDong Yibo val &= ~GENMASK_U32(31, 16); 1534543534cSDong Yibo val |= FIELD_PREP(GENMASK_U32(31, 16), ack); 1544543534cSDong Yibo mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val); 1554543534cSDong Yibo } 1564543534cSDong Yibo 1574543534cSDong Yibo /** 1584543534cSDong Yibo * mucse_read_mbx_pf - Read a message from the mailbox 1594543534cSDong Yibo * @hw: pointer to the HW structure 1604543534cSDong Yibo * @msg: the message buffer 1614543534cSDong Yibo * @size: length of buffer 1624543534cSDong Yibo * 1634543534cSDong Yibo * mucse_read_mbx_pf copies a message from the mbx buffer to the caller's 1644543534cSDong Yibo * memory buffer. The presumption is that the caller knows that there was 1654543534cSDong Yibo * a message due to a fw request so no polling for message is needed. 1664543534cSDong Yibo * 1674543534cSDong Yibo * Return: 0 on success, negative errno on failure 1684543534cSDong Yibo **/ 1694543534cSDong Yibo static int mucse_read_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size) 1704543534cSDong Yibo { 1714543534cSDong Yibo const int size_in_words = size / sizeof(u32); 1724543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 1734543534cSDong Yibo int err; 1744543534cSDong Yibo 1754543534cSDong Yibo err = mucse_obtain_mbx_lock_pf(hw); 1764543534cSDong Yibo if (err) 1774543534cSDong Yibo return err; 1784543534cSDong Yibo 1794543534cSDong Yibo for (int i = 0; i < size_in_words; i++) 1804543534cSDong Yibo msg[i] = mbx_data_rd32(mbx, MUCSE_MBX_FWPF_SHM + 4 * i); 1814543534cSDong Yibo /* Hw needs write data_reg at last */ 1824543534cSDong Yibo mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM, 0); 1834543534cSDong Yibo /* flush reqs as we have read this request data */ 1844543534cSDong Yibo hw->mbx.fw_req = mucse_mbx_get_fwreq(mbx); 1854543534cSDong Yibo mucse_mbx_inc_pf_ack(hw); 1864543534cSDong Yibo mucse_release_mbx_lock_pf(hw, false); 1874543534cSDong Yibo 1884543534cSDong Yibo return 0; 1894543534cSDong Yibo } 1904543534cSDong Yibo 1914543534cSDong Yibo /** 1924543534cSDong Yibo * mucse_check_for_msg_pf - Check to see if the fw has sent mail 1934543534cSDong Yibo * @hw: pointer to the HW structure 1944543534cSDong Yibo * 1954543534cSDong Yibo * Return: 0 if the fw has set the Status bit or else -EIO 1964543534cSDong Yibo **/ 1974543534cSDong Yibo static int mucse_check_for_msg_pf(struct mucse_hw *hw) 1984543534cSDong Yibo { 1994543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 2004543534cSDong Yibo u16 fw_req; 2014543534cSDong Yibo 2024543534cSDong Yibo fw_req = mucse_mbx_get_fwreq(mbx); 2034543534cSDong Yibo /* chip's register is reset to 0 when rc send reset 2044543534cSDong Yibo * mbx command. Return -EIO if in this state, others 2054543534cSDong Yibo * fw == hw->mbx.fw_req means no new msg. 2064543534cSDong Yibo **/ 2074543534cSDong Yibo if (fw_req == 0 || fw_req == hw->mbx.fw_req) 2084543534cSDong Yibo return -EIO; 2094543534cSDong Yibo 2104543534cSDong Yibo return 0; 2114543534cSDong Yibo } 2124543534cSDong Yibo 2134543534cSDong Yibo /** 2144543534cSDong Yibo * mucse_poll_for_msg - Wait for message notification 2154543534cSDong Yibo * @hw: pointer to the HW structure 2164543534cSDong Yibo * 2174543534cSDong Yibo * Return: 0 on success, negative errno on failure 2184543534cSDong Yibo **/ 2194543534cSDong Yibo static int mucse_poll_for_msg(struct mucse_hw *hw) 2204543534cSDong Yibo { 2214543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 2224543534cSDong Yibo int val; 2234543534cSDong Yibo 2244543534cSDong Yibo return read_poll_timeout(mucse_check_for_msg_pf, 2254543534cSDong Yibo val, !val, mbx->delay_us, 2264543534cSDong Yibo mbx->timeout_us, 2274543534cSDong Yibo false, hw); 2284543534cSDong Yibo } 2294543534cSDong Yibo 2304543534cSDong Yibo /** 2314543534cSDong Yibo * mucse_poll_and_read_mbx - Wait for message notification and receive message 2324543534cSDong Yibo * @hw: pointer to the HW structure 2334543534cSDong Yibo * @msg: the message buffer 2344543534cSDong Yibo * @size: length of buffer 2354543534cSDong Yibo * 2364543534cSDong Yibo * Return: 0 if it successfully received a message notification and 2374543534cSDong Yibo * copied it into the receive buffer, negative errno on failure 2384543534cSDong Yibo **/ 2394543534cSDong Yibo int mucse_poll_and_read_mbx(struct mucse_hw *hw, u32 *msg, u16 size) 2404543534cSDong Yibo { 2414543534cSDong Yibo int err; 2424543534cSDong Yibo 2434543534cSDong Yibo err = mucse_poll_for_msg(hw); 2444543534cSDong Yibo if (err) 2454543534cSDong Yibo return err; 2464543534cSDong Yibo 2474543534cSDong Yibo return mucse_read_mbx_pf(hw, msg, size); 2484543534cSDong Yibo } 2494543534cSDong Yibo 2504543534cSDong Yibo /** 2514543534cSDong Yibo * mucse_mbx_get_fwack - Read fw ack from reg 2524543534cSDong Yibo * @mbx: pointer to the MBX structure 2534543534cSDong Yibo * 2544543534cSDong Yibo * Return: the fwack value 2554543534cSDong Yibo **/ 2564543534cSDong Yibo static u16 mucse_mbx_get_fwack(struct mucse_mbx_info *mbx) 2574543534cSDong Yibo { 2584543534cSDong Yibo u32 val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT); 2594543534cSDong Yibo 2604543534cSDong Yibo return FIELD_GET(GENMASK_U32(31, 16), val); 2614543534cSDong Yibo } 2624543534cSDong Yibo 2634543534cSDong Yibo /** 2644543534cSDong Yibo * mucse_mbx_inc_pf_req - Increase req 2654543534cSDong Yibo * @hw: pointer to the HW structure 2664543534cSDong Yibo * 2674543534cSDong Yibo * mucse_mbx_inc_pf_req reads pf_req from hw, then writes 2684543534cSDong Yibo * new value back after increase 2694543534cSDong Yibo **/ 2704543534cSDong Yibo static void mucse_mbx_inc_pf_req(struct mucse_hw *hw) 2714543534cSDong Yibo { 2724543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 2734543534cSDong Yibo u16 req; 2744543534cSDong Yibo u32 val; 2754543534cSDong Yibo 2764543534cSDong Yibo val = mbx_data_rd32(mbx, MUCSE_MBX_PF2FW_CNT); 2774543534cSDong Yibo req = FIELD_GET(GENMASK_U32(15, 0), val); 2784543534cSDong Yibo req++; 2794543534cSDong Yibo val &= ~GENMASK_U32(15, 0); 2804543534cSDong Yibo val |= FIELD_PREP(GENMASK_U32(15, 0), req); 2814543534cSDong Yibo mbx_data_wr32(mbx, MUCSE_MBX_PF2FW_CNT, val); 2824543534cSDong Yibo } 2834543534cSDong Yibo 2844543534cSDong Yibo /** 2854543534cSDong Yibo * mucse_write_mbx_pf - Place a message in the mailbox 2864543534cSDong Yibo * @hw: pointer to the HW structure 2874543534cSDong Yibo * @msg: the message buffer 2884543534cSDong Yibo * @size: length of buffer 2894543534cSDong Yibo * 2904543534cSDong Yibo * Return: 0 if it successfully copied message into the buffer, 2914543534cSDong Yibo * negative errno on failure 2924543534cSDong Yibo **/ 2934543534cSDong Yibo static int mucse_write_mbx_pf(struct mucse_hw *hw, u32 *msg, u16 size) 2944543534cSDong Yibo { 2954543534cSDong Yibo const int size_in_words = size / sizeof(u32); 2964543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 2974543534cSDong Yibo int err; 2984543534cSDong Yibo 2994543534cSDong Yibo err = mucse_obtain_mbx_lock_pf(hw); 3004543534cSDong Yibo if (err) 3014543534cSDong Yibo return err; 3024543534cSDong Yibo 3034543534cSDong Yibo for (int i = 0; i < size_in_words; i++) 3044543534cSDong Yibo mbx_data_wr32(mbx, MUCSE_MBX_FWPF_SHM + i * 4, msg[i]); 3054543534cSDong Yibo 3064543534cSDong Yibo /* flush acks as we are overwriting the message buffer */ 3074543534cSDong Yibo hw->mbx.fw_ack = mucse_mbx_get_fwack(mbx); 3084543534cSDong Yibo mucse_mbx_inc_pf_req(hw); 3094543534cSDong Yibo mucse_release_mbx_lock_pf(hw, true); 3104543534cSDong Yibo 3114543534cSDong Yibo return 0; 3124543534cSDong Yibo } 3134543534cSDong Yibo 3144543534cSDong Yibo /** 3154543534cSDong Yibo * mucse_check_for_ack_pf - Check to see if the fw has ACKed 3164543534cSDong Yibo * @hw: pointer to the HW structure 3174543534cSDong Yibo * 3184543534cSDong Yibo * Return: 0 if the fw has set the Status bit or else -EIO 3194543534cSDong Yibo **/ 3204543534cSDong Yibo static int mucse_check_for_ack_pf(struct mucse_hw *hw) 3214543534cSDong Yibo { 3224543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 3234543534cSDong Yibo u16 fw_ack; 3244543534cSDong Yibo 3254543534cSDong Yibo fw_ack = mucse_mbx_get_fwack(mbx); 3264543534cSDong Yibo /* chip's register is reset to 0 when rc send reset 3274543534cSDong Yibo * mbx command. Return -EIO if in this state, others 3284543534cSDong Yibo * fw_ack == hw->mbx.fw_ack means no new ack. 3294543534cSDong Yibo **/ 3304543534cSDong Yibo if (fw_ack == 0 || fw_ack == hw->mbx.fw_ack) 3314543534cSDong Yibo return -EIO; 3324543534cSDong Yibo 3334543534cSDong Yibo return 0; 3344543534cSDong Yibo } 3354543534cSDong Yibo 3364543534cSDong Yibo /** 3374543534cSDong Yibo * mucse_poll_for_ack - Wait for message acknowledgment 3384543534cSDong Yibo * @hw: pointer to the HW structure 3394543534cSDong Yibo * 3404543534cSDong Yibo * Return: 0 if it successfully received a message acknowledgment, 3414543534cSDong Yibo * else negative errno 3424543534cSDong Yibo **/ 3434543534cSDong Yibo static int mucse_poll_for_ack(struct mucse_hw *hw) 3444543534cSDong Yibo { 3454543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 3464543534cSDong Yibo int val; 3474543534cSDong Yibo 3484543534cSDong Yibo return read_poll_timeout(mucse_check_for_ack_pf, 3494543534cSDong Yibo val, !val, mbx->delay_us, 3504543534cSDong Yibo mbx->timeout_us, 3514543534cSDong Yibo false, hw); 3524543534cSDong Yibo } 3534543534cSDong Yibo 3544543534cSDong Yibo /** 3554543534cSDong Yibo * mucse_write_and_wait_ack_mbx - Write a message to the mailbox, wait for ack 3564543534cSDong Yibo * @hw: pointer to the HW structure 3574543534cSDong Yibo * @msg: the message buffer 3584543534cSDong Yibo * @size: length of buffer 3594543534cSDong Yibo * 3604543534cSDong Yibo * Return: 0 if it successfully copied message into the buffer and 3614543534cSDong Yibo * received an ack to that message within delay * timeout_cnt period 3624543534cSDong Yibo **/ 3634543534cSDong Yibo int mucse_write_and_wait_ack_mbx(struct mucse_hw *hw, u32 *msg, u16 size) 3644543534cSDong Yibo { 3654543534cSDong Yibo int err; 3664543534cSDong Yibo 3674543534cSDong Yibo err = mucse_write_mbx_pf(hw, msg, size); 3684543534cSDong Yibo if (err) 3694543534cSDong Yibo return err; 3704543534cSDong Yibo 3714543534cSDong Yibo return mucse_poll_for_ack(hw); 3724543534cSDong Yibo } 3734543534cSDong Yibo 3744543534cSDong Yibo /** 3754543534cSDong Yibo * mucse_mbx_reset - Reset mbx info, sync info from regs 3764543534cSDong Yibo * @hw: pointer to the HW structure 3774543534cSDong Yibo * 3784543534cSDong Yibo * mucse_mbx_reset resets all mbx variables to default. 3794543534cSDong Yibo **/ 3804543534cSDong Yibo static void mucse_mbx_reset(struct mucse_hw *hw) 3814543534cSDong Yibo { 3824543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 3834543534cSDong Yibo u32 val; 3844543534cSDong Yibo 3854543534cSDong Yibo val = mbx_data_rd32(mbx, MUCSE_MBX_FW2PF_CNT); 3864543534cSDong Yibo hw->mbx.fw_req = FIELD_GET(GENMASK_U32(15, 0), val); 3874543534cSDong Yibo hw->mbx.fw_ack = FIELD_GET(GENMASK_U32(31, 16), val); 3884543534cSDong Yibo mbx_ctrl_wr32(mbx, MUCSE_MBX_PF2FW_CTRL(mbx), 0); 3894543534cSDong Yibo mbx_ctrl_wr32(mbx, MUCSE_MBX_FWPF_MASK(mbx), GENMASK_U32(31, 16)); 3904543534cSDong Yibo } 3914543534cSDong Yibo 3924543534cSDong Yibo /** 3934543534cSDong Yibo * mucse_init_mbx_params_pf - Set initial values for pf mailbox 3944543534cSDong Yibo * @hw: pointer to the HW structure 3954543534cSDong Yibo * 3964543534cSDong Yibo * Initializes the hw->mbx struct to correct values for pf mailbox 3974543534cSDong Yibo */ 3984543534cSDong Yibo void mucse_init_mbx_params_pf(struct mucse_hw *hw) 3994543534cSDong Yibo { 4004543534cSDong Yibo struct mucse_mbx_info *mbx = &hw->mbx; 4014543534cSDong Yibo 4024543534cSDong Yibo mbx->delay_us = 100; 4034543534cSDong Yibo mbx->timeout_us = 4 * USEC_PER_SEC; 404*c6d3f019SDong Yibo mutex_init(&mbx->lock); 4054543534cSDong Yibo mucse_mbx_reset(hw); 4064543534cSDong Yibo } 407