2 * This file is part of the coreboot project.
4 * Copyright (C) 2015-2016 Intel Corp.
5 * (Written by Lance Zhao <lijian.zhao@intel.com> for Intel Corp.)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
19 #include <console/console.h>
20 #include <device/device.h>
21 #include <device/pci.h>
22 #include <device/pci_ids.h>
23 #include <pc80/mc146818rtc.h>
27 #include <vboot/vbnv.h>
33 * The purpose of this driver is to eliminate manual resource allocation for
34 * devices under the LPC bridge.
37 * The resource allocator reserves IO and memory resources to devices on the
38 * LPC bus, but it is up to the hardware driver to make sure that those
39 * resources are decoded to the LPC bus. This is what this driver does.
41 * THEORY OF OPERATION:
42 * The .scan_bus member of the driver's ops will scan the static device tree
43 * (devicetree.cb) and invoke drivers of devices on the LPC bus. This creates
44 * a list of child devices, along with their resources. set_child_resources()
45 * parses that list and looks for resources needed by the child devices. It
46 * opens up IO and memory windows as needed.
49 static void rtc_init(void)
52 const struct chipset_power_state
*ps
= cbmem_find(CBMEM_ID_POWER_STATE
);
55 printk(BIOS_ERR
, "Could not find power state in cbmem, RTC init aborted\n");
59 rtc_fail
= !!(ps
->gen_pmcon1
& RPS
);
60 /* Ensure the date is set including century byte. */
61 cmos_check_update_date();
62 if (IS_ENABLED(CONFIG_VBOOT_VBNV_CMOS
))
63 init_vbnv_cmos(rtc_fail
);
68 static void lpc_init(struct device
*dev
)
71 struct soc_intel_apollolake_config
*cfg
;
75 printk(BIOS_ERR
, "BUG! Could not find SOC devicetree config\n");
79 scnt
= pci_read_config8(dev
, REG_SERIRQ_CTL
);
80 scnt
&= ~(SCNT_EN
| SCNT_MODE
);
81 if (cfg
->serirq_mode
== SERIRQ_QUIET
)
83 else if (cfg
->serirq_mode
== SERIRQ_CONTINUOUS
)
84 scnt
|= SCNT_EN
| SCNT_MODE
;
85 pci_write_config8(dev
, REG_SERIRQ_CTL
, scnt
);
91 static void soc_lpc_add_io_resources(device_t dev
)
95 /* Add the default claimed legacy IO range for the LPC device. */
96 res
= new_resource(dev
, 0);
99 res
->flags
= IORESOURCE_IO
| IORESOURCE_ASSIGNED
| IORESOURCE_FIXED
;
102 static void soc_lpc_read_resources(device_t dev
)
104 /* Get the PCI resources of this device. */
105 pci_dev_read_resources(dev
);
107 /* Add IO resources to LPC. */
108 soc_lpc_add_io_resources(dev
);
111 static void set_child_resources(struct device
*dev
);
113 static void loop_resources(struct device
*dev
)
115 struct resource
*res
;
117 for (res
= dev
->resource_list
; res
; res
= res
->next
) {
119 if (res
->flags
& IORESOURCE_IO
)
120 lpc_open_pmio_window(res
->base
, res
->size
);
122 if (res
->flags
& IORESOURCE_MEM
) {
123 /* Check if this is already decoded. */
124 if (lpc_fits_fixed_mmio_window(res
->base
, res
->size
))
127 lpc_open_mmio_window(res
->base
, res
->size
);
131 set_child_resources(dev
);
135 * Loop through all the child devices' resources, and open up windows to the
136 * LPC bus, as appropriate.
138 static void set_child_resources(struct device
*dev
)
141 struct device
*child
;
143 for (link
= dev
->link_list
; link
; link
= link
->next
) {
144 for (child
= link
->children
; child
; child
= child
->sibling
)
145 loop_resources(child
);
149 static void set_resources(device_t dev
)
151 pci_dev_set_resources(dev
);
153 /* Close all previously opened windows and allocate from scratch. */
154 lpc_close_pmio_windows();
155 /* Now open up windows to devices which have declared resources. */
156 set_child_resources(dev
);
159 static struct device_operations device_ops
= {
160 .read_resources
= &soc_lpc_read_resources
,
161 .set_resources
= set_resources
,
162 .enable_resources
= &pci_dev_enable_resources
,
163 .write_acpi_tables
= southbridge_write_acpi_tables
,
164 .acpi_inject_dsdt_generator
= southbridge_inject_dsdt
,
166 .scan_bus
= scan_lpc_bus
,
169 static const unsigned short pci_device_ids
[] = {
170 PCI_DEVICE_ID_INTEL_APL_LPC
,
171 PCI_DEVICE_ID_INTEL_GLK_LPC
,
175 static const struct pci_driver soc_lpc __pci_driver
= {
177 .vendor
= PCI_VENDOR_ID_INTEL
,
178 .devices
= pci_device_ids
,