diff options
author | Rodrigo Vivi <rodrigo.vivi@intel.com> | 2018-07-23 09:13:12 -0700 |
---|---|---|
committer | Rodrigo Vivi <rodrigo.vivi@intel.com> | 2018-07-23 09:13:12 -0700 |
commit | c74a7469f97c0f40b46e82ee979f9fb1bb6e847c (patch) | |
tree | f2690a1a916b73ef94657fbf0e0141ae57701825 /drivers/firmware/google/coreboot_table.c | |
parent | 6f15a7de86c8cf2dc09fc9e6d07047efa40ef809 (diff) | |
parent | 500775074f88d9cf5416bed2ca19592812d62c41 (diff) |
Merge drm/drm-next into drm-intel-next-queued
We need a backmerge to get DP_DPCD_REV_14 before we push other
i915 changes to dinq that could break compilation.
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Diffstat (limited to 'drivers/firmware/google/coreboot_table.c')
-rw-r--r-- | drivers/firmware/google/coreboot_table.c | 130 |
1 files changed, 97 insertions, 33 deletions
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index 0019d3ec18dd..19db5709ae28 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -4,6 +4,7 @@ * Module providing coreboot table access. * * Copyright 2017 Google Inc. + * Copyright 2017 Samuel Holland <samuel@sholland.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License v2.0 as published by @@ -15,37 +16,96 @@ * GNU General Public License for more details. */ +#include <linux/device.h> #include <linux/err.h> #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/slab.h> #include "coreboot_table.h" -struct coreboot_table_entry { - u32 tag; - u32 size; -}; +#define CB_DEV(d) container_of(d, struct coreboot_device, dev) +#define CB_DRV(d) container_of(d, struct coreboot_driver, drv) static struct coreboot_table_header __iomem *ptr_header; -/* - * This function parses the coreboot table for an entry that contains the base - * address of the given entry tag. The coreboot table consists of a header - * directly followed by a number of small, variable-sized entries, which each - * contain an identifying tag and their length as the first two fields. - */ -int coreboot_table_find(int tag, void *data, size_t data_size) +static int coreboot_bus_match(struct device *dev, struct device_driver *drv) { - struct coreboot_table_header header; - struct coreboot_table_entry entry; - void *ptr_entry; - int i; + struct coreboot_device *device = CB_DEV(dev); + struct coreboot_driver *driver = CB_DRV(drv); - if (!ptr_header) - return -EPROBE_DEFER; + return device->entry.tag == driver->tag; +} +static int coreboot_bus_probe(struct device *dev) +{ + int ret = -ENODEV; + struct coreboot_device *device = CB_DEV(dev); + struct coreboot_driver *driver = CB_DRV(dev->driver); + + if (driver->probe) + ret = driver->probe(device); + + return ret; +} + +static int coreboot_bus_remove(struct device *dev) +{ + int ret = 0; + struct coreboot_device *device = CB_DEV(dev); + struct coreboot_driver *driver = CB_DRV(dev->driver); + + if (driver->remove) + ret = driver->remove(device); + + return ret; +} + +static struct bus_type coreboot_bus_type = { + .name = "coreboot", + .match = coreboot_bus_match, + .probe = coreboot_bus_probe, + .remove = coreboot_bus_remove, +}; + +static int __init coreboot_bus_init(void) +{ + return bus_register(&coreboot_bus_type); +} +module_init(coreboot_bus_init); + +static void coreboot_device_release(struct device *dev) +{ + struct coreboot_device *device = CB_DEV(dev); + + kfree(device); +} + +int coreboot_driver_register(struct coreboot_driver *driver) +{ + driver->drv.bus = &coreboot_bus_type; + + return driver_register(&driver->drv); +} +EXPORT_SYMBOL(coreboot_driver_register); + +void coreboot_driver_unregister(struct coreboot_driver *driver) +{ + driver_unregister(&driver->drv); +} +EXPORT_SYMBOL(coreboot_driver_unregister); + +int coreboot_table_init(struct device *dev, void __iomem *ptr) +{ + int i, ret; + void *ptr_entry; + struct coreboot_device *device; + struct coreboot_table_entry entry; + struct coreboot_table_header header; + + ptr_header = ptr; memcpy_fromio(&header, ptr_header, sizeof(header)); if (strncmp(header.signature, "LBIO", sizeof(header.signature))) { @@ -54,37 +114,41 @@ int coreboot_table_find(int tag, void *data, size_t data_size) } ptr_entry = (void *)ptr_header + header.header_bytes; - for (i = 0; i < header.table_entries; i++) { memcpy_fromio(&entry, ptr_entry, sizeof(entry)); - if (entry.tag == tag) { - if (data_size < entry.size) - return -EINVAL; - memcpy_fromio(data, ptr_entry, entry.size); + device = kzalloc(sizeof(struct device) + entry.size, GFP_KERNEL); + if (!device) { + ret = -ENOMEM; + break; + } + + dev_set_name(&device->dev, "coreboot%d", i); + device->dev.parent = dev; + device->dev.bus = &coreboot_bus_type; + device->dev.release = coreboot_device_release; + memcpy_fromio(&device->entry, ptr_entry, entry.size); - return 0; + ret = device_register(&device->dev); + if (ret) { + put_device(&device->dev); + break; } ptr_entry += entry.size; } - return -ENOENT; -} -EXPORT_SYMBOL(coreboot_table_find); - -int coreboot_table_init(void __iomem *ptr) -{ - ptr_header = ptr; - - return 0; + return ret; } EXPORT_SYMBOL(coreboot_table_init); int coreboot_table_exit(void) { - if (ptr_header) + if (ptr_header) { + bus_unregister(&coreboot_bus_type); iounmap(ptr_header); + ptr_header = NULL; + } return 0; } |