Commit 0ec5a38b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tag-chrome-platform-for-v6.2' of...

Merge tag 'tag-chrome-platform-for-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux

Pull chrome platform updates from Tzung-Bi Shih:
 "New drivers
   - Driver for ChromeOS human presence sensor

  Cleanups:
   - Add missing property in dt-binding example.
   - Update the availability of properties in dt-binding.
   - Separate dt-binding for ChromeOS fingerprint sensor.

  Improvements:
   - Set PROBE_PREFER_ASYNCHRONOUS for some drivers for shortening boot time.

  Fixes:
   - Fix an use-after-free in cros_ec_typec.

  And minor fixes and cleanups"

* tag 'tag-chrome-platform-for-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
  platform/chrome: cros_ec_typec: zero out stale pointers
  platform/chrome: cros_usbpd_notify: Fix error handling in cros_usbpd_notify_init()
  platform/chrome: cros_ec: Convert to i2c's .probe_new()
  platform/chrome: cros_ec_lpc: Force synchronous probe
  platform/chrome: cros_ec_spi: Set PROBE_PREFER_ASYNCHRONOUS
  platform/chrome: cros_ec_lightbar: Set PROBE_PREFER_ASYNCHRONOUS
  platform/chrome: cros_ec_debugfs: Set PROBE_PREFER_ASYNCHRONOUS
  platform/chrome: cros_ec_lpc: Mark PROBE_PREFER_ASYNCHRONOUS
  platform/chrome: cros_ec_lpc: Move mec_init to device probe
  platform/chrome: Use kstrtobool() instead of strtobool()
  platform/chrome: cros_ec_lpc_mec: remove cros_ec_lpc_mec_destroy()
  dt-bindings: cros-ec: Add ChromeOS fingerprint binding
  dt-bindings: cros-ec: Reorganize and enforce property availability
  platform/chrome: cros_hps_i2c: make remove callback return void
  platform/chrome: add a driver for HPS
