#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/mfd/core.h>
#include <linux/mfd/cros_ec.h>
#include <linux/suspend.h>
#include <asm/unaligned.h>
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
};
-static const struct mfd_cell ec_cell = {
- .name = "cros-ec-dev",
- .platform_data = &ec_p,
- .pdata_size = sizeof(ec_p),
-};
-
-static const struct mfd_cell ec_pd_cell = {
- .name = "cros-ec-dev",
- .platform_data = &pd_p,
- .pdata_size = sizeof(pd_p),
-};
-
static irqreturn_t ec_irq_thread(int irq, void *data)
{
struct cros_ec_device *ec_dev = data;
}
}
- err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell,
- 1, NULL, ec_dev->irq, NULL);
- if (err) {
- dev_err(dev,
- "Failed to register Embedded Controller subdevice %d\n",
- err);
- return err;
+ /* Register a platform device for the main EC instance */
+ ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev",
+ PLATFORM_DEVID_AUTO, &ec_p,
+ sizeof(struct cros_ec_platform));
+ if (IS_ERR(ec_dev->ec)) {
+ dev_err(ec_dev->dev,
+ "Failed to create CrOS EC platform device\n");
+ return PTR_ERR(ec_dev->ec);
}
if (ec_dev->max_passthru) {
/*
- * Register a PD device as well on top of this device.
+ * Register a platform device for the PD behind the main EC.
* We make the following assumptions:
* - behind an EC, we have a pd
* - only one device added.
* - the EC is responsive at init time (it is not true for a
- * sensor hub.
+ * sensor hub).
*/
- err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO,
- &ec_pd_cell, 1, NULL, ec_dev->irq, NULL);
- if (err) {
- dev_err(dev,
- "Failed to register Power Delivery subdevice %d\n",
- err);
- return err;
+ ec_dev->pd = platform_device_register_data(ec_dev->dev,
+ "cros-ec-dev",
+ PLATFORM_DEVID_AUTO, &pd_p,
+ sizeof(struct cros_ec_platform));
+ if (IS_ERR(ec_dev->pd)) {
+ dev_err(ec_dev->dev,
+ "Failed to create CrOS PD platform device\n");
+ platform_device_unregister(ec_dev->ec);
+ return PTR_ERR(ec_dev->pd);
}
}
if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
err = devm_of_platform_populate(dev);
if (err) {
- mfd_remove_devices(dev);
+ platform_device_unregister(ec_dev->pd);
+ platform_device_unregister(ec_dev->ec);
dev_err(dev, "Failed to register sub-devices\n");
return err;
}
}
EXPORT_SYMBOL(cros_ec_register);
+int cros_ec_unregister(struct cros_ec_device *ec_dev)
+{
+ if (ec_dev->pd)
+ platform_device_unregister(ec_dev->pd);
+ platform_device_unregister(ec_dev->ec);
+
+ return 0;
+}
+EXPORT_SYMBOL(cros_ec_unregister);
+
#ifdef CONFIG_PM_SLEEP
int cros_ec_suspend(struct cros_ec_device *ec_dev)
{
* @event_data: Raw payload transferred with the MKBP event.
* @event_size: Size in bytes of the event data.
* @host_event_wake_mask: Mask of host events that cause wake from suspend.
+ * @ec: The platform_device used by the mfd driver to interface with the
+ * main EC.
+ * @pd: The platform_device used by the mfd driver to interface with the
+ * PD behind an EC.
*/
struct cros_ec_device {
/* These are used by other drivers that want to talk to the EC */
int event_size;
u32 host_event_wake_mask;
u32 last_resume_result;
+
+ /* The platform devices used by the mfd driver */
+ struct platform_device *ec;
+ struct platform_device *pd;
};
/**
int cros_ec_register(struct cros_ec_device *ec_dev);
/**
+ * cros_ec_unregister() - Remove a ChromeOS EC.
+ * @ec_dev: Device to unregister.
+ *
+ * Call this to deregister a ChromeOS EC, then clean up any private data.
+ *
+ * Return: 0 on success or negative error code.
+ */
+int cros_ec_unregister(struct cros_ec_device *ec_dev);
+
+/**
* cros_ec_query_all() - Query the protocol version supported by the
* ChromeOS EC.
* @ec_dev: Device to register.