1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpi_gnvs.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <device/mmio.h>
11 #include <soc/device_nvs.h>
14 #include <soc/intel/broadwell/pch/chip.h>
15 #include <southbridge/intel/lynxpoint/iobp.h>
18 static void adsp_init(struct device
*dev
)
20 const struct soc_intel_broadwell_pch_config
*config
= config_of(dev
);
21 struct resource
*bar0
, *bar1
;
24 /* Ensure memory and bus master are enabled */
25 pci_or_config16(dev
, PCI_COMMAND
, PCI_COMMAND_MASTER
| PCI_COMMAND_MEMORY
);
27 /* Find BAR0 and BAR1 */
28 bar0
= probe_resource(dev
, PCI_BASE_ADDRESS_0
);
31 bar1
= probe_resource(dev
, PCI_BASE_ADDRESS_1
);
36 * Set LTR value in DSP shim LTR control register to 3ms
37 * SNOOP_REQ[13]=1b SNOOP_SCALE[12:10]=100b (1ms) SNOOP_VAL[9:0]=3h
39 tmp32
= pch_is_wpt() ? ADSP_SHIM_BASE_WPT
: ADSP_SHIM_BASE_LPT
;
40 write32(res2mmio(bar0
, tmp32
+ ADSP_SHIM_LTRC
, 0),
41 ADSP_SHIM_LTRC_VALUE
);
43 /* Program VDRTCTL2 D19:F0:A8[31:0] = 0x00000fff */
44 pci_write_config32(dev
, ADSP_PCI_VDRTCTL2
, ADSP_VDRTCTL2_VALUE
);
46 /* Program ADSP IOBP VDLDAT1 to 0x040100 */
47 pch_iobp_write(ADSP_IOBP_VDLDAT1
, ADSP_VDLDAT1_VALUE
);
49 /* Set D3 Power Gating Enable in D19:F0:A0 based on PCH type */
50 tmp32
= pci_read_config32(dev
, ADSP_PCI_VDRTCTL0
);
52 if (config
->adsp_d3_pg_enable
) {
53 tmp32
&= ~ADSP_VDRTCTL0_D3PGD_WPT
;
54 if (config
->adsp_sram_pg_enable
)
55 tmp32
&= ~ADSP_VDRTCTL0_D3SRAMPGD_WPT
;
57 tmp32
|= ADSP_VDRTCTL0_D3SRAMPGD_WPT
;
59 tmp32
|= ADSP_VDRTCTL0_D3PGD_WPT
;
62 if (config
->adsp_d3_pg_enable
) {
63 tmp32
&= ~ADSP_VDRTCTL0_D3PGD_LPT
;
64 if (config
->adsp_sram_pg_enable
)
65 tmp32
&= ~ADSP_VDRTCTL0_D3SRAMPGD_LPT
;
67 tmp32
|= ADSP_VDRTCTL0_D3SRAMPGD_LPT
;
69 tmp32
|= ADSP_VDRTCTL0_D3PGD_LPT
;
72 pci_write_config32(dev
, ADSP_PCI_VDRTCTL0
, tmp32
);
74 /* Set PSF Snoop to SA, RCBA+0x3350[10]=1b */
75 RCBA32_OR(0x3350, (1 << 10));
77 /* Set DSP IOBP PMCTL 0x1e0=0x3f */
78 pch_iobp_write(ADSP_IOBP_PMCTL
, ADSP_PMCTL_VALUE
);
80 if (config
->sio_acpi_mode
) {
81 struct device_nvs
*dev_nvs
= acpi_get_device_nvs();
83 /* Configure for ACPI mode */
84 printk(BIOS_INFO
, "ADSP: Enable ACPI Mode IRQ3\n");
86 /* Save BAR0 and BAR1 to ACPI NVS */
87 dev_nvs
->bar0
[SIO_NVS_ADSP
] = (u32
)bar0
->base
;
88 dev_nvs
->bar1
[SIO_NVS_ADSP
] = (u32
)bar1
->base
;
89 dev_nvs
->enable
[SIO_NVS_ADSP
] = 1;
91 /* Set PCI Config Disable Bit */
92 pch_iobp_update(ADSP_IOBP_PCICFGCTL
, ~0, ADSP_PCICFGCTL_PCICD
);
94 /* Set interrupt de-assert/assert opcode override to IRQ3 */
95 pch_iobp_write(ADSP_IOBP_VDLDAT2
, ADSP_IOBP_ACPI_IRQ3
);
97 /* Enable IRQ3 in RCBA */
98 RCBA32_OR(ACPIIRQEN
, ADSP_ACPI_IRQEN
);
100 /* Set ACPI Interrupt Enable Bit */
101 pch_iobp_update(ADSP_IOBP_PCICFGCTL
, ~ADSP_PCICFGCTL_SPCBAD
,
102 ADSP_PCICFGCTL_ACPIIE
);
104 /* Put ADSP in D3hot */
105 tmp32
= read32(res2mmio(bar1
, PCH_PCS
, 0));
106 tmp32
|= PCH_PCS_PS_D3HOT
;
107 write32(res2mmio(bar1
, PCH_PCS
, 0), tmp32
);
109 printk(BIOS_INFO
, "ADSP: Enable PCI Mode IRQ23\n");
111 /* Configure for PCI mode */
112 pci_write_config8(dev
, PCI_INTERRUPT_LINE
, ADSP_PCI_IRQ
);
114 /* Clear ACPI Interrupt Enable Bit */
115 pch_iobp_update(ADSP_IOBP_PCICFGCTL
,
116 ~(ADSP_PCICFGCTL_SPCBAD
| ADSP_PCICFGCTL_ACPIIE
), 0);
120 static struct device_operations adsp_ops
= {
121 .read_resources
= pci_dev_read_resources
,
122 .set_resources
= pci_dev_set_resources
,
123 .enable_resources
= pci_dev_enable_resources
,
125 .ops_pci
= &pci_dev_ops_pci
,
128 static const unsigned short pci_device_ids
[] = {
129 0x9c36, /* LynxPoint */
130 0x9cb6, /* WildcatPoint */
134 static const struct pci_driver pch_adsp __pci_driver
= {
136 .vendor
= PCI_VID_INTEL
,
137 .devices
= pci_device_ids
,