coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
lpe.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <device/pci_ops.h>
5 #include <acpi/acpi_gnvs.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <device/pci_ids.h>
10 #include <reg_script.h>
11 
12 #include <soc/iomap.h>
13 #include <soc/iosf.h>
14 #include <soc/lpc.h>
15 #include <soc/device_nvs.h>
16 #include <soc/pattrs.h>
17 #include <soc/pci_devs.h>
18 #include <soc/pm.h>
19 #include <soc/ramstage.h>
20 #include "chip.h"
21 
22 /*
23  * The LPE audio devices needs 1MiB of memory reserved aligned to a 512MiB
24  * address. Just take 1MiB @ 512MiB.
25  */
26 #define FIRMWARE_PHYS_BASE (512 << 20)
27 #define FIRMWARE_PHYS_LENGTH (1 << 20)
28 #define FIRMWARE_PCI_REG_BASE 0xa8
29 #define FIRMWARE_PCI_REG_LENGTH 0xac
30 #define FIRMWARE_REG_BASE_C0 0x144000
31 #define FIRMWARE_REG_LENGTH_C0 (FIRMWARE_REG_BASE_C0 + 4)
32 
33 static void assign_device_nvs(struct device *dev, u32 *field, unsigned int index)
34 {
35  struct resource *res;
36 
37  res = probe_resource(dev, index);
38  if (res)
39  *field = res->base;
40 }
41 
42 static void lpe_enable_acpi_mode(struct device *dev)
43 {
44  static const struct reg_script ops[] = {
45  /* Disable PCI interrupt, enable Memory and Bus Master */
48 
49  /* Enable ACPI mode */
50  REG_IOSF_OR(IOSF_PORT_0x58, LPE_PCICFGCTR1,
52 
54  };
55  struct device_nvs *dev_nvs = acpi_get_device_nvs();
56 
57  /* Save BAR0, BAR1, and firmware base to ACPI NVS */
61 
62  /* Device is enabled in ACPI mode */
63  dev_nvs->lpe_en = 1;
64 
65  /* Put device in ACPI mode */
67 }
68 
69 static void setup_codec_clock(struct device *dev)
70 {
71  uint32_t reg;
72  u32 *clk_reg;
74  const char *freq_str;
75 
76  config = config_of(dev);
77  switch (config->lpe_codec_clk_freq) {
78  case 19:
79  freq_str = "19.2";
80  reg = CLK_FREQ_19P2MHZ;
81  break;
82 
83  case 25:
84  freq_str = "25";
85  reg = CLK_FREQ_25MHZ;
86  break;
87 
88  default:
89  printk(BIOS_DEBUG, "LPE codec clock not required.\n");
90  return;
91  }
92 
93  /* Default to always running. */
94  reg |= CLK_CTL_ON;
95 
96  if (config->lpe_codec_clk_num < 0 || config->lpe_codec_clk_num > 5) {
97  printk(BIOS_DEBUG, "Invalid LPE codec clock number.\n");
98  return;
99  }
100 
101  printk(BIOS_DEBUG, "LPE Audio codec clock set to %sMHz.\n", freq_str);
102 
103  clk_reg = (u32 *)(PMC_BASE_ADDRESS + PLT_CLK_CTL_0);
104  clk_reg += config->lpe_codec_clk_num;
105 
106  write32(clk_reg, (read32(clk_reg) & ~0x7) | reg);
107 }
108 
109 static void lpe_stash_firmware_info(struct device *dev)
110 {
111  struct resource *res;
112  struct resource *mmio;
113  const struct pattrs *pattrs = pattrs_get();
114 
116  if (res == NULL) {
117  printk(BIOS_DEBUG, "LPE Firmware memory not found.\n");
118  return;
119  }
120 
121  /* Continue using old way of informing firmware address / size. */
124 
125  /* C0 and later steppings use an offset in the MMIO space. */
126  if (pattrs->stepping >= STEP_C0) {
127  mmio = find_resource(dev, PCI_BASE_ADDRESS_0);
129  res->base);
131  res->size);
132  }
133 }
134 
135 static void lpe_init(struct device *dev)
136 {
138 
140  setup_codec_clock(dev);
141 
142  if (config->lpe_acpi_mode)
144 }
145 
146 static void lpe_read_resources(struct device *dev)
147 {
149 
151  FIRMWARE_PHYS_BASE >> 10,
152  FIRMWARE_PHYS_LENGTH >> 10);
153 }
154 
155 static const struct device_operations device_ops = {
157  .set_resources = pci_dev_set_resources,
158  .enable_resources = pci_dev_enable_resources,
159  .init = lpe_init,
160  .ops_pci = &soc_pci_ops,
161 };
162 
163 static const struct pci_driver southcluster __pci_driver = {
164  .ops = &device_ops,
165  .vendor = PCI_VID_INTEL,
166  .device = LPE_DEVID,
167 };
void * acpi_get_device_nvs(void)
Definition: gnvs.c:53
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define LPE_PCICFGCTR1_ACPI_INT_EN
Definition: iosf.h:334
#define IOSF_PORT_0x58
Definition: iosf.h:106
#define LPE_PCICFGCTR1_PCI_CFG_DIS
Definition: iosf.h:333
#define LPE_PCICFGCTR1
Definition: iosf.h:332
static const struct pattrs * pattrs_get(void)
Definition: pattrs.h:41
#define CLK_CTL_ON
Definition: pm.h:110
#define PLT_CLK_CTL_0
Definition: pm.h:101
#define CLK_FREQ_25MHZ
Definition: pm.h:107
#define CLK_FREQ_19P2MHZ
Definition: pm.h:108
static void lpe_enable_acpi_mode(struct device *dev)
Definition: lpe.c:42
#define FIRMWARE_PHYS_BASE
Definition: lpe.c:26
#define FIRMWARE_REG_BASE_C0
Definition: lpe.c:30
static const struct device_operations device_ops
Definition: lpe.c:155
#define FIRMWARE_PHYS_LENGTH
Definition: lpe.c:27
static const struct pci_driver southcluster __pci_driver
Definition: lpe.c:163
#define FIRMWARE_PCI_REG_LENGTH
Definition: lpe.c:29
static void setup_codec_clock(struct device *dev)
Definition: lpe.c:69
static void assign_device_nvs(struct device *dev, u32 *field, unsigned int index)
Definition: lpe.c:33
static void lpe_read_resources(struct device *dev)
Definition: lpe.c:146
#define FIRMWARE_PCI_REG_BASE
Definition: lpe.c:28
#define FIRMWARE_REG_LENGTH_C0
Definition: lpe.c:31
static void lpe_init(struct device *dev)
Definition: lpe.c:135
static void lpe_stash_firmware_info(struct device *dev)
Definition: lpe.c:109
#define printk(level,...)
Definition: stdlib.h:16
struct resource * probe_resource(const struct device *dev, unsigned int index)
See if a resource structure already exists for a given index.
Definition: device_util.c:323
struct resource * find_resource(const struct device *dev, unsigned int index)
Return an existing resource structure for a given index.
Definition: device_util.c:394
static DEVTREE_CONST void * config_of(const struct device *dev)
Definition: device.h:382
#define reserved_ram_resource(dev, idx, basek, sizek)
Definition: device.h:324
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
#define PMC_BASE_ADDRESS
Definition: iomap.h:15
static struct device_operations ops
Definition: ipmi_kcs_ops.c:416
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
enum board_config config
Definition: memory.c:448
#define PCI_COMMAND_MASTER
Definition: pci_def.h:13
#define PCI_COMMAND_MEMORY
Definition: pci_def.h:12
#define PCI_COMMAND_INT_DISABLE
Definition: pci_def.h:21
#define PCI_BASE_ADDRESS_0
Definition: pci_def.h:63
#define PCI_COMMAND
Definition: pci_def.h:10
#define PCI_BASE_ADDRESS_1
Definition: pci_def.h:64
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_VID_INTEL
Definition: pci_ids.h:2157
void reg_script_run_on_dev(struct device *dev, const struct reg_script *step)
Definition: reg_script.c:689
#define REG_PCI_OR16(reg_, value_)
Definition: reg_script.h:185
#define REG_SCRIPT_END
Definition: reg_script.h:427
struct pci_operations soc_pci_ops
Definition: chip.c:51
@ STEP_C0
Definition: lpc.h:31
#define LPE_DEVID
Definition: pci_devs.h:118
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
u32 lpe_bar1
Definition: device_nvs.h:41
u32 lpe_bar0
Definition: device_nvs.h:36
u32 lpe_fw
Definition: device_nvs.h:44
void(* read_resources)(struct device *dev)
Definition: device.h:39
Definition: device.h:107
Definition: pattrs.h:22
int stepping
Definition: pattrs.h:29
resource_t base
Definition: resource.h:45
unsigned long index
Definition: resource.h:50
resource_t size
Definition: resource.h:46