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: ...@@ -48,6 +48,7 @@ examples:
cros_ec: ec@0 { cros_ec: ec@0 {
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
interrupts = <35 0>;
typec { typec {
compatible = "google,cros-ec-typec"; compatible = "google,cros-ec-typec";
......
...@@ -27,6 +27,7 @@ examples: ...@@ -27,6 +27,7 @@ examples:
cros_ec: ec@0 { cros_ec: ec@0 {
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
interrupts = <15 0>;
kbd-led-backlight { kbd-led-backlight {
compatible = "google,cros-kbd-led-backlight"; compatible = "google,cros-kbd-led-backlight";
......
...@@ -40,6 +40,7 @@ examples: ...@@ -40,6 +40,7 @@ examples:
cros-ec@0 { cros-ec@0 {
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
interrupts = <44 0>;
usbc_extcon0: extcon0 { usbc_extcon0: extcon0 {
compatible = "google,extcon-usbc-cros-ec"; compatible = "google,extcon-usbc-cros-ec";
......
...@@ -47,6 +47,7 @@ examples: ...@@ -47,6 +47,7 @@ examples:
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
spi-max-frequency = <5000000>; spi-max-frequency = <5000000>;
interrupts = <99 0>;
i2c-tunnel { i2c-tunnel {
compatible = "google,cros-ec-i2c-tunnel"; compatible = "google,cros-ec-i2c-tunnel";
......
...@@ -20,19 +20,21 @@ properties: ...@@ -20,19 +20,21 @@ properties:
compatible: compatible:
oneOf: oneOf:
- description: - description:
For implementations of the EC is connected through I2C. For implementations of the EC connected through I2C.
const: google,cros-ec-i2c const: google,cros-ec-i2c
- description: - description:
For implementations of the EC is connected through SPI. For implementations of the EC connected through SPI.
const: google,cros-ec-spi const: google,cros-ec-spi
- description: - 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 const: google,cros-ec-rpmsg
controller-data: controller-data: true
description:
SPI controller data, see bindings/spi/samsung,spi-peripheral-props.yaml
type: object
google,cros-ec-spi-pre-delay: google,cros-ec-spi-pre-delay:
description: description:
...@@ -62,8 +64,7 @@ properties: ...@@ -62,8 +64,7 @@ properties:
the SCP. the SCP.
$ref: "/schemas/types.yaml#/definitions/string" $ref: "/schemas/types.yaml#/definitions/string"
spi-max-frequency: spi-max-frequency: true
description: Maximum SPI frequency of the device in Hz.
reg: reg:
maxItems: 1 maxItems: 1
...@@ -71,6 +72,15 @@ properties: ...@@ -71,6 +72,15 @@ properties:
interrupts: interrupts:
maxItems: 1 maxItems: 1
reset-gpios:
maxItems: 1
boot0-gpios:
maxItems: 1
description: Assert for bootloader mode.
vdd-supply: true
wakeup-source: wakeup-source:
description: Button can wake-up the system. description: Button can wake-up the system.
...@@ -155,18 +165,67 @@ allOf: ...@@ -155,18 +165,67 @@ allOf:
- if: - if:
properties: properties:
compatible: compatible:
contains: not:
enum: contains:
- google,cros-ec-i2c const: google,cros-ec-spi
- google,cros-ec-rpmsg
then: then:
properties: properties:
controller-data: false
google,cros-ec-spi-pre-delay: false google,cros-ec-spi-pre-delay: false
google,cros-ec-spi-msg-delay: false google,cros-ec-spi-msg-delay: false
spi-max-frequency: false spi-max-frequency: false
else: else:
$ref: /schemas/spi/spi-peripheral-props.yaml $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 additionalProperties: false
examples: examples:
...@@ -222,4 +281,22 @@ examples: ...@@ -222,4 +281,22 @@ examples:
compatible = "google,cros-ec-rpmsg"; 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: ...@@ -48,6 +48,7 @@ examples:
cros-ec@0 { cros-ec@0 {
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
interrupts = <101 0>;
cros_ec_pwm: pwm { cros_ec_pwm: pwm {
compatible = "google,cros-ec-pwm"; compatible = "google,cros-ec-pwm";
......
...@@ -41,6 +41,7 @@ examples: ...@@ -41,6 +41,7 @@ examples:
reg = <0>; reg = <0>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
interrupts = <99 0>;
regulator@0 { regulator@0 {
compatible = "google,cros-ec-regulator"; compatible = "google,cros-ec-regulator";
......
...@@ -57,6 +57,7 @@ examples: ...@@ -57,6 +57,7 @@ examples:
cros-ec@0 { cros-ec@0 {
compatible = "google,cros-ec-spi"; compatible = "google,cros-ec-spi";
reg = <0>; reg = <0>;
interrupts = <93 0>;
codecs { codecs {
#address-cells = <2>; #address-cells = <2>;
......
...@@ -4954,6 +4954,12 @@ S: Maintained ...@@ -4954,6 +4954,12 @@ S: Maintained
F: drivers/platform/chrome/cros_usbpd_notify.c F: drivers/platform/chrome/cros_usbpd_notify.c
F: include/linux/platform_data/cros_usbpd_notify.h 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 CHRONTEL CH7322 CEC DRIVER
M: Joe Tessler <jrt@google.com> M: Joe Tessler <jrt@google.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
......
...@@ -228,6 +228,16 @@ config CROS_EC_TYPEC ...@@ -228,6 +228,16 @@ config CROS_EC_TYPEC
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called cros_ec_typec. 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 config CROS_USBPD_LOGGER
tristate "Logging driver for USB PD charger" tristate "Logging driver for USB PD charger"
depends on CHARGER_CROS_USBPD depends on CHARGER_CROS_USBPD
......
...@@ -27,6 +27,7 @@ obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o ...@@ -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 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_SENSORHUB) += cros-ec-sensorhub.o
obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.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_LOGGER) += cros_usbpd_logger.o
obj-$(CONFIG_CROS_USBPD_NOTIFY) += cros_usbpd_notify.o obj-$(CONFIG_CROS_USBPD_NOTIFY) += cros_usbpd_notify.o
......
...@@ -521,6 +521,7 @@ static struct platform_driver cros_ec_debugfs_driver = { ...@@ -521,6 +521,7 @@ static struct platform_driver cros_ec_debugfs_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.pm = &cros_ec_debugfs_pm_ops, .pm = &cros_ec_debugfs_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
}, },
.probe = cros_ec_debugfs_probe, .probe = cros_ec_debugfs_probe,
.remove = cros_ec_debugfs_remove, .remove = cros_ec_debugfs_remove,
......
...@@ -286,8 +286,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev, ...@@ -286,8 +286,7 @@ static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
return ret; return ret;
} }
static int cros_ec_i2c_probe(struct i2c_client *client, static int cros_ec_i2c_probe(struct i2c_client *client)
const struct i2c_device_id *dev_id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct cros_ec_device *ec_dev = NULL; struct cros_ec_device *ec_dev = NULL;
...@@ -373,7 +372,7 @@ static struct i2c_driver cros_ec_driver = { ...@@ -373,7 +372,7 @@ static struct i2c_driver cros_ec_driver = {
.of_match_table = of_match_ptr(cros_ec_i2c_of_match), .of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops, .pm = &cros_ec_i2c_pm_ops,
}, },
.probe = cros_ec_i2c_probe, .probe_new = cros_ec_i2c_probe,
.remove = cros_ec_i2c_remove, .remove = cros_ec_i2c_remove,
.id_table = cros_ec_i2c_id, .id_table = cros_ec_i2c_id,
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/kstrtox.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h> #include <linux/platform_data/cros_ec_proto.h>
...@@ -493,7 +494,7 @@ static ssize_t userspace_control_store(struct device *dev, ...@@ -493,7 +494,7 @@ static ssize_t userspace_control_store(struct device *dev,
bool enable; bool enable;
int ret; int ret;
ret = strtobool(buf, &enable); ret = kstrtobool(buf, &enable);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -601,6 +602,7 @@ static struct platform_driver cros_ec_lightbar_driver = { ...@@ -601,6 +602,7 @@ static struct platform_driver cros_ec_lightbar_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.pm = &cros_ec_lightbar_pm_ops, .pm = &cros_ec_lightbar_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
}, },
.probe = cros_ec_lightbar_probe, .probe = cros_ec_lightbar_probe,
.remove = cros_ec_lightbar_remove, .remove = cros_ec_lightbar_remove,
......
...@@ -354,6 +354,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) ...@@ -354,6 +354,9 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
return -EBUSY; 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 * Read the mapped ID twice, the first one is assuming the
* EC is a Microchip Embedded Controller (MEC) variant, if the * EC is a Microchip Embedded Controller (MEC) variant, if the
...@@ -554,6 +557,12 @@ static struct platform_driver cros_ec_lpc_driver = { ...@@ -554,6 +557,12 @@ static struct platform_driver cros_ec_lpc_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.acpi_match_table = cros_ec_lpc_acpi_device_ids, .acpi_match_table = cros_ec_lpc_acpi_device_ids,
.pm = &cros_ec_lpc_pm_ops, .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, .probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove, .remove = cros_ec_lpc_remove,
...@@ -586,14 +595,10 @@ static int __init cros_ec_lpc_init(void) ...@@ -586,14 +595,10 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV; return -ENODEV;
} }
cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
/* Register the driver */ /* Register the driver */
ret = platform_driver_register(&cros_ec_lpc_driver); ret = platform_driver_register(&cros_ec_lpc_driver);
if (ret) { if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret); pr_err(DRV_NAME ": can't register driver: %d\n", ret);
cros_ec_lpc_mec_destroy();
return ret; return ret;
} }
...@@ -603,7 +608,6 @@ static int __init cros_ec_lpc_init(void) ...@@ -603,7 +608,6 @@ static int __init cros_ec_lpc_init(void)
if (ret) { if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret); pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(&cros_ec_lpc_driver); platform_driver_unregister(&cros_ec_lpc_driver);
cros_ec_lpc_mec_destroy();
} }
} }
...@@ -615,7 +619,6 @@ static void __exit cros_ec_lpc_exit(void) ...@@ -615,7 +619,6 @@ static void __exit cros_ec_lpc_exit(void)
if (!cros_ec_lpc_acpi_device_found) if (!cros_ec_lpc_acpi_device_found)
platform_device_unregister(&cros_ec_lpc_device); platform_device_unregister(&cros_ec_lpc_device);
platform_driver_unregister(&cros_ec_lpc_driver); platform_driver_unregister(&cros_ec_lpc_driver);
cros_ec_lpc_mec_destroy();
} }
module_init(cros_ec_lpc_init); module_init(cros_ec_lpc_init);
......
...@@ -146,9 +146,3 @@ void cros_ec_lpc_mec_init(unsigned int base, unsigned int end) ...@@ -146,9 +146,3 @@ void cros_ec_lpc_mec_init(unsigned int base, unsigned int end)
mec_emi_end = end; mec_emi_end = end;
} }
EXPORT_SYMBOL(cros_ec_lpc_mec_init); 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 { ...@@ -45,13 +45,6 @@ enum cros_ec_lpc_mec_io_type {
*/ */
void cros_ec_lpc_mec_init(unsigned int base, unsigned int end); 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. * 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 = { ...@@ -834,6 +834,7 @@ static struct spi_driver cros_ec_driver_spi = {
.name = "cros-ec-spi", .name = "cros-ec-spi",
.of_match_table = cros_ec_spi_of_match, .of_match_table = cros_ec_spi_of_match,
.pm = &cros_ec_spi_pm_ops, .pm = &cros_ec_spi_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
}, },
.probe = cros_ec_spi_probe, .probe = cros_ec_spi_probe,
.remove = cros_ec_spi_remove, .remove = cros_ec_spi_remove,
......
...@@ -173,10 +173,13 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port, ...@@ -173,10 +173,13 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port,
role_sw_err: role_sw_err:
typec_switch_put(port->ori_sw); typec_switch_put(port->ori_sw);
port->ori_sw = NULL;
ori_sw_err: ori_sw_err:
typec_retimer_put(port->retimer); typec_retimer_put(port->retimer);
port->retimer = NULL;
retimer_sw_err: retimer_sw_err:
typec_mux_put(port->mux); typec_mux_put(port->mux);
port->mux = NULL;
mux_err: mux_err:
return -ENODEV; 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) ...@@ -239,7 +239,11 @@ static int __init cros_usbpd_notify_init(void)
return ret; return ret;
#ifdef CONFIG_ACPI #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 #endif
return 0; return 0;
} }
......
...@@ -129,7 +129,6 @@ static int wilco_ec_probe(struct platform_device *pdev) ...@@ -129,7 +129,6 @@ static int wilco_ec_probe(struct platform_device *pdev)
unregister_debugfs: unregister_debugfs:
if (ec->debugfs_pdev) if (ec->debugfs_pdev)
platform_device_unregister(ec->debugfs_pdev); platform_device_unregister(ec->debugfs_pdev);
cros_ec_lpc_mec_destroy();
return ret; return ret;
} }
...@@ -143,10 +142,6 @@ static int wilco_ec_remove(struct platform_device *pdev) ...@@ -143,10 +142,6 @@ static int wilco_ec_remove(struct platform_device *pdev)
platform_device_unregister(ec->rtc_pdev); platform_device_unregister(ec->rtc_pdev);
if (ec->debugfs_pdev) if (ec->debugfs_pdev)
platform_device_unregister(ec->debugfs_pdev); platform_device_unregister(ec->debugfs_pdev);
/* Teardown cros_ec interface */
cros_ec_lpc_mec_destroy();
return 0; 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