-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
iio / platform: cros_ec: Add cros-ec-sensorhub driver
Similar to HID sensor stack, the new driver sits between cros-ec-dev and the IIO device drivers: The EC based IIO device topology would be: iio:device1 -> ...0/0000:00:1f.0/PNP0C09:00/GOOG0004:00/cros-ec-dev.6.auto/ cros-ec-sensorhub.7.auto/ cros-ec-accel.15.auto/ iio:device1 It will be expanded to control EC sensor FIFO. Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> [Fix "unknown type name 'uint32_t'" type errors] Reported-by: kbuild test robot <lkp@intel.com> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
- Loading branch information
Gwendal Grignou
authored and
Enric Balletbo i Serra
committed
Nov 21, 2019
1 parent
a16b2e2
commit 5306747
Showing
5 changed files
with
235 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Sensor HUB driver that discovers sensors behind a ChromeOS Embedded | ||
* Controller. | ||
* | ||
* Copyright 2019 Google LLC | ||
*/ | ||
|
||
#include <linux/init.h> | ||
#include <linux/device.h> | ||
#include <linux/module.h> | ||
#include <linux/mfd/cros_ec.h> | ||
#include <linux/platform_data/cros_ec_commands.h> | ||
#include <linux/platform_data/cros_ec_proto.h> | ||
#include <linux/platform_data/cros_ec_sensorhub.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/slab.h> | ||
#include <linux/types.h> | ||
|
||
#define DRV_NAME "cros-ec-sensorhub" | ||
|
||
static void cros_ec_sensorhub_free_sensor(void *arg) | ||
{ | ||
struct platform_device *pdev = arg; | ||
|
||
platform_device_unregister(pdev); | ||
} | ||
|
||
static int cros_ec_sensorhub_allocate_sensor(struct device *parent, | ||
char *sensor_name, | ||
int sensor_num) | ||
{ | ||
struct cros_ec_sensor_platform sensor_platforms = { | ||
.sensor_num = sensor_num, | ||
}; | ||
struct platform_device *pdev; | ||
|
||
pdev = platform_device_register_data(parent, sensor_name, | ||
PLATFORM_DEVID_AUTO, | ||
&sensor_platforms, | ||
sizeof(sensor_platforms)); | ||
if (IS_ERR(pdev)) | ||
return PTR_ERR(pdev); | ||
|
||
return devm_add_action_or_reset(parent, | ||
cros_ec_sensorhub_free_sensor, | ||
pdev); | ||
} | ||
|
||
static int cros_ec_sensorhub_register(struct device *dev, | ||
struct cros_ec_sensorhub *sensorhub) | ||
{ | ||
int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; | ||
struct cros_ec_dev *ec = sensorhub->ec; | ||
struct ec_params_motion_sense *params; | ||
struct ec_response_motion_sense *resp; | ||
struct cros_ec_command *msg; | ||
int ret, i, sensor_num; | ||
char *name; | ||
|
||
sensor_num = cros_ec_get_sensor_count(ec); | ||
if (sensor_num < 0) { | ||
dev_err(dev, | ||
"Unable to retrieve sensor information (err:%d)\n", | ||
sensor_num); | ||
return sensor_num; | ||
} | ||
|
||
if (sensor_num == 0) { | ||
dev_err(dev, "Zero sensors reported.\n"); | ||
return -EINVAL; | ||
} | ||
|
||
/* Prepare a message to send INFO command to each sensor. */ | ||
msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)), | ||
GFP_KERNEL); | ||
if (!msg) | ||
return -ENOMEM; | ||
|
||
msg->version = 1; | ||
msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; | ||
msg->outsize = sizeof(*params); | ||
msg->insize = sizeof(*resp); | ||
params = (struct ec_params_motion_sense *)msg->data; | ||
resp = (struct ec_response_motion_sense *)msg->data; | ||
|
||
for (i = 0; i < sensor_num; i++) { | ||
params->cmd = MOTIONSENSE_CMD_INFO; | ||
params->info.sensor_num = i; | ||
|
||
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); | ||
if (ret < 0) { | ||
dev_warn(dev, "no info for EC sensor %d : %d/%d\n", | ||
i, ret, msg->result); | ||
continue; | ||
} | ||
|
||
switch (resp->info.type) { | ||
case MOTIONSENSE_TYPE_ACCEL: | ||
name = "cros-ec-accel"; | ||
break; | ||
case MOTIONSENSE_TYPE_BARO: | ||
name = "cros-ec-baro"; | ||
break; | ||
case MOTIONSENSE_TYPE_GYRO: | ||
name = "cros-ec-gyro"; | ||
break; | ||
case MOTIONSENSE_TYPE_MAG: | ||
name = "cros-ec-mag"; | ||
break; | ||
case MOTIONSENSE_TYPE_PROX: | ||
name = "cros-ec-prox"; | ||
break; | ||
case MOTIONSENSE_TYPE_LIGHT: | ||
name = "cros-ec-light"; | ||
break; | ||
case MOTIONSENSE_TYPE_ACTIVITY: | ||
name = "cros-ec-activity"; | ||
break; | ||
default: | ||
dev_warn(dev, "unknown type %d\n", resp->info.type); | ||
continue; | ||
} | ||
|
||
ret = cros_ec_sensorhub_allocate_sensor(dev, name, i); | ||
if (ret) | ||
goto error; | ||
|
||
sensor_type[resp->info.type]++; | ||
} | ||
|
||
if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) | ||
ec->has_kb_wake_angle = true; | ||
|
||
if (cros_ec_check_features(ec, | ||
EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) { | ||
ret = cros_ec_sensorhub_allocate_sensor(dev, | ||
"cros-ec-lid-angle", | ||
0); | ||
if (ret) | ||
goto error; | ||
} | ||
|
||
kfree(msg); | ||
return 0; | ||
|
||
error: | ||
kfree(msg); | ||
return ret; | ||
} | ||
|
||
static int cros_ec_sensorhub_probe(struct platform_device *pdev) | ||
{ | ||
struct device *dev = &pdev->dev; | ||
struct cros_ec_sensorhub *data; | ||
int ret; | ||
int i; | ||
|
||
data = devm_kzalloc(dev, sizeof(struct cros_ec_sensorhub), GFP_KERNEL); | ||
if (!data) | ||
return -ENOMEM; | ||
|
||
data->ec = dev_get_drvdata(dev->parent); | ||
dev_set_drvdata(dev, data); | ||
|
||
/* Check whether this EC is a sensor hub. */ | ||
if (cros_ec_check_features(data->ec, EC_FEATURE_MOTION_SENSE)) { | ||
ret = cros_ec_sensorhub_register(dev, data); | ||
if (ret) | ||
return ret; | ||
} else { | ||
/* | ||
* If the device has sensors but does not claim to | ||
* be a sensor hub, we are in legacy mode. | ||
*/ | ||
for (i = 0; i < 2; i++) { | ||
ret = cros_ec_sensorhub_allocate_sensor(dev, | ||
"cros-ec-accel-legacy", i); | ||
if (ret) | ||
return ret; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static struct platform_driver cros_ec_sensorhub_driver = { | ||
.driver = { | ||
.name = DRV_NAME, | ||
}, | ||
.probe = cros_ec_sensorhub_probe, | ||
}; | ||
|
||
module_platform_driver(cros_ec_sensorhub_driver); | ||
|
||
MODULE_ALIAS("platform:" DRV_NAME); | ||
MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>"); | ||
MODULE_DESCRIPTION("ChromeOS EC MEMS Sensor Hub Driver"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Chrome OS EC MEMS Sensor Hub driver. | ||
* | ||
* Copyright 2019 Google LLC | ||
*/ | ||
|
||
#ifndef __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H | ||
#define __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H | ||
|
||
#include <linux/platform_data/cros_ec_commands.h> | ||
|
||
/** | ||
* struct cros_ec_sensorhub - Sensor Hub device data. | ||
* | ||
* @ec: Embedded Controller where the hub is located. | ||
*/ | ||
struct cros_ec_sensorhub { | ||
struct cros_ec_dev *ec; | ||
}; | ||
|
||
#endif /* __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H */ |