brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · 3e6b6cd Raw
176 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Core driver for Wilco Embedded Controller4 *5 * Copyright 2018 Google LLC6 *7 * This is the entry point for the drivers that control the Wilco EC.8 */9 10#include <linux/acpi.h>11#include <linux/device.h>12#include <linux/ioport.h>13#include <linux/mod_devicetable.h>14#include <linux/module.h>15#include <linux/platform_data/wilco-ec.h>16#include <linux/platform_device.h>17 18#include "../cros_ec_lpc_mec.h"19 20#define DRV_NAME "wilco-ec"21 22static struct resource *wilco_get_resource(struct platform_device *pdev,23					   int index)24{25	struct device *dev = &pdev->dev;26	struct resource *res;27 28	res = platform_get_resource(pdev, IORESOURCE_IO, index);29	if (!res) {30		dev_dbg(dev, "Couldn't find IO resource %d\n", index);31		return res;32	}33 34	return devm_request_region(dev, res->start, resource_size(res),35				   dev_name(dev));36}37 38static int wilco_ec_probe(struct platform_device *pdev)39{40	struct device *dev = &pdev->dev;41	struct wilco_ec_device *ec;42	int ret;43 44	ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);45	if (!ec)46		return -ENOMEM;47 48	platform_set_drvdata(pdev, ec);49	ec->dev = dev;50	mutex_init(&ec->mailbox_lock);51 52	ec->data_size = sizeof(struct wilco_ec_response) + EC_MAILBOX_DATA_SIZE;53	ec->data_buffer = devm_kzalloc(dev, ec->data_size, GFP_KERNEL);54	if (!ec->data_buffer)55		return -ENOMEM;56 57	/* Prepare access to IO regions provided by ACPI */58	ec->io_data = wilco_get_resource(pdev, 0);	/* Host Data */59	ec->io_command = wilco_get_resource(pdev, 1);	/* Host Command */60	ec->io_packet = wilco_get_resource(pdev, 2);	/* MEC EMI */61	if (!ec->io_data || !ec->io_command || !ec->io_packet)62		return -ENODEV;63 64	/* Initialize cros_ec register interface for communication */65	cros_ec_lpc_mec_init(ec->io_packet->start,66			     ec->io_packet->start + EC_MAILBOX_DATA_SIZE);67 68	/*69	 * Register a child device that will be found by the debugfs driver.70	 * Ignore failure.71	 */72	ec->debugfs_pdev = platform_device_register_data(dev,73							 "wilco-ec-debugfs",74							 PLATFORM_DEVID_AUTO,75							 NULL, 0);76 77	/* Register a child device that will be found by the RTC driver. */78	ec->rtc_pdev = platform_device_register_data(dev, "rtc-wilco-ec",79						     PLATFORM_DEVID_AUTO,80						     NULL, 0);81	if (IS_ERR(ec->rtc_pdev)) {82		dev_err(dev, "Failed to create RTC platform device\n");83		ret = PTR_ERR(ec->rtc_pdev);84		goto unregister_debugfs;85	}86 87	/* Set up the keyboard backlight LEDs. */88	ret = wilco_keyboard_leds_init(ec);89	if (ret < 0) {90		dev_err(dev,91			"Failed to initialize keyboard LEDs: %d\n",92			ret);93		goto unregister_rtc;94	}95 96	ret = wilco_ec_add_sysfs(ec);97	if (ret < 0) {98		dev_err(dev, "Failed to create sysfs entries: %d\n", ret);99		goto unregister_rtc;100	}101 102	/* Register child device to be found by charger config driver. */103	ec->charger_pdev = platform_device_register_data(dev, "wilco-charger",104							 PLATFORM_DEVID_AUTO,105							 NULL, 0);106	if (IS_ERR(ec->charger_pdev)) {107		dev_err(dev, "Failed to create charger platform device\n");108		ret = PTR_ERR(ec->charger_pdev);109		goto remove_sysfs;110	}111 112	/* Register child device that will be found by the telemetry driver. */113	ec->telem_pdev = platform_device_register_data(dev, "wilco_telem",114						       PLATFORM_DEVID_AUTO,115						       ec, sizeof(*ec));116	if (IS_ERR(ec->telem_pdev)) {117		dev_err(dev, "Failed to create telemetry platform device\n");118		ret = PTR_ERR(ec->telem_pdev);119		goto unregister_charge_config;120	}121 122	return 0;123 124unregister_charge_config:125	platform_device_unregister(ec->charger_pdev);126remove_sysfs:127	wilco_ec_remove_sysfs(ec);128unregister_rtc:129	platform_device_unregister(ec->rtc_pdev);130unregister_debugfs:131	if (ec->debugfs_pdev)132		platform_device_unregister(ec->debugfs_pdev);133	return ret;134}135 136static void wilco_ec_remove(struct platform_device *pdev)137{138	struct wilco_ec_device *ec = platform_get_drvdata(pdev);139 140	platform_device_unregister(ec->telem_pdev);141	platform_device_unregister(ec->charger_pdev);142	wilco_ec_remove_sysfs(ec);143	platform_device_unregister(ec->rtc_pdev);144	if (ec->debugfs_pdev)145		platform_device_unregister(ec->debugfs_pdev);146}147 148static const struct acpi_device_id wilco_ec_acpi_device_ids[] = {149	{ "GOOG000C", 0 },150	{ }151};152MODULE_DEVICE_TABLE(acpi, wilco_ec_acpi_device_ids);153 154static const struct platform_device_id wilco_ec_id[] = {155	{ DRV_NAME, 0 },156	{}157};158MODULE_DEVICE_TABLE(platform, wilco_ec_id);159 160static struct platform_driver wilco_ec_driver = {161	.driver = {162		.name = DRV_NAME,163		.acpi_match_table = wilco_ec_acpi_device_ids,164	},165	.probe = wilco_ec_probe,166	.remove_new = wilco_ec_remove,167	.id_table = wilco_ec_id,168};169 170module_platform_driver(wilco_ec_driver);171 172MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>");173MODULE_AUTHOR("Duncan Laurie <dlaurie@chromium.org>");174MODULE_LICENSE("GPL v2");175MODULE_DESCRIPTION("ChromeOS Wilco Embedded Controller driver");176