xref: /OK3568_Linux_fs/kernel/drivers/input/joystick/as5011.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2010, 2011 Fabien Marteau <fabien.marteau@armadeus.com>
4*4882a593Smuzhiyun  * Sponsored by ARMadeus Systems
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Driver for Austria Microsystems joysticks AS5011
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * TODO:
9*4882a593Smuzhiyun  *	- Power on the chip when open() and power down when close()
10*4882a593Smuzhiyun  *	- Manage power mode
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <linux/i2c.h>
14*4882a593Smuzhiyun #include <linux/interrupt.h>
15*4882a593Smuzhiyun #include <linux/input.h>
16*4882a593Smuzhiyun #include <linux/gpio.h>
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include <linux/input/as5011.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick"
23*4882a593Smuzhiyun #define MODULE_DEVICE_ALIAS "as5011"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun MODULE_AUTHOR("Fabien Marteau <fabien.marteau@armadeus.com>");
26*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
27*4882a593Smuzhiyun MODULE_LICENSE("GPL");
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* registers */
30*4882a593Smuzhiyun #define AS5011_CTRL1		0x76
31*4882a593Smuzhiyun #define AS5011_CTRL2		0x75
32*4882a593Smuzhiyun #define AS5011_XP		0x43
33*4882a593Smuzhiyun #define AS5011_XN		0x44
34*4882a593Smuzhiyun #define AS5011_YP		0x53
35*4882a593Smuzhiyun #define AS5011_YN		0x54
36*4882a593Smuzhiyun #define AS5011_X_REG		0x41
37*4882a593Smuzhiyun #define AS5011_Y_REG		0x42
38*4882a593Smuzhiyun #define AS5011_X_RES_INT	0x51
39*4882a593Smuzhiyun #define AS5011_Y_RES_INT	0x52
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun /* CTRL1 bits */
42*4882a593Smuzhiyun #define AS5011_CTRL1_LP_PULSED		0x80
43*4882a593Smuzhiyun #define AS5011_CTRL1_LP_ACTIVE		0x40
44*4882a593Smuzhiyun #define AS5011_CTRL1_LP_CONTINUE	0x20
45*4882a593Smuzhiyun #define AS5011_CTRL1_INT_WUP_EN		0x10
46*4882a593Smuzhiyun #define AS5011_CTRL1_INT_ACT_EN		0x08
47*4882a593Smuzhiyun #define AS5011_CTRL1_EXT_CLK_EN		0x04
48*4882a593Smuzhiyun #define AS5011_CTRL1_SOFT_RST		0x02
49*4882a593Smuzhiyun #define AS5011_CTRL1_DATA_VALID		0x01
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /* CTRL2 bits */
52*4882a593Smuzhiyun #define AS5011_CTRL2_EXT_SAMPLE_EN	0x08
53*4882a593Smuzhiyun #define AS5011_CTRL2_RC_BIAS_ON		0x04
54*4882a593Smuzhiyun #define AS5011_CTRL2_INV_SPINNING	0x02
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define AS5011_MAX_AXIS	80
57*4882a593Smuzhiyun #define AS5011_MIN_AXIS	(-80)
58*4882a593Smuzhiyun #define AS5011_FUZZ	8
59*4882a593Smuzhiyun #define AS5011_FLAT	40
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct as5011_device {
62*4882a593Smuzhiyun 	struct input_dev *input_dev;
63*4882a593Smuzhiyun 	struct i2c_client *i2c_client;
64*4882a593Smuzhiyun 	unsigned int button_gpio;
65*4882a593Smuzhiyun 	unsigned int button_irq;
66*4882a593Smuzhiyun 	unsigned int axis_irq;
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
as5011_i2c_write(struct i2c_client * client,uint8_t aregaddr,uint8_t avalue)69*4882a593Smuzhiyun static int as5011_i2c_write(struct i2c_client *client,
70*4882a593Smuzhiyun 			    uint8_t aregaddr,
71*4882a593Smuzhiyun 			    uint8_t avalue)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	uint8_t data[2] = { aregaddr, avalue };
74*4882a593Smuzhiyun 	struct i2c_msg msg = {
75*4882a593Smuzhiyun 		.addr = client->addr,
76*4882a593Smuzhiyun 		.flags = I2C_M_IGNORE_NAK,
77*4882a593Smuzhiyun 		.len = 2,
78*4882a593Smuzhiyun 		.buf = (uint8_t *)data
79*4882a593Smuzhiyun 	};
80*4882a593Smuzhiyun 	int error;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	error = i2c_transfer(client->adapter, &msg, 1);
83*4882a593Smuzhiyun 	return error < 0 ? error : 0;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
as5011_i2c_read(struct i2c_client * client,uint8_t aregaddr,signed char * value)86*4882a593Smuzhiyun static int as5011_i2c_read(struct i2c_client *client,
87*4882a593Smuzhiyun 			   uint8_t aregaddr, signed char *value)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	uint8_t data[2] = { aregaddr };
90*4882a593Smuzhiyun 	struct i2c_msg msg_set[2] = {
91*4882a593Smuzhiyun 		{
92*4882a593Smuzhiyun 			.addr = client->addr,
93*4882a593Smuzhiyun 			.flags = I2C_M_REV_DIR_ADDR,
94*4882a593Smuzhiyun 			.len = 1,
95*4882a593Smuzhiyun 			.buf = (uint8_t *)data
96*4882a593Smuzhiyun 		},
97*4882a593Smuzhiyun 		{
98*4882a593Smuzhiyun 			.addr = client->addr,
99*4882a593Smuzhiyun 			.flags = I2C_M_RD | I2C_M_NOSTART,
100*4882a593Smuzhiyun 			.len = 1,
101*4882a593Smuzhiyun 			.buf = (uint8_t *)data
102*4882a593Smuzhiyun 		}
103*4882a593Smuzhiyun 	};
104*4882a593Smuzhiyun 	int error;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	error = i2c_transfer(client->adapter, msg_set, 2);
107*4882a593Smuzhiyun 	if (error < 0)
108*4882a593Smuzhiyun 		return error;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	*value = data[0] & 0x80 ? -1 * (1 + ~data[0]) : data[0];
111*4882a593Smuzhiyun 	return 0;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
as5011_button_interrupt(int irq,void * dev_id)114*4882a593Smuzhiyun static irqreturn_t as5011_button_interrupt(int irq, void *dev_id)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct as5011_device *as5011 = dev_id;
117*4882a593Smuzhiyun 	int val = gpio_get_value_cansleep(as5011->button_gpio);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	input_report_key(as5011->input_dev, BTN_JOYSTICK, !val);
120*4882a593Smuzhiyun 	input_sync(as5011->input_dev);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	return IRQ_HANDLED;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
as5011_axis_interrupt(int irq,void * dev_id)125*4882a593Smuzhiyun static irqreturn_t as5011_axis_interrupt(int irq, void *dev_id)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	struct as5011_device *as5011 = dev_id;
128*4882a593Smuzhiyun 	int error;
129*4882a593Smuzhiyun 	signed char x, y;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	error = as5011_i2c_read(as5011->i2c_client, AS5011_X_RES_INT, &x);
132*4882a593Smuzhiyun 	if (error < 0)
133*4882a593Smuzhiyun 		goto out;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	error = as5011_i2c_read(as5011->i2c_client, AS5011_Y_RES_INT, &y);
136*4882a593Smuzhiyun 	if (error < 0)
137*4882a593Smuzhiyun 		goto out;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	input_report_abs(as5011->input_dev, ABS_X, x);
140*4882a593Smuzhiyun 	input_report_abs(as5011->input_dev, ABS_Y, y);
141*4882a593Smuzhiyun 	input_sync(as5011->input_dev);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun out:
144*4882a593Smuzhiyun 	return IRQ_HANDLED;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
as5011_configure_chip(struct as5011_device * as5011,const struct as5011_platform_data * plat_dat)147*4882a593Smuzhiyun static int as5011_configure_chip(struct as5011_device *as5011,
148*4882a593Smuzhiyun 				const struct as5011_platform_data *plat_dat)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct i2c_client *client = as5011->i2c_client;
151*4882a593Smuzhiyun 	int error;
152*4882a593Smuzhiyun 	signed char value;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	/* chip soft reset */
155*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_CTRL1,
156*4882a593Smuzhiyun 				 AS5011_CTRL1_SOFT_RST);
157*4882a593Smuzhiyun 	if (error < 0) {
158*4882a593Smuzhiyun 		dev_err(&client->dev, "Soft reset failed\n");
159*4882a593Smuzhiyun 		return error;
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	mdelay(10);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_CTRL1,
165*4882a593Smuzhiyun 				 AS5011_CTRL1_LP_PULSED |
166*4882a593Smuzhiyun 				 AS5011_CTRL1_LP_ACTIVE |
167*4882a593Smuzhiyun 				 AS5011_CTRL1_INT_ACT_EN);
168*4882a593Smuzhiyun 	if (error < 0) {
169*4882a593Smuzhiyun 		dev_err(&client->dev, "Power config failed\n");
170*4882a593Smuzhiyun 		return error;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_CTRL2,
174*4882a593Smuzhiyun 				 AS5011_CTRL2_INV_SPINNING);
175*4882a593Smuzhiyun 	if (error < 0) {
176*4882a593Smuzhiyun 		dev_err(&client->dev, "Can't invert spinning\n");
177*4882a593Smuzhiyun 		return error;
178*4882a593Smuzhiyun 	}
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	/* write threshold */
181*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_XP, plat_dat->xp);
182*4882a593Smuzhiyun 	if (error < 0) {
183*4882a593Smuzhiyun 		dev_err(&client->dev, "Can't write threshold\n");
184*4882a593Smuzhiyun 		return error;
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_XN, plat_dat->xn);
188*4882a593Smuzhiyun 	if (error < 0) {
189*4882a593Smuzhiyun 		dev_err(&client->dev, "Can't write threshold\n");
190*4882a593Smuzhiyun 		return error;
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_YP, plat_dat->yp);
194*4882a593Smuzhiyun 	if (error < 0) {
195*4882a593Smuzhiyun 		dev_err(&client->dev, "Can't write threshold\n");
196*4882a593Smuzhiyun 		return error;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	error = as5011_i2c_write(client, AS5011_YN, plat_dat->yn);
200*4882a593Smuzhiyun 	if (error < 0) {
201*4882a593Smuzhiyun 		dev_err(&client->dev, "Can't write threshold\n");
202*4882a593Smuzhiyun 		return error;
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* to free irq gpio in chip */
206*4882a593Smuzhiyun 	error = as5011_i2c_read(client, AS5011_X_RES_INT, &value);
207*4882a593Smuzhiyun 	if (error < 0) {
208*4882a593Smuzhiyun 		dev_err(&client->dev, "Can't read i2c X resolution value\n");
209*4882a593Smuzhiyun 		return error;
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
as5011_probe(struct i2c_client * client,const struct i2c_device_id * id)215*4882a593Smuzhiyun static int as5011_probe(struct i2c_client *client,
216*4882a593Smuzhiyun 			 const struct i2c_device_id *id)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	const struct as5011_platform_data *plat_data;
219*4882a593Smuzhiyun 	struct as5011_device *as5011;
220*4882a593Smuzhiyun 	struct input_dev *input_dev;
221*4882a593Smuzhiyun 	int irq;
222*4882a593Smuzhiyun 	int error;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	plat_data = dev_get_platdata(&client->dev);
225*4882a593Smuzhiyun 	if (!plat_data)
226*4882a593Smuzhiyun 		return -EINVAL;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	if (!plat_data->axis_irq) {
229*4882a593Smuzhiyun 		dev_err(&client->dev, "No axis IRQ?\n");
230*4882a593Smuzhiyun 		return -EINVAL;
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	if (!i2c_check_functionality(client->adapter,
234*4882a593Smuzhiyun 				     I2C_FUNC_NOSTART |
235*4882a593Smuzhiyun 				     I2C_FUNC_PROTOCOL_MANGLING)) {
236*4882a593Smuzhiyun 		dev_err(&client->dev,
237*4882a593Smuzhiyun 			"need i2c bus that supports protocol mangling\n");
238*4882a593Smuzhiyun 		return -ENODEV;
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL);
242*4882a593Smuzhiyun 	input_dev = input_allocate_device();
243*4882a593Smuzhiyun 	if (!as5011 || !input_dev) {
244*4882a593Smuzhiyun 		dev_err(&client->dev,
245*4882a593Smuzhiyun 			"Can't allocate memory for device structure\n");
246*4882a593Smuzhiyun 		error = -ENOMEM;
247*4882a593Smuzhiyun 		goto err_free_mem;
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	as5011->i2c_client = client;
251*4882a593Smuzhiyun 	as5011->input_dev = input_dev;
252*4882a593Smuzhiyun 	as5011->button_gpio = plat_data->button_gpio;
253*4882a593Smuzhiyun 	as5011->axis_irq = plat_data->axis_irq;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	input_dev->name = "Austria Microsystem as5011 joystick";
256*4882a593Smuzhiyun 	input_dev->id.bustype = BUS_I2C;
257*4882a593Smuzhiyun 	input_dev->dev.parent = &client->dev;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	input_set_capability(input_dev, EV_KEY, BTN_JOYSTICK);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	input_set_abs_params(input_dev, ABS_X,
262*4882a593Smuzhiyun 		AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
263*4882a593Smuzhiyun 	input_set_abs_params(as5011->input_dev, ABS_Y,
264*4882a593Smuzhiyun 		AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	error = gpio_request(as5011->button_gpio, "AS5011 button");
267*4882a593Smuzhiyun 	if (error < 0) {
268*4882a593Smuzhiyun 		dev_err(&client->dev, "Failed to request button gpio\n");
269*4882a593Smuzhiyun 		goto err_free_mem;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	irq = gpio_to_irq(as5011->button_gpio);
273*4882a593Smuzhiyun 	if (irq < 0) {
274*4882a593Smuzhiyun 		dev_err(&client->dev,
275*4882a593Smuzhiyun 			"Failed to get irq number for button gpio\n");
276*4882a593Smuzhiyun 		error = irq;
277*4882a593Smuzhiyun 		goto err_free_button_gpio;
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	as5011->button_irq = irq;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	error = request_threaded_irq(as5011->button_irq,
283*4882a593Smuzhiyun 				     NULL, as5011_button_interrupt,
284*4882a593Smuzhiyun 				     IRQF_TRIGGER_RISING |
285*4882a593Smuzhiyun 					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
286*4882a593Smuzhiyun 				     "as5011_button", as5011);
287*4882a593Smuzhiyun 	if (error < 0) {
288*4882a593Smuzhiyun 		dev_err(&client->dev,
289*4882a593Smuzhiyun 			"Can't allocate button irq %d\n", as5011->button_irq);
290*4882a593Smuzhiyun 		goto err_free_button_gpio;
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	error = as5011_configure_chip(as5011, plat_data);
294*4882a593Smuzhiyun 	if (error)
295*4882a593Smuzhiyun 		goto err_free_button_irq;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	error = request_threaded_irq(as5011->axis_irq, NULL,
298*4882a593Smuzhiyun 				     as5011_axis_interrupt,
299*4882a593Smuzhiyun 				     plat_data->axis_irqflags | IRQF_ONESHOT,
300*4882a593Smuzhiyun 				     "as5011_joystick", as5011);
301*4882a593Smuzhiyun 	if (error) {
302*4882a593Smuzhiyun 		dev_err(&client->dev,
303*4882a593Smuzhiyun 			"Can't allocate axis irq %d\n", plat_data->axis_irq);
304*4882a593Smuzhiyun 		goto err_free_button_irq;
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	error = input_register_device(as5011->input_dev);
308*4882a593Smuzhiyun 	if (error) {
309*4882a593Smuzhiyun 		dev_err(&client->dev, "Failed to register input device\n");
310*4882a593Smuzhiyun 		goto err_free_axis_irq;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	i2c_set_clientdata(client, as5011);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	return 0;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun err_free_axis_irq:
318*4882a593Smuzhiyun 	free_irq(as5011->axis_irq, as5011);
319*4882a593Smuzhiyun err_free_button_irq:
320*4882a593Smuzhiyun 	free_irq(as5011->button_irq, as5011);
321*4882a593Smuzhiyun err_free_button_gpio:
322*4882a593Smuzhiyun 	gpio_free(as5011->button_gpio);
323*4882a593Smuzhiyun err_free_mem:
324*4882a593Smuzhiyun 	input_free_device(input_dev);
325*4882a593Smuzhiyun 	kfree(as5011);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	return error;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
as5011_remove(struct i2c_client * client)330*4882a593Smuzhiyun static int as5011_remove(struct i2c_client *client)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	struct as5011_device *as5011 = i2c_get_clientdata(client);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	free_irq(as5011->axis_irq, as5011);
335*4882a593Smuzhiyun 	free_irq(as5011->button_irq, as5011);
336*4882a593Smuzhiyun 	gpio_free(as5011->button_gpio);
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	input_unregister_device(as5011->input_dev);
339*4882a593Smuzhiyun 	kfree(as5011);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun static const struct i2c_device_id as5011_id[] = {
345*4882a593Smuzhiyun 	{ MODULE_DEVICE_ALIAS, 0 },
346*4882a593Smuzhiyun 	{ }
347*4882a593Smuzhiyun };
348*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, as5011_id);
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun static struct i2c_driver as5011_driver = {
351*4882a593Smuzhiyun 	.driver = {
352*4882a593Smuzhiyun 		.name = "as5011",
353*4882a593Smuzhiyun 	},
354*4882a593Smuzhiyun 	.probe		= as5011_probe,
355*4882a593Smuzhiyun 	.remove		= as5011_remove,
356*4882a593Smuzhiyun 	.id_table	= as5011_id,
357*4882a593Smuzhiyun };
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun module_i2c_driver(as5011_driver);
360