-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local utils = require 'mc.utils'

local tesla_t4 = {
    protocol_dependencies = { smbus_postbox = { ref_chip = nil, buffer_len = 32, data_reg_addr = 0x5d } },
    properties = {
        Capability0 = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 60,
            request = {
                name = 'Capability0',
                opcode = 0x1,
                capa_mask = 0x00000000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                arg1 = 0,
                arg2 = 0,
                capa_dword_num = 0,
                data_mask = 0xffffffff
            },
            response = function(data)
                return data
            end
        },
        Capability1 = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 60,
            request = {
                name = 'Capability1',
                opcode = 0x1,
                capa_mask = 0x00000000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                arg1 = 1,
                arg2 = 0,
                capa_dword_num = 1,
                data_mask = 0xffffffff
            },
            response = function(data)
                return data
            end
        },
        Capability2 = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 60,
            request = {
                name = 'Capability2',
                opcode = 0x1,
                capa_mask = 0x00000000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                arg1 = 2,
                arg2 = 0,
                capa_dword_num = 2,
                data_mask = 0xffffffff
            },
            response = function(data)
                return data
            end
        },
        Capability3 = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 60,
            request = {
                name = 'Capability3',
                opcode = 0x1,
                capa_mask = 0x00000000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                arg1 = 3,
                arg2 = 0,
                capa_dword_num = 3,
                data_mask = 0xffffffff
            },
            response = function(data)
                return data
            end
        },
        InfoRomVersion = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardInfoRomVersion',
                opcode = 0x5,
                arg1 = 0xe,
                capa_dword_num = 1,
                capa_mask = 0x00004000,
                data_out = 1,
                data_len = 16,
                data_type = 1
            },
            response = function(data)
                return data
            end
        },
        BoardPartNumber = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardBoardPartNumber',
                opcode = 0x5,
                arg1 = 0x0,
                capa_dword_num = 1,
                capa_mask = 0x00000001,
                data_out = 1,
                data_len = 24,
                data_type = 1
            },
            response = function(data)
                return data
            end
        },
        MemoryVendor = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardMemoryVendor',
                opcode = 0x5,
                arg1 = 0x5,
                capa_dword_num = 1,
                capa_mask = 0x00000020,
                data_out = 1,
                data_len = 1,
                data_type = 1
            },
            response = function(data)
                if data:sub(1, 1) == 'H' then
                    return 'Hynix'
                elseif data:sub(1, 1) == 'S' then
                    return 'Samsung'
                end
                return ''
            end
        },
        MemoryPartNumber = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardMemoryPartNumber',
                opcode = 0x5,
                arg1 = 0x6,
                capa_dword_num = 1,
                capa_mask = 0x00000040,
                data_out = 1,
                data_len = 20,
                data_type = 1
            },
            response = function(data)
                return data
            end
        },
        BuildDate = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardBuildDate',
                opcode = 0x5,
                arg1 = 0x7,
                capa_dword_num = 1,
                capa_mask = 0x00000080,
                data_out = 1,
                data_len = 4,
                data_type = 3
            },
            response = function(data)
                return data
            end
        },
        UUID = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardUUID',
                opcode = 0x5,
                arg1 = 0xd,
                capa_dword_num = 1,
                capa_mask = 0x00002000,
                data_out = 1,
                data_len = 16,
                data_type = 2
            },
            response = function(data)
                return string.format('GPU-%s-%s-%s-%s-%s',
                    string.sub(data, 1, 8), string.sub(data, 9, 12),
                    string.sub(data, 13, 16), string.sub(data, 17, 20), string.sub(data, 21, 32))
            end
        },
        FirmwareVersion = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardFirmVer',
                opcode = 0x5,
                arg1 = 0x8,
                capa_dword_num = 1,
                capa_mask = 0x00000100,
                data_out = 1,
                data_len = 14,
                data_type = 1
            },
            response = function(data)
                return data
            end
        },
        SN = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardSN',
                opcode = 0x5,
                arg1 = 0x2,
                capa_dword_num = 1,
                capa_mask = 0x00000004,
                data_out = 1,
                data_len = 16,
                data_type = 1
            },
            response = function(data)
                return data
            end
        },
        PartNumber = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 10,
            request = {
                name = 'CardGPUPartNumber',
                opcode = 0x5,
                arg1 = 0x4,
                capa_dword_num = 1,
                capa_mask = 0x00000010,
                data_out = 1,
                data_len = 16,
                data_type = 1
            },
            response = function(data)
                return data
            end
        },
        -- 依赖驱动
        PowerWatts = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardPower',
                opcode = 0x4,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 0,
                capa_mask = 0x00010000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                data_mask = 0xffffffff
            },
            response = function(data)
                return tonumber(data) // 1000
            end
        },
        PowerBrakeSet = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardPowerBrakeIsSet',
                opcode = 0xF5,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 3,
                capa_mask = 0x00000020,
                data_out = 1,
                data_len = 1,
                data_type = 0,
                data_mask = 0x01
            },
            response = function(data)
                return tonumber(data)
            end
        },
        -- 依赖驱动
        ExternalPowerSufficient = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardSufficientExternalPower',
                opcode = 0x12,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 0,
                capa_mask = 0x00010000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                data_mask = 0x01
            },
            response = function(data)
                return tonumber(data)
            end
        },
        ECCModeEnabled = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardECCModeEnabled',
                opcode = 0x18,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 1,
                capa_mask = 0x00800000,
                data_out = 1,
                data_len = 1,
                data_type = 0,
                data_mask = 0x01
            },
            response = function(data)
                return tonumber(data)
            end
        },
        ECCModePendingEnabled = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardECCModePendingEnabled',
                opcode = 0x18,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 1,
                capa_mask = 0x00800000,
                data_out = 1,
                data_len = 1,
                data_type = 0,
                data_mask = 0x04
            },
            response = function(data)
                return tonumber(data)
            end
        },
        ResetRequired = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardGPUResetRequired',
                opcode = 0x18,
                arg1 = 0x1,
                arg2 = 0x0,
                capa_dword_num = 1,
                capa_mask = 0x01000000,
                data_out = 1,
                data_len = 1,
                data_type = 0,
                data_mask = 0x01
            },
            response = function(data)
                return tonumber(data)
            end
        },
        RetiredPage = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardRetiredPage',
                opcode = 0x13,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 1,
                capa_mask = 0x00080000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                data_mask = 0x0000ffff
            },
            response = function(data)
                return tonumber(data)
            end
        },
        NvLinkNum = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardNvLinkNum',
                opcode = 0x1A,
                arg1 = 0x0,
                arg2 = 0x0,
                capa_dword_num = 1,
                capa_mask = 0x04000000,
                data_out = 1,
                data_len = 4,
                data_type = 0,
                data_mask = 0xffffffff
            },
            response = function(data)
                return tonumber(data)
            end
        },
        NvLinkInfo = {
            protocol = 'smbus_postbox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                name = 'CardNvLinkStatus',
                opcode = 0x1A,
                arg1 = 0x1,
                capa_dword_num = 1,
                capa_mask = 0x04000000,
                data_out = 1,
                ex_data_out = 0,
                data_len = 1,
                data_type = 4
            },
            response = function(data)
                local result = {}
                for _, v in pairs(data) do
                    if v == 1 then
                        table.insert(result, 'Up')
                    elseif v == 0 then
                        table.insert(result, 'Down')
                    end
                end
                return result
            end
        }
    }
}

return {
    smbus_postbox = function(ref_chip)
        local obj = utils.table_copy(tesla_t4)
        obj.protocol_dependencies.smbus_postbox.ref_chip = ref_chip
        return obj
    end
}