parents 7a76117f 9a8aadcf
......@@ -48,6 +48,7 @@ examples:
cros_ec: ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
interrupts = <35 0>;
typec {
compatible = "google,cros-ec-typec";
......
......@@ -27,6 +27,7 @@ examples:
cros_ec: ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
interrupts = <15 0>;
kbd-led-backlight {
compatible = "google,cros-kbd-led-backlight";
......
......@@ -40,6 +40,7 @@ examples:
cros-ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
interrupts = <44 0>;
usbc_extcon0: extcon0 {
compatible = "google,extcon-usbc-cros-ec";
......
......@@ -47,6 +47,7 @@ examples:
compatible = "google,cros-ec-spi";
reg = <0>;
spi-max-frequency = <5000000>;
interrupts = <99 0>;
i2c-tunnel {
compatible = "google,cros-ec-i2c-tunnel";
......
......@@ -20,19 +20,21 @@ properties:
compatible:
oneOf:
- description:
For implementations of the EC is connected through I2C.
For implementations of the EC connected through I2C.
const: google,cros-ec-i2c
- description:
For implementations of the EC is connected through SPI.
For implementations of the EC connected through SPI.
const: google,cros-ec-spi
- description:
For implementations of the EC is connected through RPMSG.
For implementations of the FPMCU connected through SPI.
items:
- const: google,cros-ec-fp
- const: google,cros-ec-spi
- description:
For implementations of the EC connected through RPMSG.
const: google,cros-ec-rpmsg
controller-data:
description:
SPI controller data, see bindings/spi/samsung,spi-peripheral-props.yaml
type: object
controller-data: true
google,cros-ec-spi-pre-delay:
description:
......@@ -62,8 +64,7 @@ properties:
the SCP.
$ref: "/schemas/types.yaml#/definitions/string"
spi-max-frequency:
description: Maximum SPI frequency of the device in Hz.
spi-max-frequency: true
reg:
maxItems: 1
......@@ -71,6 +72,15 @@ properties:
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
boot0-gpios:
maxItems: 1
description: Assert for bootloader mode.
vdd-supply: true
wakeup-source:
description: Button can wake-up the system.
......@@ -155,18 +165,67 @@ allOf:
- if:
properties:
compatible:
contains:
enum:
- google,cros-ec-i2c
- google,cros-ec-rpmsg
not:
contains:
const: google,cros-ec-spi
then:
properties:
controller-data: false
google,cros-ec-spi-pre-delay: false
google,cros-ec-spi-msg-delay: false
spi-max-frequency: false
else:
$ref: /schemas/spi/spi-peripheral-props.yaml
- if:
properties:
compatible:
not:
contains:
const: google,cros-ec-rpmsg
then:
properties:
mediatek,rpmsg-name: false
required:
- reg
- interrupts
- if:
properties:
compatible:
contains:
const: google,cros-ec-fp
then:
properties:
'#address-cells': false
'#size-cells': false
typec: false
ec-pwm: false
kbd-led-backlight: false
keyboard-controller: false
proximity: false
codecs: false
cbas: false
patternProperties:
"^i2c-tunnel[0-9]*$": false
"^regulator@[0-9]+$": false
"^extcon[0-9]*$": false
# Using additionalProperties: false here and
# listing true properties doesn't work
required:
- reset-gpios
- boot0-gpios
- vdd-supply
else:
properties:
reset-gpios: false
boot0-gpios: false
vdd-supply: false
additionalProperties: false
examples:
......@@ -222,4 +281,22 @@ examples:
compatible = "google,cros-ec-rpmsg";
};
};
# Example for FPMCU
- |
spi0 {
#address-cells = <0x1>;
#size-cells = <0x0>;
ec@0 {
compatible = "google,cros-ec-fp", "google,cros-ec-spi";
reg = <0x0>;
interrupt-parent = <&gpio_controller>;
interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
spi-max-frequency = <3000000>;
reset-gpios = <&gpio_controller 5 GPIO_ACTIVE_LOW>;
boot0-gpios = <&gpio_controller 10 GPIO_ACTIVE_HIGH>;
vdd-supply = <&pp3300_fp_mcu>;
};
};
...
......@@ -48,6 +48,7 @@ examples:
cros-ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
interrupts = <101 0>;
cros_ec_pwm: pwm {
compatible = "google,cros-ec-pwm";
......
......@@ -41,6 +41,7 @@ examples:
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <99 0>;
regulator@0 {
compatible = "google,cros-ec-regulator";
......
......@@ -57,6 +57,7 @@ examples:
cros-ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
interrupts = <93 0>;
codecs {
#address-cells = <2>;
......
......@@ -4954,6 +4954,12 @@ S: Maintained
F: drivers/platform/chrome/cros_usbpd_notify.c
F: include/linux/platform_data/cros_usbpd_notify.h
CHROMEOS HPS DRIVER
M: Dan Callaghan <dcallagh@chromium.org>
R: Sami Kyöstilä <skyostil@chromium.org>
S: Maintained
F: drivers/platform/chrome/cros_hps_i2c.c
CHRONTEL CH7322 CEC DRIVER
M: Joe Tessler <jrt@google.com>
L: linux-media@vger.kernel.org
......
......@@ -228,6 +228,16 @@ config CROS_EC_TYPEC
To compile this driver as a module, choose M here: the module will be
called cros_ec_typec.
config CROS_HPS_I2C
tristate "ChromeOS HPS device"
depends on HID && I2C && PM
help
Say Y here if you want to enable support for the ChromeOS
human presence sensor (HPS), attached via I2C. The driver supports a
sensor connected to the I2C bus and exposes it as a character device.
To save power, the sensor is automatically powered down when no
clients are accessing it.
config CROS_USBPD_LOGGER
tristate "Logging driver for USB PD charger"
depends on CHARGER_CROS_USBPD
......
......@@ -27,6 +27,7 @@ obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o
obj-$(CONFIG_CROS_EC_SENSORHUB) += cros-ec-sensorhub.o
obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
obj-$(CONFIG_CROS_HPS_I2C) += cros_hps_i2c.o
obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o
obj-$(CONFIG_CROS_USBPD_NOTIFY) += cros_usbpd_notify.o
......
......@@ -521,6 +521,7 @@ static struct platform_driver cros_ec_debugfs_driver = {
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_debugfs_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = cros_ec_debugfs_probe,
.remove = cros_ec_debugfs_remove,
......
......@@ -286,8 +286,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
return ret;
}
static int cros_ec_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
static int cros_ec_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct cros_ec_device *ec_dev = NULL;
......@@ -373,7 +372,7 @@ static struct i2c_driver cros_ec_driver = {
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops,
},
.probe = cros_ec_i2c_probe,
.probe_new = cros_ec_i2c_probe,
.remove = cros_ec_i2c_remove,
.id_table = cros_ec_i2c_id,
};
......
......@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kobject.h>
#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>
......@@ -493,7 +494,7 @@ static ssize_t userspace_control_store(struct device *dev,
bool enable;
int ret;
ret = strtobool(buf, &enable);
ret = kstrtobool(buf, &enable);
if (ret < 0)
return ret;
......@@ -601,6 +602,7 @@ static struct platform_driver cros_ec_lightbar_driver = {
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_lightbar_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = cros_ec_lightbar_probe,
.remove = cros_ec_lightbar_remove,
......
......@@ -354,6 +354,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
return -EBUSY;
}
cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
/*
* Read the mapped ID twice, the first one is assuming the
* EC is a Microchip Embedded Controller (MEC) variant, if the
......@@ -554,6 +557,12 @@ static struct platform_driver cros_ec_lpc_driver = {
.name = DRV_NAME,
.acpi_match_table = cros_ec_lpc_acpi_device_ids,
.pm = &cros_ec_lpc_pm_ops,
/*
* ACPI child devices may probe before us, and they racily
* check our drvdata pointer. Force synchronous probe until
* those races are resolved.
*/
.probe_type = PROBE_FORCE_SYNCHRONOUS,
},
.probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove,
......@@ -586,14 +595,10 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
/* Register the driver */
ret = platform_driver_register(&cros_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
cros_ec_lpc_mec_destroy();
return ret;
}
......@@ -603,7 +608,6 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(&cros_ec_lpc_driver);
cros_ec_lpc_mec_destroy();
}
}
......@@ -615,7 +619,6 @@ static void __exit cros_ec_lpc_exit(void)
if (!cros_ec_lpc_acpi_device_found)
platform_device_unregister(&cros_ec_lpc_device);
platform_driver_unregister(&cros_ec_lpc_driver);
cros_ec_lpc_mec_destroy();
}
module_init(cros_ec_lpc_init);
......
......@@ -146,9 +146,3 @@ void cros_ec_lpc_mec_init(unsigned int base, unsigned int end)
mec_emi_end = end;
}
EXPORT_SYMBOL(cros_ec_lpc_mec_init);
void cros_ec_lpc_mec_destroy(void)
{
mutex_destroy(&io_mutex);
}
EXPORT_SYMBOL(cros_ec_lpc_mec_destroy);
......@@ -45,13 +45,6 @@ enum cros_ec_lpc_mec_io_type {
*/
void cros_ec_lpc_mec_init(unsigned int base, unsigned int end);
/*
* cros_ec_lpc_mec_destroy
*
* Cleanup MEC I/O.
*/
void cros_ec_lpc_mec_destroy(void);
/**
* cros_ec_lpc_mec_in_range() - Determine if addresses are in MEC EMI range.
*
......
......@@ -834,6 +834,7 @@ static struct spi_driver cros_ec_driver_spi = {
.name = "cros-ec-spi",
.of_match_table = cros_ec_spi_of_match,
.pm = &cros_ec_spi_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = cros_ec_spi_probe,
.remove = cros_ec_spi_remove,
......
......@@ -173,10 +173,13 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port,
role_sw_err:
typec_switch_put(port->ori_sw);
port->ori_sw = NULL;
ori_sw_err:
typec_retimer_put(port->retimer);
port->retimer = NULL;
retimer_sw_err:
typec_mux_put(port->mux);
port->mux = NULL;
mux_err:
return -ENODEV;
}
......
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the ChromeOS human presence sensor (HPS), attached via I2C.
*
* The driver exposes HPS as a character device, although currently no read or
* write operations are supported. Instead, the driver only controls the power
* state of the sensor, keeping it on only while userspace holds an open file
* descriptor to the HPS device.
*
* Copyright 2022 Google LLC.
*/
#include <linux/acpi.h>
#include <linux/fs.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#define HPS_ACPI_ID "GOOG0020"
struct hps_drvdata {
struct i2c_client *client;
struct miscdevice misc_device;
struct gpio_desc *enable_gpio;
};
static void hps_set_power(struct hps_drvdata *hps, bool state)
{
gpiod_set_value_cansleep(hps->enable_gpio, state);
}
static int hps_open(struct inode *inode, struct file *file)
{
struct hps_drvdata *hps = container_of(file->private_data,
struct hps_drvdata, misc_device);
struct device *dev = &hps->client->dev;
return pm_runtime_resume_and_get(dev);
}
static int hps_release(struct inode *inode, struct file *file)
{
struct hps_drvdata *hps = container_of(file->private_data,
struct hps_drvdata, misc_device);
struct device *dev = &hps->client->dev;
return pm_runtime_put(dev);
}
static const struct file_operations hps_fops = {
.owner = THIS_MODULE,
.open = hps_open,
.release = hps_release,
};
static int hps_i2c_probe(struct i2c_client *client)
{
struct hps_drvdata *hps;
int ret;
hps = devm_kzalloc(&client->dev, sizeof(*hps), GFP_KERNEL);
if (!hps)
return -ENOMEM;
hps->misc_device.parent = &client->dev;
hps->misc_device.minor = MISC_DYNAMIC_MINOR;
hps->misc_device.name = "cros-hps";
hps->misc_device.fops = &hps_fops;
i2c_set_clientdata(client, hps);
hps->client = client;
/*
* HPS is powered on from firmware before entering the kernel, so we
* acquire the line with GPIOD_OUT_HIGH here to preserve the existing
* state. The peripheral is powered off after successful probe below.
*/
hps->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(hps->enable_gpio)) {
ret = PTR_ERR(hps->enable_gpio);
dev_err(&client->dev, "failed to get enable gpio: %d\n", ret);
return ret;
}
ret = misc_register(&hps->misc_device);
if (ret) {
dev_err(&client->dev, "failed to initialize misc device: %d\n", ret);
return ret;
}
hps_set_power(hps, false);
pm_runtime_enable(&client->dev);
return 0;
}
static void hps_i2c_remove(struct i2c_client *client)
{
struct hps_drvdata *hps = i2c_get_clientdata(client);
pm_runtime_disable(&client->dev);
misc_deregister(&hps->misc_device);
/*
* Re-enable HPS, in order to return it to its default state
* (i.e. powered on).
*/
hps_set_power(hps, true);
}
static int hps_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct hps_drvdata *hps = i2c_get_clientdata(client);
hps_set_power(hps, false);
return 0;
}
static int hps_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct hps_drvdata *hps = i2c_get_clientdata(client);
hps_set_power(hps, true);
return 0;
}
static UNIVERSAL_DEV_PM_OPS(hps_pm_ops, hps_suspend, hps_resume, NULL);
static const struct i2c_device_id hps_i2c_id[] = {
{ "cros-hps", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, hps_i2c_id);
#ifdef CONFIG_ACPI
static const struct acpi_device_id hps_acpi_id[] = {
{ HPS_ACPI_ID, 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, hps_acpi_id);
#endif /* CONFIG_ACPI */
static struct i2c_driver hps_i2c_driver = {
.probe_new = hps_i2c_probe,
.remove = hps_i2c_remove,
.id_table = hps_i2c_id,
.driver = {
.name = "cros-hps",
.pm = &hps_pm_ops,
.acpi_match_table = ACPI_PTR(hps_acpi_id),
},
};
module_i2c_driver(hps_i2c_driver);
MODULE_ALIAS("acpi:" HPS_ACPI_ID);
MODULE_AUTHOR("Sami Kyöstilä <skyostil@chromium.org>");
MODULE_DESCRIPTION("Driver for ChromeOS HPS");
MODULE_LICENSE("GPL");
......@@ -239,7 +239,11 @@ static int __init cros_usbpd_notify_init(void)
return ret;
#ifdef CONFIG_ACPI
platform_driver_register(&cros_usbpd_notify_acpi_driver);
ret = platform_driver_register(&cros_usbpd_notify_acpi_driver);
if (ret) {
platform_driver_unregister(&cros_usbpd_notify_plat_driver);
return ret;
}
#endif
return 0;
}
......
......@@ -129,7 +129,6 @@ static int wilco_ec_probe(struct platform_device *pdev)
unregister_debugfs:
if (ec->debugfs_pdev)
platform_device_unregister(ec->debugfs_pdev);
cros_ec_lpc_mec_destroy();
return ret;
}
......@@ -143,10 +142,6 @@ static int wilco_ec_remove(struct platform_device *pdev)
platform_device_unregister(ec->rtc_pdev);
if (ec->debugfs_pdev)
platform_device_unregister(ec->debugfs_pdev);
/* Teardown cros_ec interface */
cros_ec_lpc_mec_destroy();
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment