blob: f049e68c221a1ad105d0ba4fca1a282ad9512bd4 [file] [log] [blame]
Duncan Laurie4721f432018-05-07 15:24:10 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2018 Google LLC
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <arch/acpi_device.h>
17#include <arch/acpi_pld.h>
18#include <arch/acpigen.h>
19#include <console/console.h>
20#include <device/device.h>
21#include <device/path.h>
22#include <stdint.h>
23#include <string.h>
24#include "chip.h"
25
Nick Vaccaro0a495eb2018-11-12 19:43:35 -080026static bool usb_acpi_add_gpios_to_crs(struct drivers_usb_acpi_config *cfg)
27{
28 /*
29 * Return false if reset GPIO is not provided.
30 */
31 if (cfg->reset_gpio.pin_count == 0)
32 return false;
33
34 return true;
35}
36
Duncan Laurie4721f432018-05-07 15:24:10 -070037static void usb_acpi_fill_ssdt_generator(struct device *dev)
38{
39 struct drivers_usb_acpi_config *config = dev->chip_info;
40 const char *path = acpi_device_path(dev);
41
42 if (!dev->enabled || !path || !config)
43 return;
44
45 /* Don't generate output for hubs, only ports */
46 if (config->type == UPC_TYPE_HUB)
47 return;
48
49 acpigen_write_scope(path);
50 if (config->desc)
51 acpigen_write_name_string("_DDN", config->desc);
52 acpigen_write_upc(config->type);
53
54 if (config->use_custom_pld) {
55 /* Use board defined PLD */
56 acpigen_write_pld(&config->custom_pld);
57 } else {
58 /* Fill PLD strucutre based on port type */
59 struct acpi_pld pld;
60 acpi_pld_fill_usb(&pld, config->type);
61 acpigen_write_pld(&pld);
62 }
63
Nick Vaccaro0a495eb2018-11-12 19:43:35 -080064 /* Resources */
65 if (usb_acpi_add_gpios_to_crs(config) == true) {
66 struct acpi_dp *dsd;
67
68 acpigen_write_name("_CRS");
69 acpigen_write_resourcetemplate_header();
70 acpi_device_write_gpio(&config->reset_gpio);
71 acpigen_write_resourcetemplate_footer();
72
73 dsd = acpi_dp_new_table("_DSD");
74 acpi_dp_add_gpio(dsd, "reset-gpio", path, 0, 0,
75 config->reset_gpio.polarity);
76 acpi_dp_write(dsd);
77 }
78
Duncan Laurie4721f432018-05-07 15:24:10 -070079 acpigen_pop_len();
80
81 printk(BIOS_INFO, "%s: %s at %s\n", path,
82 config->desc ? : dev->chip_ops->name, dev_path(dev));
83}
84
85static struct device_operations usb_acpi_ops = {
86 .read_resources = DEVICE_NOOP,
87 .set_resources = DEVICE_NOOP,
88 .enable_resources = DEVICE_NOOP,
89 .scan_bus = &scan_usb_bus,
90 .acpi_fill_ssdt_generator = &usb_acpi_fill_ssdt_generator,
91};
92
93static void usb_acpi_enable(struct device *dev)
94{
95 dev->ops = &usb_acpi_ops;
96}
97
98struct chip_operations drivers_usb_acpi_ops = {
99 CHIP_NAME("USB ACPI Device")
100 .enable_dev = &usb_acpi_enable
101};