18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Intel MAX 10 BMC HWMON Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/device.h> 98c2ecf20Sopenharmony_ci#include <linux/hwmon.h> 108c2ecf20Sopenharmony_ci#include <linux/mfd/intel-m10-bmc.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 138c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistruct m10bmc_sdata { 168c2ecf20Sopenharmony_ci unsigned int reg_input; 178c2ecf20Sopenharmony_ci unsigned int reg_max; 188c2ecf20Sopenharmony_ci unsigned int reg_crit; 198c2ecf20Sopenharmony_ci unsigned int reg_hyst; 208c2ecf20Sopenharmony_ci unsigned int reg_min; 218c2ecf20Sopenharmony_ci unsigned int multiplier; 228c2ecf20Sopenharmony_ci const char *label; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct m10bmc_hwmon_board_data { 268c2ecf20Sopenharmony_ci const struct m10bmc_sdata *tables[hwmon_max]; 278c2ecf20Sopenharmony_ci const struct hwmon_channel_info **hinfo; 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct m10bmc_hwmon { 318c2ecf20Sopenharmony_ci struct device *dev; 328c2ecf20Sopenharmony_ci struct hwmon_chip_info chip; 338c2ecf20Sopenharmony_ci char *hw_name; 348c2ecf20Sopenharmony_ci struct intel_m10bmc *m10bmc; 358c2ecf20Sopenharmony_ci const struct m10bmc_hwmon_board_data *bdata; 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic const struct m10bmc_sdata n3000bmc_temp_tbl[] = { 398c2ecf20Sopenharmony_ci { 0x100, 0x104, 0x108, 0x10c, 0x0, 500, "Board Temperature" }, 408c2ecf20Sopenharmony_ci { 0x110, 0x114, 0x118, 0x0, 0x0, 500, "FPGA Die Temperature" }, 418c2ecf20Sopenharmony_ci { 0x11c, 0x124, 0x120, 0x0, 0x0, 500, "QSFP0 Temperature" }, 428c2ecf20Sopenharmony_ci { 0x12c, 0x134, 0x130, 0x0, 0x0, 500, "QSFP1 Temperature" }, 438c2ecf20Sopenharmony_ci { 0x168, 0x0, 0x0, 0x0, 0x0, 500, "Retimer A Temperature" }, 448c2ecf20Sopenharmony_ci { 0x16c, 0x0, 0x0, 0x0, 0x0, 500, "Retimer A SerDes Temperature" }, 458c2ecf20Sopenharmony_ci { 0x170, 0x0, 0x0, 0x0, 0x0, 500, "Retimer B Temperature" }, 468c2ecf20Sopenharmony_ci { 0x174, 0x0, 0x0, 0x0, 0x0, 500, "Retimer B SerDes Temperature" }, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic const struct m10bmc_sdata n3000bmc_in_tbl[] = { 508c2ecf20Sopenharmony_ci { 0x128, 0x0, 0x0, 0x0, 0x0, 1, "QSFP0 Supply Voltage" }, 518c2ecf20Sopenharmony_ci { 0x138, 0x0, 0x0, 0x0, 0x0, 1, "QSFP1 Supply Voltage" }, 528c2ecf20Sopenharmony_ci { 0x13c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Voltage" }, 538c2ecf20Sopenharmony_ci { 0x144, 0x0, 0x0, 0x0, 0x0, 1, "12V Backplane Voltage" }, 548c2ecf20Sopenharmony_ci { 0x14c, 0x0, 0x0, 0x0, 0x0, 1, "1.2V Voltage" }, 558c2ecf20Sopenharmony_ci { 0x150, 0x0, 0x0, 0x0, 0x0, 1, "12V AUX Voltage" }, 568c2ecf20Sopenharmony_ci { 0x158, 0x0, 0x0, 0x0, 0x0, 1, "1.8V Voltage" }, 578c2ecf20Sopenharmony_ci { 0x15c, 0x0, 0x0, 0x0, 0x0, 1, "3.3V Voltage" }, 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic const struct m10bmc_sdata n3000bmc_curr_tbl[] = { 618c2ecf20Sopenharmony_ci { 0x140, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Current" }, 628c2ecf20Sopenharmony_ci { 0x148, 0x0, 0x0, 0x0, 0x0, 1, "12V Backplane Current" }, 638c2ecf20Sopenharmony_ci { 0x154, 0x0, 0x0, 0x0, 0x0, 1, "12V AUX Current" }, 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic const struct m10bmc_sdata n3000bmc_power_tbl[] = { 678c2ecf20Sopenharmony_ci { 0x160, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" }, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic const struct hwmon_channel_info *n3000bmc_hinfo[] = { 718c2ecf20Sopenharmony_ci HWMON_CHANNEL_INFO(temp, 728c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | 738c2ecf20Sopenharmony_ci HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL, 748c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | 758c2ecf20Sopenharmony_ci HWMON_T_LABEL, 768c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | 778c2ecf20Sopenharmony_ci HWMON_T_LABEL, 788c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | 798c2ecf20Sopenharmony_ci HWMON_T_LABEL, 808c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_LABEL, 818c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_LABEL, 828c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_LABEL, 838c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_LABEL), 848c2ecf20Sopenharmony_ci HWMON_CHANNEL_INFO(in, 858c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 868c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 878c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 888c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 898c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 908c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 918c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL, 928c2ecf20Sopenharmony_ci HWMON_I_INPUT | HWMON_I_LABEL), 938c2ecf20Sopenharmony_ci HWMON_CHANNEL_INFO(curr, 948c2ecf20Sopenharmony_ci HWMON_C_INPUT | HWMON_C_LABEL, 958c2ecf20Sopenharmony_ci HWMON_C_INPUT | HWMON_C_LABEL, 968c2ecf20Sopenharmony_ci HWMON_C_INPUT | HWMON_C_LABEL), 978c2ecf20Sopenharmony_ci HWMON_CHANNEL_INFO(power, 988c2ecf20Sopenharmony_ci HWMON_P_INPUT | HWMON_P_LABEL), 998c2ecf20Sopenharmony_ci NULL 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic const struct m10bmc_hwmon_board_data n3000bmc_hwmon_bdata = { 1038c2ecf20Sopenharmony_ci .tables = { 1048c2ecf20Sopenharmony_ci [hwmon_temp] = n3000bmc_temp_tbl, 1058c2ecf20Sopenharmony_ci [hwmon_in] = n3000bmc_in_tbl, 1068c2ecf20Sopenharmony_ci [hwmon_curr] = n3000bmc_curr_tbl, 1078c2ecf20Sopenharmony_ci [hwmon_power] = n3000bmc_power_tbl, 1088c2ecf20Sopenharmony_ci }, 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci .hinfo = n3000bmc_hinfo, 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic umode_t 1148c2ecf20Sopenharmony_cim10bmc_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, 1158c2ecf20Sopenharmony_ci u32 attr, int channel) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci return 0444; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic const struct m10bmc_sdata * 1218c2ecf20Sopenharmony_cifind_sensor_data(struct m10bmc_hwmon *hw, enum hwmon_sensor_types type, 1228c2ecf20Sopenharmony_ci int channel) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci const struct m10bmc_sdata *tbl; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci tbl = hw->bdata->tables[type]; 1278c2ecf20Sopenharmony_ci if (!tbl) 1288c2ecf20Sopenharmony_ci return ERR_PTR(-EOPNOTSUPP); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci return &tbl[channel]; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic int do_sensor_read(struct m10bmc_hwmon *hw, 1348c2ecf20Sopenharmony_ci const struct m10bmc_sdata *data, 1358c2ecf20Sopenharmony_ci unsigned int regoff, long *val) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci unsigned int regval; 1388c2ecf20Sopenharmony_ci int ret; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci ret = m10bmc_sys_read(hw->m10bmc, regoff, ®val); 1418c2ecf20Sopenharmony_ci if (ret) 1428c2ecf20Sopenharmony_ci return ret; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * BMC Firmware will return 0xdeadbeef if the sensor value is invalid 1468c2ecf20Sopenharmony_ci * at that time. This usually happens on sensor channels which connect 1478c2ecf20Sopenharmony_ci * to external pluggable modules, e.g. QSFP temperature and voltage. 1488c2ecf20Sopenharmony_ci * When the QSFP is unplugged from cage, driver will get 0xdeadbeef 1498c2ecf20Sopenharmony_ci * from their registers. 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci if (regval == 0xdeadbeef) 1528c2ecf20Sopenharmony_ci return -ENODATA; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci *val = regval * data->multiplier; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic int m10bmc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 1608c2ecf20Sopenharmony_ci u32 attr, int channel, long *val) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci struct m10bmc_hwmon *hw = dev_get_drvdata(dev); 1638c2ecf20Sopenharmony_ci unsigned int reg = 0, reg_hyst = 0; 1648c2ecf20Sopenharmony_ci const struct m10bmc_sdata *data; 1658c2ecf20Sopenharmony_ci long hyst, value; 1668c2ecf20Sopenharmony_ci int ret; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci data = find_sensor_data(hw, type, channel); 1698c2ecf20Sopenharmony_ci if (IS_ERR(data)) 1708c2ecf20Sopenharmony_ci return PTR_ERR(data); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci switch (type) { 1738c2ecf20Sopenharmony_ci case hwmon_temp: 1748c2ecf20Sopenharmony_ci switch (attr) { 1758c2ecf20Sopenharmony_ci case hwmon_temp_input: 1768c2ecf20Sopenharmony_ci reg = data->reg_input; 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci case hwmon_temp_max_hyst: 1798c2ecf20Sopenharmony_ci reg_hyst = data->reg_hyst; 1808c2ecf20Sopenharmony_ci fallthrough; 1818c2ecf20Sopenharmony_ci case hwmon_temp_max: 1828c2ecf20Sopenharmony_ci reg = data->reg_max; 1838c2ecf20Sopenharmony_ci break; 1848c2ecf20Sopenharmony_ci case hwmon_temp_crit_hyst: 1858c2ecf20Sopenharmony_ci reg_hyst = data->reg_hyst; 1868c2ecf20Sopenharmony_ci fallthrough; 1878c2ecf20Sopenharmony_ci case hwmon_temp_crit: 1888c2ecf20Sopenharmony_ci reg = data->reg_crit; 1898c2ecf20Sopenharmony_ci break; 1908c2ecf20Sopenharmony_ci default: 1918c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci case hwmon_in: 1958c2ecf20Sopenharmony_ci switch (attr) { 1968c2ecf20Sopenharmony_ci case hwmon_in_input: 1978c2ecf20Sopenharmony_ci reg = data->reg_input; 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci case hwmon_in_max: 2008c2ecf20Sopenharmony_ci reg = data->reg_max; 2018c2ecf20Sopenharmony_ci break; 2028c2ecf20Sopenharmony_ci case hwmon_in_crit: 2038c2ecf20Sopenharmony_ci reg = data->reg_crit; 2048c2ecf20Sopenharmony_ci break; 2058c2ecf20Sopenharmony_ci case hwmon_in_min: 2068c2ecf20Sopenharmony_ci reg = data->reg_min; 2078c2ecf20Sopenharmony_ci break; 2088c2ecf20Sopenharmony_ci default: 2098c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci case hwmon_curr: 2138c2ecf20Sopenharmony_ci switch (attr) { 2148c2ecf20Sopenharmony_ci case hwmon_curr_input: 2158c2ecf20Sopenharmony_ci reg = data->reg_input; 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci case hwmon_curr_max: 2188c2ecf20Sopenharmony_ci reg = data->reg_max; 2198c2ecf20Sopenharmony_ci break; 2208c2ecf20Sopenharmony_ci case hwmon_curr_crit: 2218c2ecf20Sopenharmony_ci reg = data->reg_crit; 2228c2ecf20Sopenharmony_ci break; 2238c2ecf20Sopenharmony_ci default: 2248c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci break; 2278c2ecf20Sopenharmony_ci case hwmon_power: 2288c2ecf20Sopenharmony_ci switch (attr) { 2298c2ecf20Sopenharmony_ci case hwmon_power_input: 2308c2ecf20Sopenharmony_ci reg = data->reg_input; 2318c2ecf20Sopenharmony_ci break; 2328c2ecf20Sopenharmony_ci default: 2338c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci default: 2378c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (!reg) 2418c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci ret = do_sensor_read(hw, data, reg, &value); 2448c2ecf20Sopenharmony_ci if (ret) 2458c2ecf20Sopenharmony_ci return ret; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (reg_hyst) { 2488c2ecf20Sopenharmony_ci ret = do_sensor_read(hw, data, reg_hyst, &hyst); 2498c2ecf20Sopenharmony_ci if (ret) 2508c2ecf20Sopenharmony_ci return ret; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci value -= hyst; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci *val = value; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci return 0; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int m10bmc_hwmon_read_string(struct device *dev, 2618c2ecf20Sopenharmony_ci enum hwmon_sensor_types type, 2628c2ecf20Sopenharmony_ci u32 attr, int channel, const char **str) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci struct m10bmc_hwmon *hw = dev_get_drvdata(dev); 2658c2ecf20Sopenharmony_ci const struct m10bmc_sdata *data; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci data = find_sensor_data(hw, type, channel); 2688c2ecf20Sopenharmony_ci if (IS_ERR(data)) 2698c2ecf20Sopenharmony_ci return PTR_ERR(data); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci *str = data->label; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci return 0; 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic const struct hwmon_ops m10bmc_hwmon_ops = { 2778c2ecf20Sopenharmony_ci .is_visible = m10bmc_hwmon_is_visible, 2788c2ecf20Sopenharmony_ci .read = m10bmc_hwmon_read, 2798c2ecf20Sopenharmony_ci .read_string = m10bmc_hwmon_read_string, 2808c2ecf20Sopenharmony_ci}; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int m10bmc_hwmon_probe(struct platform_device *pdev) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci const struct platform_device_id *id = platform_get_device_id(pdev); 2858c2ecf20Sopenharmony_ci struct intel_m10bmc *m10bmc = dev_get_drvdata(pdev->dev.parent); 2868c2ecf20Sopenharmony_ci struct device *hwmon_dev, *dev = &pdev->dev; 2878c2ecf20Sopenharmony_ci struct m10bmc_hwmon *hw; 2888c2ecf20Sopenharmony_ci int i; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); 2918c2ecf20Sopenharmony_ci if (!hw) 2928c2ecf20Sopenharmony_ci return -ENOMEM; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci hw->dev = dev; 2958c2ecf20Sopenharmony_ci hw->m10bmc = m10bmc; 2968c2ecf20Sopenharmony_ci hw->bdata = (const struct m10bmc_hwmon_board_data *)id->driver_data; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci hw->chip.info = hw->bdata->hinfo; 2998c2ecf20Sopenharmony_ci hw->chip.ops = &m10bmc_hwmon_ops; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci hw->hw_name = devm_kstrdup(dev, id->name, GFP_KERNEL); 3028c2ecf20Sopenharmony_ci if (!hw->hw_name) 3038c2ecf20Sopenharmony_ci return -ENOMEM; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci for (i = 0; hw->hw_name[i]; i++) 3068c2ecf20Sopenharmony_ci if (hwmon_is_bad_char(hw->hw_name[i])) 3078c2ecf20Sopenharmony_ci hw->hw_name[i] = '_'; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci hwmon_dev = devm_hwmon_device_register_with_info(dev, hw->hw_name, 3108c2ecf20Sopenharmony_ci hw, &hw->chip, NULL); 3118c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(hwmon_dev); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic const struct platform_device_id intel_m10bmc_hwmon_ids[] = { 3158c2ecf20Sopenharmony_ci { 3168c2ecf20Sopenharmony_ci .name = "n3000bmc-hwmon", 3178c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&n3000bmc_hwmon_bdata, 3188c2ecf20Sopenharmony_ci }, 3198c2ecf20Sopenharmony_ci { } 3208c2ecf20Sopenharmony_ci}; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic struct platform_driver intel_m10bmc_hwmon_driver = { 3238c2ecf20Sopenharmony_ci .probe = m10bmc_hwmon_probe, 3248c2ecf20Sopenharmony_ci .driver = { 3258c2ecf20Sopenharmony_ci .name = "intel-m10-bmc-hwmon", 3268c2ecf20Sopenharmony_ci }, 3278c2ecf20Sopenharmony_ci .id_table = intel_m10bmc_hwmon_ids, 3288c2ecf20Sopenharmony_ci}; 3298c2ecf20Sopenharmony_cimodule_platform_driver(intel_m10bmc_hwmon_driver); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, intel_m10bmc_hwmon_ids); 3328c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel Corporation"); 3338c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel MAX 10 BMC hardware monitor"); 3348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 335