xref: /linux/drivers/hwmon/sg2042-mcu.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1*758b62e5SInochi Amaoto // SPDX-License-Identifier: GPL-2.0-only
2*758b62e5SInochi Amaoto /*
3*758b62e5SInochi Amaoto  * Copyright (c) 2024 Inochi Amaoto <inochiama@outlook.com>
4*758b62e5SInochi Amaoto  *
5*758b62e5SInochi Amaoto  * Sophgo power control mcu for SG2042
6*758b62e5SInochi Amaoto  */
7*758b62e5SInochi Amaoto 
8*758b62e5SInochi Amaoto #include <linux/cleanup.h>
9*758b62e5SInochi Amaoto #include <linux/debugfs.h>
10*758b62e5SInochi Amaoto #include <linux/err.h>
11*758b62e5SInochi Amaoto #include <linux/hwmon.h>
12*758b62e5SInochi Amaoto #include <linux/i2c.h>
13*758b62e5SInochi Amaoto #include <linux/kernel.h>
14*758b62e5SInochi Amaoto #include <linux/module.h>
15*758b62e5SInochi Amaoto #include <linux/mutex.h>
16*758b62e5SInochi Amaoto 
17*758b62e5SInochi Amaoto /* fixed MCU registers */
18*758b62e5SInochi Amaoto #define REG_BOARD_TYPE				0x00
19*758b62e5SInochi Amaoto #define REG_MCU_FIRMWARE_VERSION		0x01
20*758b62e5SInochi Amaoto #define REG_PCB_VERSION				0x02
21*758b62e5SInochi Amaoto #define REG_PWR_CTRL				0x03
22*758b62e5SInochi Amaoto #define REG_SOC_TEMP				0x04
23*758b62e5SInochi Amaoto #define REG_BOARD_TEMP				0x05
24*758b62e5SInochi Amaoto #define REG_RST_COUNT				0x0a
25*758b62e5SInochi Amaoto #define REG_UPTIME				0x0b
26*758b62e5SInochi Amaoto #define REG_RESET_REASON			0x0d
27*758b62e5SInochi Amaoto #define REG_MCU_TYPE				0x18
28*758b62e5SInochi Amaoto #define REG_REPOWER_POLICY			0x65
29*758b62e5SInochi Amaoto #define REG_CRITICAL_TEMP			0x66
30*758b62e5SInochi Amaoto #define REG_REPOWER_TEMP			0x67
31*758b62e5SInochi Amaoto 
32*758b62e5SInochi Amaoto #define REPOWER_POLICY_REBOOT			1
33*758b62e5SInochi Amaoto #define REPOWER_POLICY_KEEP_OFF			2
34*758b62e5SInochi Amaoto 
35*758b62e5SInochi Amaoto #define MCU_POWER_MAX				0xff
36*758b62e5SInochi Amaoto 
37*758b62e5SInochi Amaoto #define DEFINE_MCU_DEBUG_ATTR(_name, _reg, _format)			\
38*758b62e5SInochi Amaoto 	static int _name##_show(struct seq_file *seqf,			\
39*758b62e5SInochi Amaoto 				    void *unused)			\
40*758b62e5SInochi Amaoto 	{								\
41*758b62e5SInochi Amaoto 		struct sg2042_mcu_data *mcu = seqf->private;		\
42*758b62e5SInochi Amaoto 		int ret;						\
43*758b62e5SInochi Amaoto 		ret = i2c_smbus_read_byte_data(mcu->client, (_reg));	\
44*758b62e5SInochi Amaoto 		if (ret < 0)						\
45*758b62e5SInochi Amaoto 			return ret;					\
46*758b62e5SInochi Amaoto 		seq_printf(seqf, _format "\n", ret);			\
47*758b62e5SInochi Amaoto 		return 0;						\
48*758b62e5SInochi Amaoto 	}								\
49*758b62e5SInochi Amaoto 	DEFINE_SHOW_ATTRIBUTE(_name)					\
50*758b62e5SInochi Amaoto 
51*758b62e5SInochi Amaoto struct sg2042_mcu_data {
52*758b62e5SInochi Amaoto 	struct i2c_client	*client;
53*758b62e5SInochi Amaoto 	struct dentry		*debugfs;
54*758b62e5SInochi Amaoto 	struct mutex		mutex;
55*758b62e5SInochi Amaoto };
56*758b62e5SInochi Amaoto 
57*758b62e5SInochi Amaoto static struct dentry *sgmcu_debugfs;
58*758b62e5SInochi Amaoto 
reset_count_show(struct device * dev,struct device_attribute * attr,char * buf)59*758b62e5SInochi Amaoto static ssize_t reset_count_show(struct device *dev,
60*758b62e5SInochi Amaoto 				struct device_attribute *attr,
61*758b62e5SInochi Amaoto 				char *buf)
62*758b62e5SInochi Amaoto {
63*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
64*758b62e5SInochi Amaoto 	int ret;
65*758b62e5SInochi Amaoto 
66*758b62e5SInochi Amaoto 	ret = i2c_smbus_read_byte_data(mcu->client, REG_RST_COUNT);
67*758b62e5SInochi Amaoto 	if (ret < 0)
68*758b62e5SInochi Amaoto 		return ret;
69*758b62e5SInochi Amaoto 
70*758b62e5SInochi Amaoto 	return sprintf(buf, "%d\n", ret);
71*758b62e5SInochi Amaoto }
72*758b62e5SInochi Amaoto 
uptime_show(struct device * dev,struct device_attribute * attr,char * buf)73*758b62e5SInochi Amaoto static ssize_t uptime_show(struct device *dev,
74*758b62e5SInochi Amaoto 			   struct device_attribute *attr,
75*758b62e5SInochi Amaoto 			   char *buf)
76*758b62e5SInochi Amaoto {
77*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
78*758b62e5SInochi Amaoto 	u8 time_val[2];
79*758b62e5SInochi Amaoto 	int ret;
80*758b62e5SInochi Amaoto 
81*758b62e5SInochi Amaoto 	ret = i2c_smbus_read_i2c_block_data(mcu->client, REG_UPTIME,
82*758b62e5SInochi Amaoto 					    sizeof(time_val), time_val);
83*758b62e5SInochi Amaoto 	if (ret < 0)
84*758b62e5SInochi Amaoto 		return ret;
85*758b62e5SInochi Amaoto 
86*758b62e5SInochi Amaoto 	return sprintf(buf, "%d\n",
87*758b62e5SInochi Amaoto 		       (time_val[0]) | (time_val[1] << 8));
88*758b62e5SInochi Amaoto }
89*758b62e5SInochi Amaoto 
reset_reason_show(struct device * dev,struct device_attribute * attr,char * buf)90*758b62e5SInochi Amaoto static ssize_t reset_reason_show(struct device *dev,
91*758b62e5SInochi Amaoto 				 struct device_attribute *attr,
92*758b62e5SInochi Amaoto 				 char *buf)
93*758b62e5SInochi Amaoto {
94*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
95*758b62e5SInochi Amaoto 	int ret;
96*758b62e5SInochi Amaoto 
97*758b62e5SInochi Amaoto 	ret = i2c_smbus_read_byte_data(mcu->client, REG_RESET_REASON);
98*758b62e5SInochi Amaoto 	if (ret < 0)
99*758b62e5SInochi Amaoto 		return ret;
100*758b62e5SInochi Amaoto 
101*758b62e5SInochi Amaoto 	return sprintf(buf, "0x%02x\n", ret);
102*758b62e5SInochi Amaoto }
103*758b62e5SInochi Amaoto 
repower_policy_show(struct device * dev,struct device_attribute * attr,char * buf)104*758b62e5SInochi Amaoto static ssize_t repower_policy_show(struct device *dev,
105*758b62e5SInochi Amaoto 				   struct device_attribute *attr,
106*758b62e5SInochi Amaoto 				   char *buf)
107*758b62e5SInochi Amaoto {
108*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
109*758b62e5SInochi Amaoto 	int ret;
110*758b62e5SInochi Amaoto 	const char *action;
111*758b62e5SInochi Amaoto 
112*758b62e5SInochi Amaoto 	ret = i2c_smbus_read_byte_data(mcu->client, REG_REPOWER_POLICY);
113*758b62e5SInochi Amaoto 	if (ret < 0)
114*758b62e5SInochi Amaoto 		return ret;
115*758b62e5SInochi Amaoto 
116*758b62e5SInochi Amaoto 	if (ret == REPOWER_POLICY_REBOOT)
117*758b62e5SInochi Amaoto 		action = "repower";
118*758b62e5SInochi Amaoto 	else if (ret == REPOWER_POLICY_KEEP_OFF)
119*758b62e5SInochi Amaoto 		action = "keep";
120*758b62e5SInochi Amaoto 	else
121*758b62e5SInochi Amaoto 		action = "unknown";
122*758b62e5SInochi Amaoto 
123*758b62e5SInochi Amaoto 	return sprintf(buf, "%s\n", action);
124*758b62e5SInochi Amaoto }
125*758b62e5SInochi Amaoto 
repower_policy_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)126*758b62e5SInochi Amaoto static ssize_t repower_policy_store(struct device *dev,
127*758b62e5SInochi Amaoto 				    struct device_attribute *attr,
128*758b62e5SInochi Amaoto 				    const char *buf, size_t count)
129*758b62e5SInochi Amaoto {
130*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
131*758b62e5SInochi Amaoto 	u8 value;
132*758b62e5SInochi Amaoto 	int ret;
133*758b62e5SInochi Amaoto 
134*758b62e5SInochi Amaoto 	if (sysfs_streq("repower", buf))
135*758b62e5SInochi Amaoto 		value = REPOWER_POLICY_REBOOT;
136*758b62e5SInochi Amaoto 	else if (sysfs_streq("keep", buf))
137*758b62e5SInochi Amaoto 		value = REPOWER_POLICY_KEEP_OFF;
138*758b62e5SInochi Amaoto 	else
139*758b62e5SInochi Amaoto 		return -EINVAL;
140*758b62e5SInochi Amaoto 
141*758b62e5SInochi Amaoto 	ret = i2c_smbus_write_byte_data(mcu->client,
142*758b62e5SInochi Amaoto 					REG_REPOWER_POLICY, value);
143*758b62e5SInochi Amaoto 	if (ret < 0)
144*758b62e5SInochi Amaoto 		return ret;
145*758b62e5SInochi Amaoto 
146*758b62e5SInochi Amaoto 	return count;
147*758b62e5SInochi Amaoto }
148*758b62e5SInochi Amaoto 
149*758b62e5SInochi Amaoto static DEVICE_ATTR_RO(reset_count);
150*758b62e5SInochi Amaoto static DEVICE_ATTR_RO(uptime);
151*758b62e5SInochi Amaoto static DEVICE_ATTR_RO(reset_reason);
152*758b62e5SInochi Amaoto static DEVICE_ATTR_RW(repower_policy);
153*758b62e5SInochi Amaoto 
154*758b62e5SInochi Amaoto DEFINE_MCU_DEBUG_ATTR(firmware_version, REG_MCU_FIRMWARE_VERSION, "0x%02x");
155*758b62e5SInochi Amaoto DEFINE_MCU_DEBUG_ATTR(pcb_version, REG_PCB_VERSION, "0x%02x");
156*758b62e5SInochi Amaoto DEFINE_MCU_DEBUG_ATTR(board_type, REG_BOARD_TYPE, "0x%02x");
157*758b62e5SInochi Amaoto DEFINE_MCU_DEBUG_ATTR(mcu_type, REG_MCU_TYPE, "%d");
158*758b62e5SInochi Amaoto 
159*758b62e5SInochi Amaoto static struct attribute *sg2042_mcu_attrs[] = {
160*758b62e5SInochi Amaoto 	&dev_attr_reset_count.attr,
161*758b62e5SInochi Amaoto 	&dev_attr_uptime.attr,
162*758b62e5SInochi Amaoto 	&dev_attr_reset_reason.attr,
163*758b62e5SInochi Amaoto 	&dev_attr_repower_policy.attr,
164*758b62e5SInochi Amaoto 	NULL
165*758b62e5SInochi Amaoto };
166*758b62e5SInochi Amaoto 
167*758b62e5SInochi Amaoto static const struct attribute_group sg2042_mcu_attr_group = {
168*758b62e5SInochi Amaoto 	.attrs	= sg2042_mcu_attrs,
169*758b62e5SInochi Amaoto };
170*758b62e5SInochi Amaoto 
171*758b62e5SInochi Amaoto static const struct attribute_group *sg2042_mcu_groups[] = {
172*758b62e5SInochi Amaoto 	&sg2042_mcu_attr_group,
173*758b62e5SInochi Amaoto 	NULL
174*758b62e5SInochi Amaoto };
175*758b62e5SInochi Amaoto 
176*758b62e5SInochi Amaoto static const struct hwmon_channel_info * const sg2042_mcu_info[] = {
177*758b62e5SInochi Amaoto 	HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
178*758b62e5SInochi Amaoto 	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_CRIT |
179*758b62e5SInochi Amaoto 					HWMON_T_CRIT_HYST,
180*758b62e5SInochi Amaoto 				 HWMON_T_INPUT),
181*758b62e5SInochi Amaoto 	NULL
182*758b62e5SInochi Amaoto };
183*758b62e5SInochi Amaoto 
sg2042_mcu_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)184*758b62e5SInochi Amaoto static int sg2042_mcu_read(struct device *dev,
185*758b62e5SInochi Amaoto 			   enum hwmon_sensor_types type,
186*758b62e5SInochi Amaoto 			   u32 attr, int channel, long *val)
187*758b62e5SInochi Amaoto {
188*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
189*758b62e5SInochi Amaoto 	int tmp;
190*758b62e5SInochi Amaoto 	u8 reg;
191*758b62e5SInochi Amaoto 
192*758b62e5SInochi Amaoto 	switch (attr) {
193*758b62e5SInochi Amaoto 	case hwmon_temp_input:
194*758b62e5SInochi Amaoto 		reg = channel ? REG_BOARD_TEMP : REG_SOC_TEMP;
195*758b62e5SInochi Amaoto 		break;
196*758b62e5SInochi Amaoto 	case hwmon_temp_crit:
197*758b62e5SInochi Amaoto 		reg = REG_CRITICAL_TEMP;
198*758b62e5SInochi Amaoto 		break;
199*758b62e5SInochi Amaoto 	case hwmon_temp_crit_hyst:
200*758b62e5SInochi Amaoto 		reg = REG_REPOWER_TEMP;
201*758b62e5SInochi Amaoto 		break;
202*758b62e5SInochi Amaoto 	default:
203*758b62e5SInochi Amaoto 		return -EOPNOTSUPP;
204*758b62e5SInochi Amaoto 	}
205*758b62e5SInochi Amaoto 
206*758b62e5SInochi Amaoto 	tmp = i2c_smbus_read_byte_data(mcu->client, reg);
207*758b62e5SInochi Amaoto 	if (tmp < 0)
208*758b62e5SInochi Amaoto 		return tmp;
209*758b62e5SInochi Amaoto 	*val = tmp * 1000;
210*758b62e5SInochi Amaoto 
211*758b62e5SInochi Amaoto 	return 0;
212*758b62e5SInochi Amaoto }
213*758b62e5SInochi Amaoto 
sg2042_mcu_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)214*758b62e5SInochi Amaoto static int sg2042_mcu_write(struct device *dev,
215*758b62e5SInochi Amaoto 			    enum hwmon_sensor_types type,
216*758b62e5SInochi Amaoto 			    u32 attr, int channel, long val)
217*758b62e5SInochi Amaoto {
218*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = dev_get_drvdata(dev);
219*758b62e5SInochi Amaoto 	int temp = val / 1000;
220*758b62e5SInochi Amaoto 	int hyst_temp, crit_temp;
221*758b62e5SInochi Amaoto 	u8 reg;
222*758b62e5SInochi Amaoto 
223*758b62e5SInochi Amaoto 	temp = clamp_val(temp, 0, MCU_POWER_MAX);
224*758b62e5SInochi Amaoto 
225*758b62e5SInochi Amaoto 	guard(mutex)(&mcu->mutex);
226*758b62e5SInochi Amaoto 
227*758b62e5SInochi Amaoto 	switch (attr) {
228*758b62e5SInochi Amaoto 	case hwmon_temp_crit:
229*758b62e5SInochi Amaoto 		hyst_temp = i2c_smbus_read_byte_data(mcu->client,
230*758b62e5SInochi Amaoto 						     REG_REPOWER_TEMP);
231*758b62e5SInochi Amaoto 		if (hyst_temp < 0)
232*758b62e5SInochi Amaoto 			return hyst_temp;
233*758b62e5SInochi Amaoto 
234*758b62e5SInochi Amaoto 		crit_temp = temp;
235*758b62e5SInochi Amaoto 		reg = REG_CRITICAL_TEMP;
236*758b62e5SInochi Amaoto 		break;
237*758b62e5SInochi Amaoto 	case hwmon_temp_crit_hyst:
238*758b62e5SInochi Amaoto 		crit_temp = i2c_smbus_read_byte_data(mcu->client,
239*758b62e5SInochi Amaoto 						     REG_CRITICAL_TEMP);
240*758b62e5SInochi Amaoto 		if (crit_temp < 0)
241*758b62e5SInochi Amaoto 			return crit_temp;
242*758b62e5SInochi Amaoto 
243*758b62e5SInochi Amaoto 		hyst_temp = temp;
244*758b62e5SInochi Amaoto 		reg = REG_REPOWER_TEMP;
245*758b62e5SInochi Amaoto 		break;
246*758b62e5SInochi Amaoto 	default:
247*758b62e5SInochi Amaoto 		return -EOPNOTSUPP;
248*758b62e5SInochi Amaoto 	}
249*758b62e5SInochi Amaoto 
250*758b62e5SInochi Amaoto 	/*
251*758b62e5SInochi Amaoto 	 * ensure hyst_temp is smaller to avoid MCU from
252*758b62e5SInochi Amaoto 	 * keeping triggering repower event.
253*758b62e5SInochi Amaoto 	 */
254*758b62e5SInochi Amaoto 	if (crit_temp < hyst_temp)
255*758b62e5SInochi Amaoto 		return -EINVAL;
256*758b62e5SInochi Amaoto 
257*758b62e5SInochi Amaoto 	return i2c_smbus_write_byte_data(mcu->client, reg, temp);
258*758b62e5SInochi Amaoto }
259*758b62e5SInochi Amaoto 
sg2042_mcu_is_visible(const void * _data,enum hwmon_sensor_types type,u32 attr,int channel)260*758b62e5SInochi Amaoto static umode_t sg2042_mcu_is_visible(const void *_data,
261*758b62e5SInochi Amaoto 				     enum hwmon_sensor_types type,
262*758b62e5SInochi Amaoto 				     u32 attr, int channel)
263*758b62e5SInochi Amaoto {
264*758b62e5SInochi Amaoto 	switch (type) {
265*758b62e5SInochi Amaoto 	case hwmon_temp:
266*758b62e5SInochi Amaoto 		switch (attr) {
267*758b62e5SInochi Amaoto 		case hwmon_temp_input:
268*758b62e5SInochi Amaoto 			return 0444;
269*758b62e5SInochi Amaoto 		case hwmon_temp_crit:
270*758b62e5SInochi Amaoto 		case hwmon_temp_crit_hyst:
271*758b62e5SInochi Amaoto 			if (channel == 0)
272*758b62e5SInochi Amaoto 				return 0644;
273*758b62e5SInochi Amaoto 			break;
274*758b62e5SInochi Amaoto 		default:
275*758b62e5SInochi Amaoto 			break;
276*758b62e5SInochi Amaoto 		}
277*758b62e5SInochi Amaoto 		break;
278*758b62e5SInochi Amaoto 	default:
279*758b62e5SInochi Amaoto 			break;
280*758b62e5SInochi Amaoto 	}
281*758b62e5SInochi Amaoto 	return 0;
282*758b62e5SInochi Amaoto }
283*758b62e5SInochi Amaoto 
284*758b62e5SInochi Amaoto static const struct hwmon_ops sg2042_mcu_ops = {
285*758b62e5SInochi Amaoto 	.is_visible = sg2042_mcu_is_visible,
286*758b62e5SInochi Amaoto 	.read = sg2042_mcu_read,
287*758b62e5SInochi Amaoto 	.write = sg2042_mcu_write,
288*758b62e5SInochi Amaoto };
289*758b62e5SInochi Amaoto 
290*758b62e5SInochi Amaoto static const struct hwmon_chip_info sg2042_mcu_chip_info = {
291*758b62e5SInochi Amaoto 	.ops = &sg2042_mcu_ops,
292*758b62e5SInochi Amaoto 	.info = sg2042_mcu_info,
293*758b62e5SInochi Amaoto };
294*758b62e5SInochi Amaoto 
sg2042_mcu_debugfs_init(struct sg2042_mcu_data * mcu,struct device * dev)295*758b62e5SInochi Amaoto static void sg2042_mcu_debugfs_init(struct sg2042_mcu_data *mcu,
296*758b62e5SInochi Amaoto 				    struct device *dev)
297*758b62e5SInochi Amaoto {
298*758b62e5SInochi Amaoto 	mcu->debugfs = debugfs_create_dir(dev_name(dev), sgmcu_debugfs);
299*758b62e5SInochi Amaoto 
300*758b62e5SInochi Amaoto 	debugfs_create_file("firmware_version", 0444, mcu->debugfs,
301*758b62e5SInochi Amaoto 			    mcu, &firmware_version_fops);
302*758b62e5SInochi Amaoto 	debugfs_create_file("pcb_version", 0444, mcu->debugfs, mcu,
303*758b62e5SInochi Amaoto 			    &pcb_version_fops);
304*758b62e5SInochi Amaoto 	debugfs_create_file("mcu_type", 0444, mcu->debugfs, mcu,
305*758b62e5SInochi Amaoto 			    &mcu_type_fops);
306*758b62e5SInochi Amaoto 	debugfs_create_file("board_type", 0444, mcu->debugfs, mcu,
307*758b62e5SInochi Amaoto 			    &board_type_fops);
308*758b62e5SInochi Amaoto }
309*758b62e5SInochi Amaoto 
sg2042_mcu_i2c_probe(struct i2c_client * client)310*758b62e5SInochi Amaoto static int sg2042_mcu_i2c_probe(struct i2c_client *client)
311*758b62e5SInochi Amaoto {
312*758b62e5SInochi Amaoto 	struct device *dev = &client->dev;
313*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu;
314*758b62e5SInochi Amaoto 	struct device *hwmon_dev;
315*758b62e5SInochi Amaoto 
316*758b62e5SInochi Amaoto 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
317*758b62e5SInochi Amaoto 						I2C_FUNC_SMBUS_BLOCK_DATA))
318*758b62e5SInochi Amaoto 		return -ENODEV;
319*758b62e5SInochi Amaoto 
320*758b62e5SInochi Amaoto 	mcu = devm_kmalloc(dev, sizeof(*mcu), GFP_KERNEL);
321*758b62e5SInochi Amaoto 	if (!mcu)
322*758b62e5SInochi Amaoto 		return -ENOMEM;
323*758b62e5SInochi Amaoto 
324*758b62e5SInochi Amaoto 	mutex_init(&mcu->mutex);
325*758b62e5SInochi Amaoto 	mcu->client = client;
326*758b62e5SInochi Amaoto 
327*758b62e5SInochi Amaoto 	i2c_set_clientdata(client, mcu);
328*758b62e5SInochi Amaoto 
329*758b62e5SInochi Amaoto 	hwmon_dev = devm_hwmon_device_register_with_info(dev, "sg2042_mcu",
330*758b62e5SInochi Amaoto 							 mcu,
331*758b62e5SInochi Amaoto 							 &sg2042_mcu_chip_info,
332*758b62e5SInochi Amaoto 							 NULL);
333*758b62e5SInochi Amaoto 	if (IS_ERR(hwmon_dev))
334*758b62e5SInochi Amaoto 		return PTR_ERR(hwmon_dev);
335*758b62e5SInochi Amaoto 
336*758b62e5SInochi Amaoto 	sg2042_mcu_debugfs_init(mcu, dev);
337*758b62e5SInochi Amaoto 
338*758b62e5SInochi Amaoto 	return 0;
339*758b62e5SInochi Amaoto }
340*758b62e5SInochi Amaoto 
sg2042_mcu_i2c_remove(struct i2c_client * client)341*758b62e5SInochi Amaoto static void sg2042_mcu_i2c_remove(struct i2c_client *client)
342*758b62e5SInochi Amaoto {
343*758b62e5SInochi Amaoto 	struct sg2042_mcu_data *mcu = i2c_get_clientdata(client);
344*758b62e5SInochi Amaoto 
345*758b62e5SInochi Amaoto 	debugfs_remove_recursive(mcu->debugfs);
346*758b62e5SInochi Amaoto }
347*758b62e5SInochi Amaoto 
348*758b62e5SInochi Amaoto static const struct i2c_device_id sg2042_mcu_id[] = {
349*758b62e5SInochi Amaoto 	{ "sg2042-hwmon-mcu", 0 },
350*758b62e5SInochi Amaoto 	{},
351*758b62e5SInochi Amaoto };
352*758b62e5SInochi Amaoto MODULE_DEVICE_TABLE(i2c, sg2042_mcu_id);
353*758b62e5SInochi Amaoto 
354*758b62e5SInochi Amaoto static const struct of_device_id sg2042_mcu_of_id[] = {
355*758b62e5SInochi Amaoto 	{ .compatible = "sophgo,sg2042-hwmon-mcu" },
356*758b62e5SInochi Amaoto 	{},
357*758b62e5SInochi Amaoto };
358*758b62e5SInochi Amaoto MODULE_DEVICE_TABLE(of, sg2042_mcu_of_id);
359*758b62e5SInochi Amaoto 
360*758b62e5SInochi Amaoto static struct i2c_driver sg2042_mcu_driver = {
361*758b62e5SInochi Amaoto 	.driver = {
362*758b62e5SInochi Amaoto 		.name = "sg2042-mcu",
363*758b62e5SInochi Amaoto 		.of_match_table = sg2042_mcu_of_id,
364*758b62e5SInochi Amaoto 		.dev_groups = sg2042_mcu_groups,
365*758b62e5SInochi Amaoto 	},
366*758b62e5SInochi Amaoto 	.probe = sg2042_mcu_i2c_probe,
367*758b62e5SInochi Amaoto 	.remove = sg2042_mcu_i2c_remove,
368*758b62e5SInochi Amaoto 	.id_table = sg2042_mcu_id,
369*758b62e5SInochi Amaoto };
370*758b62e5SInochi Amaoto 
sg2042_mcu_init(void)371*758b62e5SInochi Amaoto static int __init sg2042_mcu_init(void)
372*758b62e5SInochi Amaoto {
373*758b62e5SInochi Amaoto 	sgmcu_debugfs = debugfs_create_dir("sg2042-mcu", NULL);
374*758b62e5SInochi Amaoto 	return i2c_add_driver(&sg2042_mcu_driver);
375*758b62e5SInochi Amaoto }
376*758b62e5SInochi Amaoto 
sg2042_mcu_exit(void)377*758b62e5SInochi Amaoto static void __exit sg2042_mcu_exit(void)
378*758b62e5SInochi Amaoto {
379*758b62e5SInochi Amaoto 	debugfs_remove_recursive(sgmcu_debugfs);
380*758b62e5SInochi Amaoto 	i2c_del_driver(&sg2042_mcu_driver);
381*758b62e5SInochi Amaoto }
382*758b62e5SInochi Amaoto 
383*758b62e5SInochi Amaoto module_init(sg2042_mcu_init);
384*758b62e5SInochi Amaoto module_exit(sg2042_mcu_exit);
385*758b62e5SInochi Amaoto 
386*758b62e5SInochi Amaoto MODULE_AUTHOR("Inochi Amaoto <inochiama@outlook.com>");
387*758b62e5SInochi Amaoto MODULE_DESCRIPTION("MCU I2C driver for SG2042 soc platform");
388*758b62e5SInochi Amaoto MODULE_LICENSE("GPL");
389