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, &regval);
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