| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| # Supermicro X11SSH-F | ||
|
|
||
| This section details how to run coreboot on the [Supermicro X11SSH-F]. | ||
|
|
||
| ## Flashing coreboot | ||
|
|
||
| The board can be flashed externally. [STM32-based programmers] worked. | ||
|
|
||
| The flash IC "W25Q128.V" (detected by flashrom) can be found near PCH PCIe Slot 4. It is sometime | ||
| socketed, and covered by a sticker, hindering the observation of its precise model. | ||
|
|
||
| It can be programmed in-system with a clip like pomona 5250. | ||
|
|
||
| ## BMC (IPMI) | ||
|
|
||
| This board has an ASPEED [AST2400], which has BMC/[IPMI] functionality. The BMC firmware resides in a | ||
| 32 MiB SOIC-16 chip in the corner of the mainboard near the PCH PCIe Slot 4. This chip is a | ||
| [MX25L25635F]. | ||
|
|
||
| ## IGD | ||
|
|
||
| If an IGD is integrated with CPU, it will be enabled on this board. Though there is no video output | ||
| for it (The onboard VGA port is connected to BMC), it is said to be capable of being used for compute | ||
| tasks, or for offloading graphics rendering via "muxless" [vga_witcheroo]. | ||
|
|
||
| ## Tested and working | ||
|
|
||
| - SeaBIOS payload to boot Kali Linux live USB | ||
| - ECC ram (Linux' ie31200 driver works) | ||
| - Integrated graphics device available without output | ||
| - USB ports | ||
| - Ethernet | ||
| - SATA ports | ||
| - RS232 external | ||
| - PCIe slots | ||
| - BMC (IPMI) | ||
| - VGA on Aspeed | ||
| - TPM on TPM expansion header | ||
|
|
||
| ## Known issues | ||
|
|
||
| - See general issue section | ||
| - S3 resume not working (vendor and coreboot) | ||
| - SeaBIOS cannot make use of VGA on Aspeed (even if IGD is disabled) | ||
|
|
||
| ## ToDo | ||
|
|
||
| - Fix known issues | ||
| - Testing other payloads | ||
|
|
||
| ## Technology | ||
|
|
||
| ```eval_rst | ||
| +------------------+--------------------------------------------------+ | ||
| | CPU | Intel Kaby Lake | | ||
| +------------------+--------------------------------------------------+ | ||
| | PCH | Intel C236 | | ||
| +------------------+--------------------------------------------------+ | ||
| | Coprocessor | Intel SPS (server version of the ME) | | ||
| +------------------+--------------------------------------------------+ | ||
| | Super I/O | ASPEED AST2400 | | ||
| +------------------+--------------------------------------------------+ | ||
| | Ethernet | 2x Intel I210-AT 1 GbE | | ||
| | | 1x dedicated BMC | | ||
| +------------------+--------------------------------------------------+ | ||
| | PCIe slots | 1x 3.0 x8 | | ||
| | | 1x 3.0 x8 (in x16) | | ||
| | | 1x 3.0 x4 (in x8) | | ||
| | | 1x 3.0 x2 (in M.2 slot with key M) | | ||
| +------------------+--------------------------------------------------+ | ||
| | USB slots | 2x USB 2.0 (ext) | | ||
| | | 2x USB 3.0 (ext) | | ||
| | | 1x USB 3.0 (int) | | ||
| | | 1x dual USB 3.0 header | | ||
| | | 2x dual USB 2.0 header | | ||
| +------------------+--------------------------------------------------+ | ||
| | SATA slots | 8x S-ATA III | | ||
| +------------------+--------------------------------------------------+ | ||
| | Other slots | 1x RS232 (ext) | | ||
| | | 1x RS232 header | | ||
| | | 1x TPM header | | ||
| | | 1x Power SMB header | | ||
| | | 5x PWM Fan connector | | ||
| | | 2x I-SGPIO | | ||
| | | 2x S-ATA DOM Power connector | | ||
| | | 1x XDP Port (connector may absent) | | ||
| | | 1x External BMC I2C Header (for IPMI card) | | ||
| | | 1x Chassis Intrusion Header | | ||
| +------------------+--------------------------------------------------+ | ||
| ``` | ||
|
|
||
| ## Extra links | ||
|
|
||
| - [Supermicro X11SSH-F] | ||
| - [Board manual] | ||
|
|
||
| [Supermicro X11SSH-F]: https://www.supermicro.com/en/products/motherboard/X11SSH-F | ||
| [Board manual]: https://www.supermicro.com/manuals/motherboard/C236/MNL-1778.pdf | ||
| [AST2400]: https://www.aspeedtech.com/products.php?fPath=20&rId=376 | ||
| [IPMI]: ../../../../drivers/ipmi_kcs.md | ||
| [MX25L25635F]: https://media.digikey.com/pdf/Data%20Sheets/Macronix/MX25L25635F.pdf | ||
| [STM32-based programmers]: https://github.com/dword1511/stm32-vserprog | ||
| [vga_switcheroo]: https://01.org/linuxgraphics/gfx-docs/drm/gpu/vga-switcheroo.html |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Known-working configuration to boot with TXT enabled. Since BIOS | ||
| # and SINIT ACM blobs are missing, use something else as placeholder. | ||
| # Used ACMs were extracted from a Supermicro X10SLH firmware update. | ||
| CONFIG_VENDOR_ASROCK=y | ||
| CONFIG_BOARD_ASROCK_B85M_PRO4=y | ||
| CONFIG_USER_TPM2=y | ||
| CONFIG_INTEL_TXT=y | ||
| CONFIG_INTEL_TXT_BIOSACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin" | ||
| CONFIG_INTEL_TXT_SINITACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin" | ||
| CONFIG_INTEL_TXT_LOGGING=y |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| if PAYLOAD_BOOTBOOT | ||
|
|
||
| config PAYLOAD_FILE | ||
| default "payloads/external/BOOTBOOT/bootboot/dist/bootbootcb.elf" | ||
|
|
||
| endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| config PAYLOAD_BOOTBOOT | ||
| bool "BOOTBOOT" | ||
| depends on ARCH_X86 || ARCH_ARM64 | ||
| help | ||
| Select this option if you want to build a coreboot image | ||
| with a BOOTBOOT Protocol payload. | ||
|
|
||
| See https://gitlab.com/bztsrc/bootboot for more information. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| project_git_repo=https://gitlab.com/bztsrc/bootboot.git | ||
| project_dir=bootboot | ||
| ifeq ($(CONFIG_COREBOOT_BUILD),) | ||
| include ../../../.config | ||
| endif | ||
| ifeq ($(CONFIG_ARCH_ARM64),y) | ||
| loader_dir=$(project_dir)/aarch64-cb | ||
| else | ||
| loader_dir=$(project_dir)/x86_64-cb | ||
| endif | ||
|
|
||
| unexport KCONFIG_AUTOHEADER | ||
| unexport KCONFIG_AUTOCONFIG | ||
| unexport KCONFIG_DEPENDENCIES | ||
| unexport KCONFIG_SPLITCONFIG | ||
| unexport KCONFIG_TRISTATE | ||
| unexport KCONFIG_NEGATIVES | ||
|
|
||
| all: bootboot | ||
|
|
||
| checkout: | ||
| echo " GIT BOOTBOOT $(loader_dir)" | ||
| test -L $(project_dir) || test -d $(project_dir) || \ | ||
| git clone $(project_git_repo) $(project_dir) | ||
|
|
||
| bootboot: libpayload | ||
| echo " MAKE $(loader_dir)" | ||
| $(MAKE) -C $(loader_dir) LIBCONFIG_PATH=../../../libpayload | ||
|
|
||
| libpayload: checkout | ||
| cp $(loader_dir)/lib.config ../../libpayload/.config | ||
| cd ../../libpayload && $(MAKE) oldconfig && \ | ||
| $(MAKE) && $(MAKE) DESTDIR=../external/BOOTBOOT/$(loader_dir) install | ||
|
|
||
| clean: | ||
| test -d $(loader_dir) && $(MAKE) -C $(loader_dir) clean || exit 0 | ||
|
|
||
| distclean: | ||
| rm -rf $(project_dir) | ||
|
|
||
| print-repo-info: | ||
| echo "$(project_git_repo) $(project_dir)" | ||
|
|
||
| .PHONY: checkout bootboot libpayload clean distclean print-repo-info |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* SPDX-License-Identifier: BSD-3-Clause */ | ||
|
|
||
| #ifndef __STDBOOL_H | ||
| #define __STDBOOL_H | ||
|
|
||
| #define bool _Bool | ||
| #define false 0 | ||
| #define true (!false) | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,12 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <types.h> | ||
| #include <arch/cpu.h> | ||
| #include <cpu/x86/msr.h> | ||
| #include "haswell.h" | ||
|
|
||
| void intel_cpu_haswell_finalize_smm(void) | ||
| { | ||
| /* Lock memory configuration to protect SMM */ | ||
| msr_set(MSR_LT_LOCK_MEMORY, BIT(0)); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,4 @@ | ||
| config CPU_INTEL_MODEL_65X | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,4 @@ | ||
| config CPU_INTEL_MODEL_67X | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,5 @@ | |
|
|
||
| config CPU_INTEL_MODEL_68X | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,4 @@ | ||
| config CPU_INTEL_MODEL_6BX | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,4 @@ | ||
| config CPU_INTEL_MODEL_6XX | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,6 @@ | ||
| config CPU_INTEL_MODEL_F2X | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS | ||
| select SMM_ASEG | ||
| select CPU_INTEL_COMMON | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,5 @@ | ||
| config CPU_INTEL_MODEL_F3X | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS | ||
| select CPU_INTEL_COMMON | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,4 @@ | ||
| config CPU_INTEL_MODEL_F4X | ||
| bool | ||
| select ARCH_ALL_STAGES_X86_32 | ||
| select SUPPORT_CPU_UCODE_IN_CBFS |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| config CHROMEOS_CAMERA | ||
| bool | ||
| default n | ||
| help | ||
| Camera with identifiers following Chrome OS Camera Info. The info is | ||
| usually available on MIPI camera EEPROM for identifying correct | ||
| drivers and config. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_CHROMEOS_CAMERA) += cros_camera.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <console/console.h> | ||
| #include <crc_byte.h> | ||
| #include <string.h> | ||
|
|
||
| #include "cros_camera.h" | ||
|
|
||
| int check_cros_camera_info(const struct cros_camera_info *info) | ||
| { | ||
| if (memcmp(info->magic, CROS_CAMERA_INFO_MAGIC, sizeof(info->magic))) { | ||
| printk(BIOS_ERR, "Invalid magic in camera info\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| const uint8_t *ptr = (void *)(&info->crc16 + 1); | ||
| uint16_t crc16 = 0; | ||
| while (ptr < (uint8_t *)info + sizeof(struct cros_camera_info)) | ||
| crc16 = crc16_byte(crc16, *ptr++); | ||
|
|
||
| if (info->crc16 != crc16) { | ||
| printk(BIOS_ERR, "Incorrect CRC16: expected %#06x, got %#06x\n", | ||
| crc16, info->crc16); | ||
| return -1; | ||
| } | ||
|
|
||
| if (info->version != CROS_CAMERA_INFO_VERSION) { | ||
| printk(BIOS_ERR, "Unknown camera info version: %u\n", | ||
| info->version); | ||
| return -1; | ||
| } | ||
| if (info->size < CROS_CAMERA_INFO_SIZE_MIN) { | ||
| printk(BIOS_ERR, "Size of camera info is too small: %u\n", | ||
| info->size); | ||
| return -1; | ||
| } | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __VENDORCODE_GOOGLE_CHROMEOS_CAMERA_H | ||
| #define __VENDORCODE_GOOGLE_CHROMEOS_CAMERA_H | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #define CROS_CAMERA_INFO_MAGIC "CrOS" | ||
| #define CROS_CAMERA_INFO_VERSION 1 | ||
| #define CROS_CAMERA_INFO_SIZE_MIN 0x0a | ||
|
|
||
| struct cros_camera_info { | ||
| uint8_t magic[4]; /* CROS_CAMERA_INFO_MAGIC */ | ||
| uint16_t crc16; | ||
| uint8_t version; | ||
| uint8_t size; | ||
| uint16_t data_format; | ||
| uint16_t module_pid; | ||
| uint8_t module_vid[2]; | ||
| uint8_t sensor_vid[2]; | ||
| uint16_t sensor_pid; | ||
| }; | ||
|
|
||
| /* Returns 0 on success, non-zero on errors. */ | ||
| int check_cros_camera_info(const struct cros_camera_info *info); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| config DRIVERS_I2C_GPIO_MUX | ||
| bool | ||
| default n | ||
| depends on HAVE_ACPI_TABLES | ||
| help | ||
| When enabled, add identifiers in ACPI tables for GPIO based I2C multiplexer. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| subdirs-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += mux | ||
| subdirs-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += bus |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += bus.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <acpi/acpi_device.h> | ||
| #include <acpi/acpigen.h> | ||
| #include <console/console.h> | ||
| #include <device/device.h> | ||
| #include <device/path.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include "chip.h" | ||
|
|
||
| static const char *i2c_gpiomux_bus_acpi_name(const struct device *dev) | ||
| { | ||
| static char name[ACPI_NAME_BUFFER_SIZE]; | ||
|
|
||
| snprintf(name, ACPI_NAME_BUFFER_SIZE, "MXA%01.1X", dev->path.generic.id); | ||
| return name; | ||
| } | ||
|
|
||
| static void i2c_gpiomux_bus_fill_ssdt(const struct device *dev) | ||
| { | ||
| const char *scope = acpi_device_scope(dev); | ||
| const char *path = acpi_device_path(dev); | ||
|
|
||
| if (!dev || !dev->enabled || !scope || !path) | ||
| return; | ||
|
|
||
| /* Device */ | ||
| acpigen_write_scope(scope); | ||
| acpigen_write_device(acpi_device_name(dev)); | ||
|
|
||
| acpigen_write_STA(acpi_device_status(dev)); | ||
| acpigen_write_ADR(dev->path.generic.id); | ||
|
|
||
| acpigen_pop_len(); /* Device */ | ||
| acpigen_pop_len(); /* Scope */ | ||
|
|
||
| printk(BIOS_INFO, "%s: %s at %s\n", path, dev->chip_ops->name, dev_path(dev)); | ||
| } | ||
|
|
||
| static struct device_operations i2c_gpiomux_bus_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .scan_bus = scan_static_bus, | ||
| .acpi_name = i2c_gpiomux_bus_acpi_name, | ||
| .acpi_fill_ssdt = i2c_gpiomux_bus_fill_ssdt, | ||
| }; | ||
|
|
||
| static void i2c_gpiomux_bus_enable(struct device *dev) | ||
| { | ||
| if (!dev) | ||
| return; | ||
|
|
||
| dev->ops = &i2c_gpiomux_bus_ops; | ||
| } | ||
|
|
||
| struct chip_operations drivers_i2c_gpiomux_bus_ops = { | ||
| CHIP_NAME("I2C GPIO MUX Bus Device") | ||
| .enable_dev = i2c_gpiomux_bus_enable | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __I2C_GPIOMUX_BUS_CHIP_H__ | ||
| #define __I2C_GPIOMUX_BUS_CHIP_H__ | ||
|
|
||
| struct drivers_i2c_gpiomux_bus_config { | ||
| }; | ||
|
|
||
| #endif /* __I2C_GPIOMUX_BUS_CHIP_H__ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += mux.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #ifndef __I2C_GPIOMUX_MUX_CHIP_H__ | ||
| #define __I2C_GPIOMUX_MUX_CHIP_H__ | ||
|
|
||
| #include <acpi/acpi_device.h> | ||
| #include <types.h> | ||
|
|
||
| #define MAX_NUM_MUX_GPIOS 4 | ||
|
|
||
| struct drivers_i2c_gpiomux_mux_config { | ||
| /* GPIOs used to select the mux lines */ | ||
| uint32_t mux_gpio_count; | ||
| struct acpi_gpio mux_gpio[MAX_NUM_MUX_GPIOS]; | ||
| }; | ||
|
|
||
| #endif /* __I2C_GPIOMUX_MUX_CHIP_H__ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
|
||
| #include <acpi/acpi_device.h> | ||
| #include <acpi/acpigen.h> | ||
| #include <console/console.h> | ||
| #include <device/device.h> | ||
| #include <device/path.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include "chip.h" | ||
|
|
||
| static const char *i2c_gpiomux_mux_acpi_name(const struct device *dev) | ||
| { | ||
| static char name[ACPI_NAME_BUFFER_SIZE]; | ||
|
|
||
| snprintf(name, ACPI_NAME_BUFFER_SIZE, "MUX%01.1X", dev->path.generic.id); | ||
| return name; | ||
| } | ||
|
|
||
| static void i2c_gpiomux_mux_fill_ssdt(const struct device *dev) | ||
| { | ||
| const char *scope = acpi_device_scope(dev); | ||
| const char *path = acpi_device_path(dev); | ||
| struct drivers_i2c_gpiomux_mux_config *config = config_of(dev); | ||
| struct acpi_dp *dsd = NULL; | ||
| const char *compat_string = "i2c-mux-gpio"; | ||
| struct acpi_gpio_res_params param[MAX_NUM_MUX_GPIOS]; | ||
| int i; | ||
|
|
||
| if (!dev->enabled || !scope || !path) | ||
| return; | ||
|
|
||
| /* Device */ | ||
| acpigen_write_scope(scope); | ||
| acpigen_write_device(acpi_device_name(dev)); | ||
| acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID); | ||
| acpigen_write_STA(acpi_device_status(dev)); | ||
|
|
||
| /* Resources */ | ||
| acpigen_write_name("_CRS"); | ||
| acpigen_write_resourcetemplate_header(); | ||
| for (i = 0; i < config->mux_gpio_count; i++) { | ||
| acpi_device_write_gpio(&config->mux_gpio[i]); | ||
| param[i].ref = path; | ||
| param[i].index = i; | ||
| param[i].pin = 0; | ||
| param[i].active_low = config->mux_gpio[i].active_low; | ||
| } | ||
| acpigen_write_resourcetemplate_footer(); | ||
|
|
||
| /* DSD */ | ||
| dsd = acpi_dp_new_table("_DSD"); | ||
| acpi_dp_add_string(dsd, "compatible", compat_string); | ||
| acpi_dp_add_gpio_array(dsd, "mux-gpios", param, config->mux_gpio_count); | ||
| acpi_dp_write(dsd); | ||
|
|
||
| acpigen_pop_len(); /* Device */ | ||
| acpigen_pop_len(); /* Scope */ | ||
|
|
||
| printk(BIOS_INFO, "%s: %s at %s\n", path, dev->chip_ops->name, dev_path(dev)); | ||
| } | ||
|
|
||
| static struct device_operations i2c_gpiomux_mux_ops = { | ||
| .read_resources = noop_read_resources, | ||
| .set_resources = noop_set_resources, | ||
| .scan_bus = scan_static_bus, | ||
| .acpi_name = i2c_gpiomux_mux_acpi_name, | ||
| .acpi_fill_ssdt = i2c_gpiomux_mux_fill_ssdt, | ||
| }; | ||
|
|
||
| static void i2c_gpiomux_mux_enable(struct device *dev) | ||
| { | ||
| if (!dev) | ||
| return; | ||
|
|
||
| dev->ops = &i2c_gpiomux_mux_ops; | ||
| } | ||
|
|
||
| struct chip_operations drivers_i2c_gpiomux_mux_ops = { | ||
| CHIP_NAME("I2C GPIO MUX Device") | ||
| .enable_dev = i2c_gpiomux_mux_enable | ||
| }; |