]> Git Repo - linux.git/blob - drivers/platform/chrome/wilco_ec/core.c
crypto: akcipher - Drop sign/verify operations
[linux.git] / 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
22 static 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
38 static 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
124 unregister_charge_config:
125         platform_device_unregister(ec->charger_pdev);
126 remove_sysfs:
127         wilco_ec_remove_sysfs(ec);
128 unregister_rtc:
129         platform_device_unregister(ec->rtc_pdev);
130 unregister_debugfs:
131         if (ec->debugfs_pdev)
132                 platform_device_unregister(ec->debugfs_pdev);
133         return ret;
134 }
135
136 static 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
148 static const struct acpi_device_id wilco_ec_acpi_device_ids[] = {
149         { "GOOG000C", 0 },
150         { }
151 };
152 MODULE_DEVICE_TABLE(acpi, wilco_ec_acpi_device_ids);
153
154 static const struct platform_device_id wilco_ec_id[] = {
155         { DRV_NAME, 0 },
156         {}
157 };
158 MODULE_DEVICE_TABLE(platform, wilco_ec_id);
159
160 static 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
170 module_platform_driver(wilco_ec_driver);
171
172 MODULE_AUTHOR("Nick Crews <[email protected]>");
173 MODULE_AUTHOR("Duncan Laurie <[email protected]>");
174 MODULE_LICENSE("GPL v2");
175 MODULE_DESCRIPTION("ChromeOS Wilco Embedded Controller driver");
This page took 0.040563 seconds and 4 git commands to generate.