4 * Module providing coreboot table access.
6 * Copyright 2017 Google Inc.
7 * Copyright 2017 Samuel Holland <samuel@sholland.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License v2.0 as published by
11 * the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
19 #include <linux/acpi.h>
20 #include <linux/device.h>
21 #include <linux/err.h>
22 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/slab.h>
30 #include "coreboot_table.h"
32 #define CB_DEV(d) container_of(d, struct coreboot_device, dev)
33 #define CB_DRV(d) container_of(d, struct coreboot_driver, drv)
35 static int coreboot_bus_match(struct device
*dev
, struct device_driver
*drv
)
37 struct coreboot_device
*device
= CB_DEV(dev
);
38 struct coreboot_driver
*driver
= CB_DRV(drv
);
40 return device
->entry
.tag
== driver
->tag
;
43 static int coreboot_bus_probe(struct device
*dev
)
46 struct coreboot_device
*device
= CB_DEV(dev
);
47 struct coreboot_driver
*driver
= CB_DRV(dev
->driver
);
50 ret
= driver
->probe(device
);
55 static int coreboot_bus_remove(struct device
*dev
)
58 struct coreboot_device
*device
= CB_DEV(dev
);
59 struct coreboot_driver
*driver
= CB_DRV(dev
->driver
);
62 ret
= driver
->remove(device
);
67 static struct bus_type coreboot_bus_type
= {
69 .match
= coreboot_bus_match
,
70 .probe
= coreboot_bus_probe
,
71 .remove
= coreboot_bus_remove
,
74 static void coreboot_device_release(struct device
*dev
)
76 struct coreboot_device
*device
= CB_DEV(dev
);
81 int coreboot_driver_register(struct coreboot_driver
*driver
)
83 driver
->drv
.bus
= &coreboot_bus_type
;
85 return driver_register(&driver
->drv
);
87 EXPORT_SYMBOL(coreboot_driver_register
);
89 void coreboot_driver_unregister(struct coreboot_driver
*driver
)
91 driver_unregister(&driver
->drv
);
93 EXPORT_SYMBOL(coreboot_driver_unregister
);
95 static int coreboot_table_populate(struct device
*dev
, void *ptr
)
99 struct coreboot_device
*device
;
100 struct coreboot_table_entry
*entry
;
101 struct coreboot_table_header
*header
= ptr
;
103 ptr_entry
= ptr
+ header
->header_bytes
;
104 for (i
= 0; i
< header
->table_entries
; i
++) {
107 device
= kzalloc(sizeof(struct device
) + entry
->size
, GFP_KERNEL
);
111 dev_set_name(&device
->dev
, "coreboot%d", i
);
112 device
->dev
.parent
= dev
;
113 device
->dev
.bus
= &coreboot_bus_type
;
114 device
->dev
.release
= coreboot_device_release
;
115 memcpy(&device
->entry
, ptr_entry
, entry
->size
);
117 ret
= device_register(&device
->dev
);
119 put_device(&device
->dev
);
123 ptr_entry
+= entry
->size
;
129 static int coreboot_table_probe(struct platform_device
*pdev
)
132 struct coreboot_table_header
*header
;
133 struct resource
*res
;
134 struct device
*dev
= &pdev
->dev
;
138 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
142 len
= resource_size(res
);
143 if (!res
->start
|| !len
)
146 /* Check just the header first to make sure things are sane */
147 header
= memremap(res
->start
, sizeof(*header
), MEMREMAP_WB
);
151 len
= header
->header_bytes
+ header
->table_bytes
;
152 ret
= strncmp(header
->signature
, "LBIO", sizeof(header
->signature
));
155 dev_warn(dev
, "coreboot table missing or corrupt!\n");
159 ptr
= memremap(res
->start
, len
, MEMREMAP_WB
);
163 ret
= bus_register(&coreboot_bus_type
);
165 ret
= coreboot_table_populate(dev
, ptr
);
167 bus_unregister(&coreboot_bus_type
);
174 static int coreboot_table_remove(struct platform_device
*pdev
)
176 bus_unregister(&coreboot_bus_type
);
181 static const struct acpi_device_id cros_coreboot_acpi_match
[] = {
186 MODULE_DEVICE_TABLE(acpi
, cros_coreboot_acpi_match
);
190 static const struct of_device_id coreboot_of_match
[] = {
191 { .compatible
= "coreboot" },
194 MODULE_DEVICE_TABLE(of
, coreboot_of_match
);
197 static struct platform_driver coreboot_table_driver
= {
198 .probe
= coreboot_table_probe
,
199 .remove
= coreboot_table_remove
,
201 .name
= "coreboot_table",
202 .acpi_match_table
= ACPI_PTR(cros_coreboot_acpi_match
),
203 .of_match_table
= of_match_ptr(coreboot_of_match
),
206 module_platform_driver(coreboot_table_driver
);
207 MODULE_AUTHOR("Google, Inc.");
208 MODULE_LICENSE("GPL");