| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */ | ||
|
|
||
| #ifndef _COMMONLIB_BSD_CBFS_PRIVATE_H_ | ||
| #define _COMMONLIB_BSD_CBFS_PRIVATE_H_ | ||
|
|
||
|
|
||
| #include <commonlib/bsd/cb_err.h> | ||
| #include <commonlib/bsd/cbfs_serialized.h> | ||
| #include <endian.h> | ||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
| #include <vb2_sha.h> | ||
|
|
||
| /* | ||
| * This header implements low-level CBFS access APIs that can be shared across different | ||
| * host applications (e.g. coreboot, libpayload, cbfstool). For verification purposes it | ||
| * implements the metadata hashing part but not the file hashing part, so the host application | ||
| * will need to verify file hashes itself after loading each file. Host applications that use | ||
| * verification should implement wrapper APIs that combine the lookup, loading and hashing steps | ||
| * into a single, safe function call and outside of the code implementing those APIs should not | ||
| * be accessing the low-level APIs in this file directly (e.g. coreboot SoC/driver code should | ||
| * never directly #include this file, and always use the higher level APIs in src/lib/cbfs.c). | ||
| * | ||
| * <cbfs_glue.h> needs to be provided by the host application using this CBFS library. It must | ||
| * define the following type, macros and functions: | ||
| * | ||
| * cbfs_dev_t An opaque type representing a CBFS storage backend. | ||
| * CBFS_ENABLE_HASHING Should be 0 to avoid linking hashing features, 1 otherwise. (Only for | ||
| * metadata hashing. Host application needs to check file hashes itself.) | ||
| * ERROR(...) printf-style macro to print errors. | ||
| * LOG(...) printf-style macro to print normal-operation log messages. | ||
| * DEBUG(...) printf-style macro to print detailed debug output. | ||
| * | ||
| * ssize_t cbfs_dev_read(cbfs_dev_t dev, void *buffer, size_t offset, size_t size); | ||
| * Read |size| bytes starting at |offset| from |dev| into |buffer|. | ||
| * Returns amount of bytes read on success and < 0 on error. | ||
| * This function *MUST* sanity-check offset/size on its own. | ||
| * | ||
| * size_t cbfs_dev_size(cbfs_dev_t dev); | ||
| * Return the total size in bytes of the CBFS storage (actual CBFS area). | ||
| */ | ||
| #include <cbfs_glue.h> | ||
|
|
||
| /* | ||
| * Helper structure to allocate space for a blob of metadata on the stack. | ||
| * NOTE: The fields in any union cbfs_mdata or any of its substructures from cbfs_serialized.h | ||
| * should always remain in the same byte order as they are stored on flash (= big endian). To | ||
| * avoid byte-order confusion, fields should always and only be converted to host byte order at | ||
| * exactly the time they are read from one of these structures into their own separate variable. | ||
| */ | ||
| #define CBFS_METADATA_MAX_SIZE 256 | ||
| union cbfs_mdata { | ||
| struct { | ||
| struct cbfs_file h; | ||
| char filename[]; | ||
| }; | ||
| uint8_t raw[CBFS_METADATA_MAX_SIZE]; | ||
| }; | ||
|
|
||
| /* Flags that modify behavior of cbfs_walk(). */ | ||
| enum cbfs_walk_flags { | ||
| /* Write the calculated hash back out to |metadata_hash->hash| rather than comparing it. | ||
| |metadata_hash->algo| must still have been initialized by the caller. */ | ||
| CBFS_WALK_WRITEBACK_HASH = (1 << 0), | ||
| /* Call |walker| for empty file entries (i.e. entries with one of the CBFS_TYPE_DELETED | ||
| types that mark free space in the CBFS). Otherwise, those entries will be skipped. | ||
| Either way, these entries are never included in the metadata_hash calculation. */ | ||
| CBFS_WALK_INCLUDE_EMPTY = (1 << 1), | ||
| }; | ||
|
|
||
| /* | ||
| * Traverse a CBFS and call a |walker| callback function for every file. Can additionally | ||
| * calculate a hash over the metadata of all files in the CBFS. If |metadata_hash| is NULL, | ||
| * hashing is disabled. If |walker| is NULL, will just traverse and hash the CBFS without | ||
| * invoking any callbacks (and always return CB_CBFS_NOT_FOUND unless there was another error). | ||
| * | ||
| * |arg| and |dev| will be passed through to |walker| unmodified. |offset| is the absolute | ||
| * offset in |dev| at which the current file metadata starts. |mdata| is a temporary buffer | ||
| * (only valid for the duration of this call to |walker|) containing already read metadata from | ||
| * the current file, up to |already_read| bytes. This will always at least contain the header | ||
| * fields and filename, but may contain more (i.e. attributes), depending on whether hashing is | ||
| * enabled. |walker| should call into cbfs_copy_fill_medadata() to copy the metadata of a file | ||
| * to a persistent buffer and automatically load remaining metadata from |dev| as needed based | ||
| * on the value of |already_read|. | ||
| * | ||
| * |walker| should return CB_CBFS_NOT_FOUND if it wants to continue being called for further | ||
| * files. Any other return code will be used as the final return code for cbfs_walk(). It will | ||
| * return immediately unless it needs to calculate a hash in which case it will still traverse | ||
| * the remaining CBFS (but not call |walker| anymore). | ||
| * | ||
| * Returns, from highest to lowest priority: | ||
| * CB_CBFS_IO - There was an IO error with the CBFS device (always considered fatal) | ||
| * CB_CBFS_HASH_MISMATCH - |metadata_hash| was provided and did not match the CBFS | ||
| * CB_SUCCESS/<other> - First non-CB_CBFS_NOT_FOUND code returned by walker() | ||
| * CB_CBFS_NOT_FOUND - walker() returned CB_CBFS_NOT_FOUND for every file in the CBFS | ||
| */ | ||
| cb_err_t cbfs_walk(cbfs_dev_t dev, cb_err_t (*walker)(cbfs_dev_t dev, size_t offset, | ||
| const union cbfs_mdata *mdata, | ||
| size_t already_read, void *arg), | ||
| void *arg, struct vb2_hash *metadata_hash, enum cbfs_walk_flags); | ||
|
|
||
| /* | ||
| * Helper function that can be used by a |walker| callback to cbfs_walk() to copy the metadata | ||
| * of a file into a permanent buffer. Will copy the |already_read| metadata from |src| into | ||
| * |dst| and load remaining metadata from |dev| as required. | ||
| */ | ||
| cb_err_t cbfs_copy_fill_metadata(union cbfs_mdata *dst, const union cbfs_mdata *src, | ||
| size_t already_read, cbfs_dev_t dev, size_t offset); | ||
|
|
||
| /* Find a file named |name| in the CBFS on |dev|. Copy its metadata (including attributes) | ||
| * into |mdata_out| and pass out the offset to the file data on the CBFS device. | ||
| * Verify the metadata with |metadata_hash| if provided. */ | ||
| cb_err_t cbfs_lookup(cbfs_dev_t dev, const char *name, union cbfs_mdata *mdata_out, | ||
| size_t *data_offset_out, struct vb2_hash *metadata_hash); | ||
|
|
||
| /* Both base address and size of CBFS mcaches must be aligned to this value! */ | ||
| #define CBFS_MCACHE_ALIGNMENT sizeof(uint32_t) /* Largest data type used in CBFS */ | ||
|
|
||
| /* Build an in-memory CBFS metadata cache out of the CBFS on |dev| into a |mcache_size| bytes | ||
| * memory area at |mcache|. Also verify |metadata_hash| unless it is NULL. If this returns | ||
| * CB_CBFS_CACHE_FULL, the mcache is still valid and can be used, but lookups may return | ||
| * CB_CBFS_CACHE_FULL for files that didn't fit to indicate that the caller needs to fall back | ||
| * to cbfs_lookup(). */ | ||
| cb_err_t cbfs_mcache_build(cbfs_dev_t dev, void *mcache, size_t mcache_size, | ||
| struct vb2_hash *metadata_hash); | ||
|
|
||
| /* | ||
| * Find a file named |name| in a CBFS metadata cache and copy its metadata into |mdata_out|. | ||
| * Pass out offset to the file data (on the original CBFS device used for cbfs_mcache_build()). | ||
| */ | ||
| cb_err_t cbfs_mcache_lookup(const void *mcache, size_t mcache_size, const char *name, | ||
| union cbfs_mdata *mdata_out, size_t *data_offset_out); | ||
|
|
||
| /* Returns the amount of bytes actually used by the CBFS metadata cache in |mcache|. */ | ||
| size_t cbfs_mcache_real_size(const void *mcache, size_t mcache_size); | ||
|
|
||
| #endif /* _COMMONLIB_BSD_CBFS_PRIVATE_H_ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,4 +2,3 @@ | |
|
|
||
| subdirs-$(CONFIG_CPU_AMD_PI_00630F01) += 00630F01 | ||
| subdirs-$(CONFIG_CPU_AMD_PI_00730F01) += 00730F01 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| /* Trick the linker into supporting x86_64 relocations in 32bit code */ | ||
| #if ENV_X86_64 | ||
| #define uintptr_t quad | ||
| #else | ||
| #define uintptr_t long | ||
| #endif | ||
|
|
||
| rom_mtrr_mask: | ||
| .uintptr_t _rom_mtrr_mask | ||
|
|
||
| rom_mtrr_base: | ||
| .uintptr_t _rom_mtrr_base | ||
|
|
||
| car_mtrr_mask: | ||
| .uintptr_t _car_mtrr_mask | ||
|
|
||
| car_mtrr_start: | ||
| .uintptr_t _car_mtrr_start |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <cpu/x86/msr.h> | ||
| #include <smbios.h> | ||
|
|
||
| /* This is not an architectural MSR. */ | ||
| #define MSR_PERF_STATUS 0x198 | ||
|
|
||
| unsigned int smbios_cpu_get_voltage(void) | ||
| { | ||
| return (rdmsr(MSR_PERF_STATUS).hi & 0xffff) * 10 / 8192; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <cpu/x86/smm.h> | ||
| #include <cpu/x86/save_state.h> | ||
|
|
||
| /* These are weakly linked such that platforms can link only the save state | ||
| ops they actually require. */ | ||
| const struct smm_save_state_ops *legacy_ops __weak = NULL; | ||
| const struct smm_save_state_ops *em64t100_ops __weak = NULL; | ||
| const struct smm_save_state_ops *em64t101_ops __weak = NULL; | ||
| const struct smm_save_state_ops *amd64_ops __weak = NULL; | ||
|
|
||
| static const struct smm_save_state_ops *save_state; | ||
|
|
||
| /* Returns -1 on failure, 0 on success */ | ||
| static int init_save_state(void) | ||
| { | ||
| const uint32_t revision = smm_revision(); | ||
| int i; | ||
| static bool initialized = false; | ||
| const struct smm_save_state_ops *save_state_ops[] = { | ||
| legacy_ops, | ||
| em64t100_ops, | ||
| em64t101_ops, | ||
| amd64_ops, | ||
| }; | ||
|
|
||
| if (initialized) | ||
| return 0; | ||
|
|
||
| for (i = 0; i < ARRAY_SIZE(save_state_ops); i++) { | ||
| const struct smm_save_state_ops *ops = save_state_ops[i]; | ||
| const uint32_t *rev; | ||
|
|
||
| if (ops == NULL) | ||
| continue; | ||
|
|
||
| for (rev = ops->revision_table; *rev != SMM_REV_INVALID; rev++) | ||
| if (*rev == revision) { | ||
| save_state = ops; | ||
| initialized = true; | ||
| return 0; | ||
| } | ||
| } | ||
|
|
||
| return -1; | ||
| } | ||
|
|
||
| int get_apmc_node(u8 cmd) | ||
| { | ||
| if (init_save_state()) | ||
| return -1; | ||
|
|
||
| return save_state->apmc_node(cmd); | ||
| } | ||
|
|
||
| int get_save_state_reg(const enum cpu_reg reg, const int node, void *out, const uint8_t length) | ||
| { | ||
| if (init_save_state()) | ||
| return -1; | ||
|
|
||
| if (node > CONFIG_MAX_CPUS) | ||
| return -1; | ||
|
|
||
| return save_state->get_reg(reg, node, out, length); | ||
| } | ||
|
|
||
| int set_save_state_reg(const enum cpu_reg reg, const int node, void *in, const uint8_t length) | ||
| { | ||
| if (init_save_state()) | ||
| return -1; | ||
|
|
||
| if (node > CONFIG_MAX_CPUS) | ||
| return -1; | ||
|
|
||
| return save_state->set_reg(reg, node, in, length); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| config DRIVERS_I2C_SX9324 | ||
| bool | ||
| default n | ||
| depends on HAVE_ACPI_TABLES | ||
| help | ||
| Board has a Semtech SX9324 proximity sensor. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_DRIVERS_I2C_SX9324) += sx9324.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __DRIVERS_I2C_SX9324_CHIP_H__ | ||
| #define __DRIVERS_I2C_SX9324_CHIP_H__ | ||
|
|
||
| #include <acpi/acpi_device.h> | ||
| #include <device/i2c_simple.h> | ||
|
|
||
| #define REGISTER(NAME) uint8_t NAME | ||
|
|
||
| struct drivers_i2c_sx9324_config { | ||
| /* Device Description */ | ||
| const char *desc; | ||
|
|
||
| /* ACPI _UID */ | ||
| unsigned int uid; | ||
|
|
||
| /* Bus speed in Hz, default is I2C_SPEED_FAST */ | ||
| enum i2c_speed speed; | ||
|
|
||
| /* Use GPIO-based interrupt instead of IO-APIC */ | ||
| struct acpi_gpio irq_gpio; | ||
|
|
||
| /* IO-APIC interrupt */ | ||
| struct acpi_irq irq; | ||
| #include "registers.h" | ||
| }; | ||
|
|
||
| #undef REGISTER | ||
|
|
||
| #endif /* __DRIVERS_I2C_SX9324_CHIP_H__ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef REGISTER | ||
| #error "define REGISTER(NAME) before including this file" | ||
| #endif | ||
|
|
||
| REGISTER(reg_gnrl_ctrl0); | ||
| REGISTER(reg_gnrl_ctrl1); | ||
|
|
||
| REGISTER(reg_afe_ctrl0); | ||
| REGISTER(reg_afe_ctrl1); | ||
| REGISTER(reg_afe_ctrl2); | ||
| REGISTER(reg_afe_ctrl3); | ||
| REGISTER(reg_afe_ctrl4); | ||
| REGISTER(reg_afe_ctrl5); | ||
| REGISTER(reg_afe_ctrl6); | ||
| REGISTER(reg_afe_ctrl7); | ||
| REGISTER(reg_afe_ctrl8); | ||
| REGISTER(reg_afe_ctrl9); | ||
|
|
||
| REGISTER(reg_prox_ctrl0); | ||
| REGISTER(reg_prox_ctrl1); | ||
| REGISTER(reg_prox_ctrl2); | ||
| REGISTER(reg_prox_ctrl3); | ||
| REGISTER(reg_prox_ctrl4); | ||
| REGISTER(reg_prox_ctrl5); | ||
| REGISTER(reg_prox_ctrl6); | ||
| REGISTER(reg_prox_ctrl7); | ||
|
|
||
| REGISTER(reg_adv_ctrl0); | ||
| REGISTER(reg_adv_ctrl1); | ||
| REGISTER(reg_adv_ctrl2); | ||
| REGISTER(reg_adv_ctrl3); | ||
| REGISTER(reg_adv_ctrl4); | ||
| REGISTER(reg_adv_ctrl5); | ||
| REGISTER(reg_adv_ctrl6); | ||
| REGISTER(reg_adv_ctrl7); | ||
| REGISTER(reg_adv_ctrl8); | ||
| REGISTER(reg_adv_ctrl9); | ||
| REGISTER(reg_adv_ctrl10); | ||
| REGISTER(reg_adv_ctrl11); | ||
| REGISTER(reg_adv_ctrl12); | ||
| REGISTER(reg_adv_ctrl13); | ||
| REGISTER(reg_adv_ctrl14); | ||
| REGISTER(reg_adv_ctrl15); | ||
| REGISTER(reg_adv_ctrl16); | ||
| REGISTER(reg_adv_ctrl17); | ||
| REGISTER(reg_adv_ctrl18); | ||
| REGISTER(reg_adv_ctrl19); | ||
| REGISTER(reg_adv_ctrl20); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <acpi/acpi_device.h> | ||
| #include <acpi/acpigen.h> | ||
| #include <console/console.h> | ||
| #include <device/i2c_simple.h> | ||
| #include <device/device.h> | ||
| #include <device/path.h> | ||
| #include <string.h> | ||
| #include "chip.h" | ||
|
|
||
| #define I2C_SX9324_ACPI_ID "STH9324" | ||
| #define I2C_SX9324_CHIP_NAME "Semtech SX9324" | ||
|
|
||
| #define REGISTER(NAME) acpi_dp_add_integer(dsd, \ | ||
| I2C_SX9324_ACPI_ID "," #NAME, \ | ||
| config->NAME) | ||
|
|
||
| static void i2c_sx9324_fill_ssdt(const struct device *dev) | ||
| { | ||
| struct drivers_i2c_sx9324_config *config = dev->chip_info; | ||
| const char *scope = acpi_device_scope(dev); | ||
| struct acpi_i2c i2c = { | ||
| .address = dev->path.i2c.device, | ||
| .mode_10bit = dev->path.i2c.mode_10bit, | ||
| .speed = I2C_SPEED_FAST, | ||
| .resource = scope, | ||
| }; | ||
| struct acpi_dp *dsd; | ||
|
|
||
| if (!scope || !config) | ||
| return; | ||
|
|
||
| if (config->speed) | ||
| i2c.speed = config->speed; | ||
|
|
||
| /* Device */ | ||
| acpigen_write_scope(scope); | ||
| acpigen_write_device(acpi_device_name(dev)); | ||
| acpigen_write_name_string("_HID", I2C_SX9324_ACPI_ID); | ||
| acpigen_write_name_integer("_UID", config->uid); | ||
| acpigen_write_name_string("_DDN", config->desc); | ||
| acpigen_write_STA(acpi_device_status(dev)); | ||
|
|
||
| /* Resources */ | ||
| acpigen_write_name("_CRS"); | ||
| acpigen_write_resourcetemplate_header(); | ||
| acpi_device_write_i2c(&i2c); | ||
|
|
||
| if (config->irq_gpio.pin_count) | ||
| acpi_device_write_gpio(&config->irq_gpio); | ||
| else | ||
| acpi_device_write_interrupt(&config->irq); | ||
|
|
||
| acpigen_write_resourcetemplate_footer(); | ||
|
|
||
| /* DSD */ | ||
| dsd = acpi_dp_new_table("_DSD"); | ||
| #include "registers.h" | ||
| acpi_dp_write(dsd); | ||
|
|
||
| acpigen_pop_len(); /* Device */ | ||
| acpigen_pop_len(); /* Scope */ | ||
|
|
||
| printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), | ||
| config->desc ? : dev->chip_ops->name, dev_path(dev)); | ||
| } | ||
|
|
||
| #undef REGISTER | ||
|
|
||
| static const char *i2c_sx9324_acpi_name(const struct device *dev) | ||
| { | ||
| static char name[5]; | ||
|
|
||
| snprintf(name, sizeof(name), "SX%02.2X", dev->path.i2c.device); | ||
| return name; | ||
| } | ||
|
|
||
| static struct device_operations i2c_sx9324_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .acpi_name = i2c_sx9324_acpi_name, | ||
| .acpi_fill_ssdt = i2c_sx9324_fill_ssdt, | ||
| }; | ||
|
|
||
| static void i2c_sx9324_enable(struct device *dev) | ||
| { | ||
| struct drivers_i2c_sx9324_config *config = dev->chip_info; | ||
|
|
||
| if (!config) { | ||
| dev->enabled = 0; | ||
| return; | ||
| } | ||
|
|
||
| dev->ops = &i2c_sx9324_ops; | ||
|
|
||
| if (config->desc) | ||
| dev->name = config->desc; | ||
| } | ||
|
|
||
| struct chip_operations drivers_i2c_sx9324_ops = { | ||
| CHIP_NAME(I2C_SX9324_CHIP_NAME) | ||
| .enable_dev = i2c_sx9324_enable | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <arch/symbols.h> | ||
| #include <console/console.h> | ||
| #include <fsp/util.h> | ||
|
|
||
| /* filled in assembly after FSP-T ran */ | ||
| uintptr_t temp_memory_start; | ||
| uintptr_t temp_memory_end; | ||
|
|
||
| void report_fsp_output(void) | ||
| { | ||
| const struct region fsp_car_region = { | ||
| .offset = temp_memory_start, | ||
| .size = temp_memory_end - temp_memory_start, | ||
| }; | ||
| const struct region coreboot_car_region = { | ||
| .offset = (uintptr_t)_car_region_start, | ||
| .size = (uintptr_t)_car_region_size, | ||
| }; | ||
| printk(BIOS_DEBUG, "FSP: reported temp_mem region: [0x%08lx,0x%08lx)\n", | ||
| temp_memory_start, temp_memory_end); | ||
| if (!region_is_subregion(&fsp_car_region, &coreboot_car_region)) { | ||
| printk(BIOS_ERR, "Wrong CAR region used!\n"); | ||
| printk(BIOS_ERR, "Adapt DCACHE_RAM_BASE and DCACHE_RAM_SIZE to match FSP-T\n"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <arch/symbols.h> | ||
| #include <console/console.h> | ||
| #include <fsp/util.h> | ||
|
|
||
| /* filled in assembly after FSP-T ran */ | ||
| uintptr_t temp_memory_start; | ||
| uintptr_t temp_memory_end; | ||
|
|
||
| void report_fspt_output(void) | ||
| { | ||
| const struct region fsp_car_region = { | ||
| .offset = temp_memory_start, | ||
| .size = temp_memory_end - temp_memory_start, | ||
| }; | ||
| const struct region coreboot_car_region = { | ||
| .offset = (uintptr_t)_car_region_start, | ||
| .size = (uintptr_t)_car_region_size, | ||
| }; | ||
| printk(BIOS_DEBUG, "FSP-T: reported temp_mem region: [0x%08lx,0x%08lx)\n", | ||
| temp_memory_start, temp_memory_end); | ||
| if (!region_is_subregion(&fsp_car_region, &coreboot_car_region)) { | ||
| printk(BIOS_ERR, "Wrong CAR region used!\n"); | ||
| printk(BIOS_ERR, "Adapt CONFIG_DCACHE_RAM_BASE and CONFIG_DCACHE_RAM_SIZE to match FSP-T\n"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,11 +17,6 @@ config HAS_RECOVERY_MRC_CACHE | |
| bool | ||
| default n | ||
|
|
||
| config MRC_SETTINGS_VARIABLE_DATA | ||
| bool | ||
| default n | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| config DRIVERS_SOUNDWIRE_ALC711 | ||
| bool |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_DRIVERS_SOUNDWIRE_ALC711) += alc711.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <acpi/acpigen.h> | ||
| #include <acpi/acpi_device.h> | ||
| #include <acpi/acpi_soundwire.h> | ||
| #include <device/device.h> | ||
| #include <device/path.h> | ||
| #include <device/mipi_ids.h> | ||
| #include <device/soundwire.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "chip.h" | ||
|
|
||
| static struct soundwire_address alc711_address = { | ||
| .version = SOUNDWIRE_VERSION_1_1, | ||
| .manufacturer_id = MIPI_MFG_ID_REALTEK, | ||
| .part_id = MIPI_DEV_ID_REALTEK_ALC711, | ||
| .class = MIPI_CLASS_NONE | ||
| }; | ||
|
|
||
| static struct soundwire_slave alc711_slave = { | ||
| .wake_up_unavailable = false, | ||
| .test_mode_supported = false, | ||
| .clock_stop_mode1_supported = true, | ||
| .simplified_clockstopprepare_sm_supported = true, | ||
| .clockstopprepare_hard_reset_behavior = false, | ||
| .highPHY_capable = false, | ||
| .paging_supported = false, | ||
| .bank_delay_supported = false, | ||
| .port15_read_behavior = false, | ||
| .source_port_list = SOUNDWIRE_PORT(2), | ||
| .sink_port_list = SOUNDWIRE_PORT(1), | ||
| }; | ||
|
|
||
| static struct soundwire_audio_mode alc711_audio_mode = { | ||
| /* Bus frequency must be 1/2/4/8 divider of supported input frequencies. */ | ||
| .bus_frequency_configs_count = 12, | ||
| .bus_frequency_configs = { | ||
| 9600 * KHz, | ||
| 4800 * KHz, | ||
| 2400 * KHz, | ||
| 1200 * KHz, | ||
| 12000 * KHz, | ||
| 6000 * KHz, | ||
| 3000 * KHz, | ||
| 1500 * KHz, | ||
| 12288 * KHz, | ||
| 6144 * KHz, | ||
| 3072 * KHz, | ||
| 1536 * KHz | ||
| }, | ||
| /* Support 16 KHz to 192 KHz sampling frequency */ | ||
| .sampling_frequency_configs_count = 9, | ||
| .sampling_frequency_configs = { | ||
| 16 * KHz, | ||
| 22.05 * KHz, | ||
| 24 * KHz, | ||
| 32 * KHz, | ||
| 44.1 * KHz, | ||
| 48 * KHz, | ||
| 88.2 * KHz, | ||
| 96 * KHz, | ||
| 192 * KHz | ||
| }, | ||
| .prepare_channel_behavior = CHANNEL_PREPARE_ANY_FREQUENCY | ||
| }; | ||
|
|
||
| static struct soundwire_dpn alc711_dp = { | ||
| .port_wordlength_configs_count = 1, | ||
| .port_wordlength_configs = { 32 }, | ||
| .data_port_type = FULL_DATA_PORT, | ||
| .max_grouping_supported = BLOCK_GROUP_COUNT_1, | ||
| .simplified_channelprepare_sm = false, | ||
| .imp_def_dpn_interrupts_supported = 0, | ||
| .min_channel_number = 1, | ||
| .max_channel_number = 2, | ||
| .modes_supported = MODE_ISOCHRONOUS | MODE_TX_CONTROLLED | | ||
| MODE_RX_CONTROLLED | MODE_FULL_ASYNCHRONOUS, | ||
| .block_packing_mode = true, | ||
| .port_audio_mode_count = 1, | ||
| .port_audio_mode_list = { 0 } | ||
| }; | ||
|
|
||
| static const struct soundwire_codec alc711_codec = { | ||
| .slave = &alc711_slave, | ||
| .audio_mode = { &alc711_audio_mode }, | ||
| .dpn = { | ||
| { | ||
| /* Data Input for Speaker Path */ | ||
| .port = 1, | ||
| .sink = &alc711_dp | ||
| }, | ||
| { | ||
| /* Data Output for DSP Path */ | ||
| .port = 2, | ||
| .source = &alc711_dp | ||
| } | ||
| } | ||
|
|
||
| }; | ||
|
|
||
| static void soundwire_alc711_fill_ssdt(const struct device *dev) | ||
| { | ||
| struct drivers_soundwire_alc711_config *config = dev->chip_info; | ||
| const char *scope = acpi_device_scope(dev); | ||
| struct acpi_dp *dsd; | ||
|
|
||
| if (!scope) | ||
| return; | ||
|
|
||
| acpigen_write_scope(scope); | ||
| acpigen_write_device(acpi_device_name(dev)); | ||
|
|
||
| /* Set codec address IDs. */ | ||
| alc711_address.link_id = dev->path.generic.id; | ||
| alc711_address.unique_id = dev->path.generic.subid; | ||
|
|
||
| acpigen_write_ADR_soundwire_device(&alc711_address); | ||
| acpigen_write_name_string("_DDN", config->desc ? : dev->chip_ops->name); | ||
| acpigen_write_STA(acpi_device_status(dev)); | ||
|
|
||
| dsd = acpi_dp_new_table("_DSD"); | ||
| soundwire_gen_codec(dsd, &alc711_codec, NULL); | ||
| acpi_dp_write(dsd); | ||
|
|
||
| acpigen_pop_len(); /* Device */ | ||
| acpigen_pop_len(); /* Scope */ | ||
| } | ||
|
|
||
| static const char *soundwire_alc711_acpi_name(const struct device *dev) | ||
| { | ||
| struct drivers_soundwire_alc711_config *config = dev->chip_info; | ||
| static char name[5]; | ||
|
|
||
| if (config->name) | ||
| return config->name; | ||
| snprintf(name, sizeof(name), "SW%1X%1X", dev->path.generic.id, dev->path.generic.subid); | ||
| return name; | ||
| } | ||
|
|
||
| static struct device_operations soundwire_alc711_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .acpi_name = soundwire_alc711_acpi_name, | ||
| .acpi_fill_ssdt = soundwire_alc711_fill_ssdt, | ||
| }; | ||
|
|
||
| static void soundwire_alc711_enable(struct device *dev) | ||
| { | ||
| dev->ops = &soundwire_alc711_ops; | ||
| } | ||
|
|
||
| struct chip_operations drivers_soundwire_alc711_ops = { | ||
| CHIP_NAME("Realtek ALC711 SoundWire Codec") | ||
| .enable_dev = soundwire_alc711_enable | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __DRIVERS_SOUNDWIRE_ALC711_CHIP_H__ | ||
| #define __DRIVERS_SOUNDWIRE_ALC711_CHIP_H__ | ||
|
|
||
| struct drivers_soundwire_alc711_config { | ||
| const char *name; | ||
| const char *desc; | ||
| }; | ||
|
|
||
| #endif /* __DRIVERS_SOUNDWIRE_ALC711_CHIP_H__ */ |