xref: /OK3568_Linux_fs/kernel/drivers/input/sensors/gyro/iam20680_gyro.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * gyroscope driver for iam20680
4  *
5  * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
6  *
7  * Author: sxj <sxj@rock-chips.com>
8  *
9  */
10 #include <linux/interrupt.h>
11 #include <linux/i2c.h>
12 #include <linux/slab.h>
13 #include <linux/irq.h>
14 #include <linux/miscdevice.h>
15 #include <linux/gpio.h>
16 #include <linux/uaccess.h>
17 #include <linux/atomic.h>
18 #include <linux/delay.h>
19 #include <linux/input.h>
20 #include <linux/workqueue.h>
21 #include <linux/freezer.h>
22 #include <linux/of_gpio.h>
23 #ifdef CONFIG_HAS_EARLYSUSPEND
24 #include <linux/earlysuspend.h>
25 #endif
26 #include <linux/sensor-dev.h>
27 #include <linux/iam20680.h>
28 
sensor_active(struct i2c_client * client,int enable,int rate)29 static int sensor_active(struct i2c_client *client, int enable, int rate)
30 {
31 	struct sensor_private_data *sensor =
32 	    (struct sensor_private_data *) i2c_get_clientdata(client);
33 	int result = 0;
34 	int status = 0;
35 	u8 pwrm1 = 0;
36 
37 	sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
38 	pwrm1 = sensor_read_reg(client, IAM20680_PWR_MGMT_1);
39 
40 	if (!enable) {
41 		status = BIT_GYRO_STBY;
42 		sensor->ops->ctrl_data |= status;
43 		if ((sensor->ops->ctrl_data & BIT_ACCEL_STBY) == BIT_ACCEL_STBY)
44 			pwrm1 |= IAM20680_PWRM1_SLEEP;
45 	} else {
46 		status = ~BIT_GYRO_STBY;
47 		sensor->ops->ctrl_data &= status;
48 		pwrm1 &= ~IAM20680_PWRM1_SLEEP;
49 	}
50 
51 	result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
52 	if (result) {
53 		dev_err(&client->dev, "%s:fail to active sensor\n", __func__);
54 		return -1;
55 	}
56 	msleep(20);
57 
58 	result = sensor_write_reg(client, IAM20680_PWR_MGMT_1, pwrm1);
59 	if (result) {
60 		dev_err(&client->dev, "%s:fail to set pwrm1\n", __func__);
61 		return -1;
62 	}
63 	msleep(50);
64 
65 	return result;
66 }
67 
sensor_init(struct i2c_client * client)68 static int sensor_init(struct i2c_client *client)
69 {
70 	int ret;
71 	struct sensor_private_data *sensor =
72 	    (struct sensor_private_data *) i2c_get_clientdata(client);
73 
74 	/* init on iam20680_acc.c */
75 	ret = sensor->ops->active(client, 0, sensor->pdata->poll_delay_ms);
76 	if (ret) {
77 		dev_err(&client->dev, "%s:line=%d,error\n", __func__, __LINE__);
78 		return ret;
79 	}
80 
81 	return ret;
82 }
83 
gyro_report_value(struct i2c_client * client,struct sensor_axis * axis)84 static int gyro_report_value(struct i2c_client *client, struct sensor_axis *axis)
85 {
86 	struct sensor_private_data *sensor =
87 	    (struct sensor_private_data *) i2c_get_clientdata(client);
88 
89 	if (sensor->status_cur == SENSOR_ON) {
90 		/* Report gyro sensor information */
91 		input_report_rel(sensor->input_dev, ABS_RX, axis->x);
92 		input_report_rel(sensor->input_dev, ABS_RY, axis->y);
93 		input_report_rel(sensor->input_dev, ABS_RZ, axis->z);
94 		input_sync(sensor->input_dev);
95 	}
96 
97 	return 0;
98 }
99 
sensor_report_value(struct i2c_client * client)100 static int sensor_report_value(struct i2c_client *client)
101 {
102 	struct sensor_private_data *sensor =
103 		(struct sensor_private_data *) i2c_get_clientdata(client);
104 	struct sensor_platform_data *pdata = sensor->pdata;
105 	int ret = 0;
106 	short x, y, z;
107 	struct sensor_axis axis;
108 	u8 buffer[6] = {0};
109 
110 	if (sensor->ops->read_len < 6) {
111 		dev_err(&client->dev, "%s: length is error, len=%d\n",
112 				__func__, sensor->ops->read_len);
113 		return -1;
114 	}
115 
116 	memset(buffer, 0, 6);
117 
118 	do {
119 		*buffer = sensor->ops->read_reg;
120 		ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
121 		if (ret < 0)
122 			return ret;
123 	} while (0);
124 
125 	x = ((buffer[0] << 8) & 0xFF00) + (buffer[1] & 0xFF);
126 	y = ((buffer[2] << 8) & 0xFF00) + (buffer[3] & 0xFF);
127 	z = ((buffer[4] << 8) & 0xFF00) + (buffer[5] & 0xFF);
128 
129 	axis.x = (pdata->orientation[0]) * x + (pdata->orientation[1]) * y + (pdata->orientation[2]) * z;
130 	axis.y = (pdata->orientation[3]) * x + (pdata->orientation[4]) * y + (pdata->orientation[5]) * z;
131 	axis.z = (pdata->orientation[6]) * x + (pdata->orientation[7]) * y + (pdata->orientation[8]) * z;
132 
133 	gyro_report_value(client, &axis);
134 
135 	mutex_lock(&(sensor->data_mutex));
136 	sensor->axis = axis;
137 	mutex_unlock(&(sensor->data_mutex));
138 
139 	return ret;
140 }
141 
142 static struct sensor_operate gyro_iam20680_ops = {
143 	.name				= "iam20680_gyro",
144 	.type				= SENSOR_TYPE_GYROSCOPE,
145 	.id_i2c				= GYRO_ID_IAM20680,
146 	.read_reg			= IAM20680_GYRO_XOUT_H,
147 	.read_len			= 6,
148 	.id_reg				= IAM20680_WHOAMI,
149 	.id_data			= IAM20680_DEVICE_ID,
150 	.precision			= IAM20680_PRECISION,
151 	.ctrl_reg			= IAM20680_PWR_MGMT_2,
152 	.int_status_reg		= IAM20680_INT_STATUS,
153 	.range				= {-32768, 32768},
154 	.trig				= IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
155 	.active				= sensor_active,
156 	.init				= sensor_init,
157 	.report				= sensor_report_value,
158 };
159 
160 /****************operate according to sensor chip:end************/
gyro_iam20680_probe(struct i2c_client * client,const struct i2c_device_id * devid)161 static int gyro_iam20680_probe(struct i2c_client *client,
162 				 const struct i2c_device_id *devid)
163 {
164 	return sensor_register_device(client, NULL, devid, &gyro_iam20680_ops);
165 }
166 
gyro_iam20680_remove(struct i2c_client * client)167 static int gyro_iam20680_remove(struct i2c_client *client)
168 {
169 	return sensor_unregister_device(client, NULL, &gyro_iam20680_ops);
170 }
171 
172 static const struct i2c_device_id gyro_iam20680_id[] = {
173 	{"iam20680_gyro", GYRO_ID_IAM20680},
174 	{}
175 };
176 
177 static struct i2c_driver gyro_iam20680_driver = {
178 	.probe = gyro_iam20680_probe,
179 	.remove = gyro_iam20680_remove,
180 	.shutdown = sensor_shutdown,
181 	.id_table = gyro_iam20680_id,
182 	.driver = {
183 		.name = "gyro_iam20680",
184 	#ifdef CONFIG_PM
185 		.pm = &sensor_pm_ops,
186 	#endif
187 	},
188 };
189 
gyro_iam20680_init(void)190 static int __init gyro_iam20680_init(void)
191 {
192 	return i2c_add_driver(&gyro_iam20680_driver);
193 }
194 
gyro_iam20680_exit(void)195 static void __exit gyro_iam20680_exit(void)
196 {
197 	i2c_del_driver(&gyro_iam20680_driver);
198 }
199 
200 /* must register after iam20680_acc */
201 device_initcall_sync(gyro_iam20680_init);
202 module_exit(gyro_iam20680_exit);
203 
204 MODULE_AUTHOR("sxj <sxj@rock-chips.com>");
205 MODULE_DESCRIPTION("iam20680_gyro 3-Axis Gyroscope driver");
206 MODULE_LICENSE("GPL");
207