FILE
core.c
File preview with syntax highlighting.
linux-6.19.14/drivers/platform/chrome/wilco_ec/core.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Core driver for Wilco Embedded Controller 4 * 5 * Copyright 2018 Google LLC 6 * 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 = 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");
~/
Read-only file preview.