2 * This file is part of the coreboot project.
4 * Copyright (C) 2013 Google Inc.
5 * Copyright (C) 2015 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; version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * 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 <reg_script.h>
25 #include <soc/iomap.h>
29 #include <soc/pattrs.h>
30 #include <soc/pci_devs.h>
32 #include <soc/ramstage.h>
37 * The LPE audio devices needs 1MiB of memory reserved aligned to a 512MiB
38 * address. Just take 1MiB @ 512MiB.
40 #define FIRMWARE_PHYS_BASE (512 << 20)
41 #define FIRMWARE_PHYS_LENGTH (1 << 20)
42 #define FIRMWARE_PCI_REG_BASE 0xa8
43 #define FIRMWARE_PCI_REG_LENGTH 0xac
44 #define FIRMWARE_REG_BASE_C0 0x144000
45 #define FIRMWARE_REG_LENGTH_C0 (FIRMWARE_REG_BASE_C0 + 4)
47 static void assign_device_nvs(device_t dev
, u32
*field
, unsigned index
)
51 res
= find_resource(dev
, index
);
56 static void lpe_enable_acpi_mode(device_t dev
)
58 static const struct reg_script ops
[] = {
59 /* Disable PCI interrupt, enable Memory and Bus Master */
60 REG_PCI_OR32(PCI_COMMAND
,
61 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
62 | PCI_COMMAND_INT_DISABLE
),
63 /* Enable ACPI mode */
64 REG_IOSF_OR(IOSF_PORT_0x58
, LPE_PCICFGCTR1
,
65 LPE_PCICFGCTR1_PCI_CFG_DIS
|
66 LPE_PCICFGCTR1_ACPI_INT_EN
),
71 /* Find ACPI NVS to update BARs */
72 gnvs
= cbmem_find(CBMEM_ID_ACPI_GNVS
);
74 printk(BIOS_ERR
, "Unable to locate Global NVS\n");
78 /* Save BAR0, BAR1, and firmware base to ACPI NVS */
79 assign_device_nvs(dev
, &gnvs
->dev
.lpe_bar0
, PCI_BASE_ADDRESS_0
);
80 /* LPE seems does not have BAR at PCI_BASE_ADDRESS_1 so disable it. */
81 /* assign_device_nvs(dev, &gnvs->dev.lpe_bar1, PCI_BASE_ADDRESS_1); */
82 assign_device_nvs(dev
, &gnvs
->dev
.lpe_fw
, FIRMWARE_PCI_REG_BASE
);
84 /* Device is enabled in ACPI mode */
87 /* Put device in ACPI mode */
88 reg_script_run_on_dev(dev
, ops
);
91 static void setup_codec_clock(device_t dev
)
95 struct soc_intel_braswell_config
*config
;
98 config
= dev
->chip_info
;
99 switch (config
->lpe_codec_clk_freq
) {
102 reg
= CLK_FREQ_19P2MHZ
;
106 reg
= CLK_FREQ_25MHZ
;
109 printk(BIOS_DEBUG
, "LPE codec clock not required.\n");
113 /* Default to always running. */
116 if (config
->lpe_codec_clk_num
< 0 || config
->lpe_codec_clk_num
> 5) {
117 printk(BIOS_DEBUG
, "Invalid LPE codec clock number.\n");
121 printk(BIOS_DEBUG
, "LPE Audio codec clock set to %sMHz.\n", freq_str
);
123 clk_reg
= (u32
*) (PMC_BASE_ADDRESS
+ PLT_CLK_CTL_0
);
124 clk_reg
+= config
->lpe_codec_clk_num
;
126 write32(clk_reg
, (read32(clk_reg
) & ~0x7) | reg
);
129 static void lpe_stash_firmware_info(device_t dev
)
131 struct resource
*res
;
132 struct resource
*mmio
;
134 res
= find_resource(dev
, FIRMWARE_PCI_REG_BASE
);
136 printk(BIOS_DEBUG
, "LPE Firmware memory not found.\n");
139 printk(BIOS_DEBUG
, "LPE FW Resource: 0x%08x\n", (u32
) res
->base
);
141 /* Continue using old way of informing firmware address / size. */
142 pci_write_config32(dev
, FIRMWARE_PCI_REG_BASE
, res
->base
);
143 pci_write_config32(dev
, FIRMWARE_PCI_REG_LENGTH
, res
->size
);
145 /* Also put the address in MMIO space like on C0 BTM */
146 mmio
= find_resource(dev
, PCI_BASE_ADDRESS_0
);
147 write32((void *)(uintptr_t)(mmio
->base
+ FIRMWARE_REG_BASE_C0
), \
149 write32((void *)(uintptr_t)(mmio
->base
+ FIRMWARE_REG_LENGTH_C0
), \
154 static void lpe_init(device_t dev
)
156 struct soc_intel_braswell_config
*config
= dev
->chip_info
;
158 printk(BIOS_SPEW
, "%s/%s ( %s )\n",
159 __FILE__
, __func__
, dev_name(dev
));
161 lpe_stash_firmware_info(dev
);
162 setup_codec_clock(dev
);
164 if (config
->lpe_acpi_mode
)
165 lpe_enable_acpi_mode(dev
);
168 static void lpe_read_resources(device_t dev
)
170 pci_dev_read_resources(dev
);
172 reserved_ram_resource(dev
, FIRMWARE_PCI_REG_BASE
,
173 FIRMWARE_PHYS_BASE
>> 10,
174 FIRMWARE_PHYS_LENGTH
>> 10);
177 static const struct device_operations device_ops
= {
178 .read_resources
= lpe_read_resources
,
179 .set_resources
= pci_dev_set_resources
,
180 .enable_resources
= pci_dev_enable_resources
,
184 .ops_pci
= &soc_pci_ops
,
187 static const struct pci_driver southcluster __pci_driver
= {
189 .vendor
= PCI_VENDOR_ID_INTEL
,