void chromeos_acpi_gpio_generate(const struct cros_gpio *gpios, size_t num) { size_t i; int gpio_num; acpigen_write_scope("\\"); acpigen_write_name("OIPG"); acpigen_write_package(num); for (i = 0; i < num; i++) { acpigen_write_package(4); acpigen_write_integer(gpios[i].type); acpigen_write_integer(gpios[i].polarity); gpio_num = gpios[i].gpio_num; #if CONFIG(GENERIC_GPIO_LIB) /* Get ACPI pin from GPIO library if available */ if (gpios[i].gpio_num != CROS_GPIO_VIRTUAL) gpio_num = gpio_acpi_pin(gpio_num); #endif acpigen_write_integer(gpio_num); acpigen_write_string(gpios[i].device); acpigen_pop_len(); } acpigen_pop_len(); acpigen_pop_len(); }
/* e.g. * generate_sata_ssdt_ports("\_SB.PCI0.SATA", 0x3); * generates: * Scope (\_SB.PCI0.SATA) * { * Device (PR00) * { * Name (_ADR, 0x0000FFFF) // _ADR: Address * } * * Device (PR01) * { * Name (_ADR, 0x0001FFFF) // _ADR: Address * } * } * */ void generate_sata_ssdt_ports(const char *scope, uint32_t enable_map) { int i; uint32_t bit; char port_name[4] = "PR00"; acpigen_write_scope(scope); /* generate a device for every enabled port */ for (i = 0; i < 32; i++) { bit = 1 << i; if (!(bit & enable_map)) continue; port_name[2] = '0' + i / 10; port_name[3] = '0' + i % 10; acpigen_write_device(port_name); acpigen_write_name_dword("_ADR", 0xffff + i * 0x10000); acpigen_pop_len(); /* close PRT%d */ } acpigen_pop_len(); /* close scope */ }
unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { int lens; msr_t msr; char pscope[] = "\\_SB.PCI0"; lens = acpigen_write_scope(pscope); msr = rdmsr(TOP_MEM); lens += acpigen_write_name_dword("TOM1", msr.lo); msr = rdmsr(TOP_MEM2); /* * Since XP only implements parts of ACPI 2.0, we can't use a qword * here. * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt * slide 22ff. * Shift value right by 20 bit to make it fit into 32bit, * giving us 1MB granularity and a limit of almost 4Exabyte of memory. */ lens += acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20); acpigen_patch_len(lens - 1); /* TODO: More HT and other tables need to go into this table generation. * This should also be moved out to the silicon level if it can. */ return (unsigned long) (acpigen_get_current()); }
void northbridge_acpi_fill_ssdt_generator(device_t device) { u32 bmbound; char pscope[] = "\\_SB.PCI0"; bmbound = sideband_read(B_UNIT, BMBOUND); acpigen_write_scope(pscope); acpigen_write_name_dword("BMBD", bmbound); acpigen_pop_len(); generate_cpu_entries(device); }
/* Generate ACPI I2C device objects */ static void i2c_fill_ssdt(struct device *dev) { struct soc_intel_skylake_config *config = dev->chip_info; int bus = i2c_dev_to_bus(dev); if (!config || bus < 0) return; acpigen_write_scope(acpi_device_path(dev)); lpss_i2c_acpi_fill_ssdt(bus, &config->i2c[bus]); acpigen_pop_len(); }
void drivers_lenovo_serial_ports_ssdt_generate(const char *scope, int have_dock_serial) { acpigen_write_scope(scope); if (drivers_lenovo_is_wacom_present()) { acpigen_write_device("DTR"); acpigen_write_name("_HID"); acpigen_emit_eisaid("WACF004"); acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpigen_write_io16(0x200, 0x200, 1, 8, 1); acpigen_write_irq((1 << 5)); acpigen_write_resourcetemplate_footer(); acpigen_write_STA(0xf); acpigen_pop_len(); } if (have_dock_serial) { acpigen_write_device("COMA"); acpigen_write_name("_HID"); acpigen_emit_eisaid("PNP0501"); acpigen_write_name("_UID"); /* Byte */ acpigen_write_byte(0x2); acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpigen_write_io16(0x3f8, 0x3f8, 1, 8, 1); acpigen_write_irq(1 << 4); acpigen_write_resourcetemplate_footer(); acpigen_write_STA(0xf); acpigen_pop_len(); } acpigen_pop_len(); }
void southbridge_inject_dsdt(struct device *device) { struct global_nvs_t *gnvs; gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); if (gnvs) { acpi_create_gnvs(gnvs); /* Add it to DSDT */ acpigen_write_scope("\\"); acpigen_write_name_dword("NVSA", (uintptr_t)gnvs); acpigen_pop_len(); } }
void generate_cpu_entries(device_t device) { int cpu, pcontrol_blk=DEFAULT_PMBASE+PCNTRL, plen=6; int numcpus = determine_total_number_of_cores(); printk(BIOS_DEBUG, "Found %d CPU(s).\n", numcpus); /* without the outer scope, furhter ssdt addition will end up * within the processor statement */ acpigen_write_scope("\\_PR"); for (cpu=0; cpu < numcpus; cpu++) { acpigen_write_processor(cpu, pcontrol_blk, plen); acpigen_pop_len(); } acpigen_pop_len(); }
void southbridge_inject_dsdt(device_t device) { struct global_nvs_t *gnvs; gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); if (gnvs) { acpi_create_gnvs(gnvs); acpi_save_gnvs((uintptr_t)gnvs); /* And tell SMI about it */ smm_setup_structures(gnvs, NULL, NULL); /* Add it to DSDT. */ acpigen_write_scope("\\"); acpigen_write_name_dword("NVSA", (uintptr_t)gnvs); acpigen_pop_len(); } }
static void southbridge_inject_dsdt(void) { global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs)); if (gnvs) { memset(gnvs, 0, sizeof(*gnvs)); gnvs->apic = 1; gnvs->mpen = 1; /* Enable Multi Processing */ acpi_create_gnvs(gnvs); /* And tell SMI about it */ smm_setup_structures(gnvs, NULL, NULL); /* Add it to SSDT. */ acpigen_write_scope("\\"); acpigen_write_name_dword("NVSA", (u32) gnvs); acpigen_pop_len(); } }
static void southbridge_inject_dsdt(device_t dev) { global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs)); if (gnvs) { const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info(); memset(gnvs, 0, sizeof(*gnvs)); acpi_create_gnvs(gnvs); gnvs->ndid = gfx->ndid; memcpy(gnvs->did, gfx->did, sizeof(gnvs->did)); /* And tell SMI about it */ smm_setup_structures(gnvs, NULL, NULL); /* Add it to SSDT. */ acpigen_write_scope("\\"); acpigen_write_name_dword("NVSA", (u32) gnvs); acpigen_pop_len(); } }
unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) { int lens; msr_t msr; char pscope[] = "\\_SB.PCI0"; lens = acpigen_write_scope(pscope); msr = rdmsr(TOP_MEM); lens += acpigen_write_name_dword("TOM1", msr.lo); msr = rdmsr(TOP_MEM2); /* * FIXME: remove this work-around and url.. WinXP is EOL'ed any way. * Since XP only implements parts of ACPI 2.0, we can't use a qword * here. * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt * slide 22ff. * Shift value right by 20 bit to make it fit into 32bit, * giving us 1MB granularity and a limit of almost 4Exabyte of memory. */ lens += acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20); acpigen_patch_len(lens - 1); return (unsigned long) (acpigen_get_current()); }
void southcluster_inject_dsdt(device_t device) { global_nvs_t *gnvs; gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); if (!gnvs) { gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof (*gnvs)); if (gnvs) memset(gnvs, 0, sizeof(*gnvs)); } if (gnvs) { acpi_create_gnvs(gnvs); acpi_save_gnvs((unsigned long)gnvs); /* And tell SMI about it */ smm_setup_structures(gnvs, NULL, NULL); /* Add it to DSDT. */ acpigen_write_scope("\\"); acpigen_write_name_dword("NVSA", (u32) gnvs); acpigen_pop_len(); } }
static void gpio_regulator_fill_ssdt_generator(struct device *dev) { struct drivers_generic_gpio_regulator_config *config = dev->chip_info; const char *scope = acpi_device_scope(dev); const char *path = acpi_device_path(dev); struct acpi_dp *dsd; if (!dev->enabled || !scope || !path || !config->gpio.pin_count) return; /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); /* _HID is set to PRP0001 */ acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID); /* Resources - _CRS */ acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpi_device_write_gpio(&config->gpio); acpigen_write_resourcetemplate_footer(); /* DSD */ dsd = acpi_dp_new_table("_DSD"); acpi_dp_add_string(dsd, "compatible", "regulator-fixed"); acpi_dp_add_string(dsd, "regulator-name", config->name); acpi_dp_add_gpio(dsd, "gpio-gpios", path, 0, 0, config->gpio.polarity); if (config->enabled_on_boot) acpi_dp_add_string(dsd, "regulator-boot-on", "on"); if (config->gpio.polarity == ACPI_GPIO_ACTIVE_HIGH) acpi_dp_add_string(dsd, "enable-active-high", "on"); acpi_dp_write(dsd); acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ }
static void i2c_tpm_fill_ssdt(struct device *dev) { struct drivers_i2c_tpm_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 = config->speed ? : I2C_SPEED_FAST, .resource = scope, }; if (!dev->enabled || !scope) return; if (!config->hid) { printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev)); return; } /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); acpigen_write_name_string("_HID", config->hid); acpigen_write_name_integer("_UID", config->uid); acpigen_write_name_string("_DDN", dev->chip_ops->name); acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON); /* Resources */ acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpi_device_write_i2c(&i2c); acpi_device_write_interrupt(&config->irq); acpigen_write_resourcetemplate_footer(); acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), dev->chip_ops->name, dev_path(dev)); } static const char *i2c_tpm_acpi_name(struct device *dev) { return "TPMI"; } static struct device_operations i2c_tpm_ops = { .read_resources = DEVICE_NOOP, .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, .acpi_name = &i2c_tpm_acpi_name, .acpi_fill_ssdt_generator = &i2c_tpm_fill_ssdt, }; static void i2c_tpm_enable(struct device *dev) { dev->ops = &i2c_tpm_ops; } struct chip_operations drivers_i2c_tpm_ops = { CHIP_NAME("I2C TPM") .enable_dev = &i2c_tpm_enable };
static void max98373_fill_ssdt(struct device *dev) { struct drivers_i2c_max98373_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 = config->bus_speed ? : I2C_SPEED_STANDARD, .resource = scope, }; struct acpi_dp *dp; if (!dev->enabled || !scope) { printk(BIOS_ERR, "%s: dev not enabled", __func__); return; } /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); acpigen_write_name_string("_HID", MAX98373_ACPI_HID); acpigen_write_name_integer("_UID", config->uid); if (config->desc) 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); acpigen_write_resourcetemplate_footer(); /* Device Properties */ dp = acpi_dp_new_table("_DSD"); if (config->interleave_mode) acpi_dp_add_integer(dp, "maxim,interleave_mode", config->interleave_mode); acpi_dp_add_integer(dp, "maxim,vmon-slot-no", config->vmon_slot_no); acpi_dp_add_integer(dp, "maxim,imon-slot-no", config->imon_slot_no); acpi_dp_write(dp); acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ printk(BIOS_INFO, "%s: %s address 0%xh\n", acpi_device_path(dev), dev->chip_ops->name, dev->path.i2c.device); } static const char *max98373_acpi_name(const struct device *dev) { struct drivers_i2c_max98373_config *config = dev->chip_info; if (config->name) return config->name; return MAX98373_ACPI_NAME; } static struct device_operations max98373_ops = { .read_resources = DEVICE_NOOP, .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, .acpi_name = &max98373_acpi_name, .acpi_fill_ssdt_generator = &max98373_fill_ssdt, }; static void max98373_enable(struct device *dev) { struct drivers_i2c_max98373_config *config = dev->chip_info; dev->ops = &max98373_ops; if (config && config->desc) { dev->name = config->desc; } } struct chip_operations drivers_i2c_max98373_ops = { CHIP_NAME("Maxim MAX98373 Codec") .enable_dev = &max98373_enable };
static void nau8825_fill_ssdt(struct device *dev) { struct drivers_i2c_nau8825_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 = config->bus_speed ? : I2C_SPEED_FAST, .resource = scope, }; struct acpi_dp *dp = NULL; if (!dev->enabled || !scope) return; if (config->sar_threshold_num > NAU8825_MAX_BUTTONS) return; /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); acpigen_write_name_string("_HID", NAU8825_ACPI_HID); acpigen_write_name_integer("_UID", 0); acpigen_write_name_string("_DDN", dev->chip_ops->name); acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON); /* Resources */ acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpi_device_write_i2c(&i2c); acpi_device_write_interrupt(&config->irq); acpigen_write_resourcetemplate_footer(); /* Device Properties */ dp = acpi_dp_new_table("_DSD"); NAU8825_DP_INT("jkdet-enable", config->jkdet_enable); NAU8825_DP_INT("jkdet-pull-enable", config->jkdet_pull_enable); NAU8825_DP_INT("jkdet-pull-up", config->jkdet_pull_up); NAU8825_DP_INT("jkdet-polarity", config->jkdet_polarity); NAU8825_DP_INT("vref-impedance", config->vref_impedance); NAU8825_DP_INT("micbias-voltage", config->micbias_voltage); NAU8825_DP_INT("sar-hysteresis", config->sar_hysteresis); NAU8825_DP_INT("sar-voltage", config->sar_voltage); NAU8825_DP_INT("sar-compare-time", config->sar_compare_time); NAU8825_DP_INT("sar-sampling-time", config->sar_sampling_time); NAU8825_DP_INT("short-key-debounce", config->short_key_debounce); NAU8825_DP_INT("jack-insert-debounce", config->jack_insert_debounce); NAU8825_DP_INT("jack-eject-deboune", config->jack_eject_debounce); NAU8825_DP_INT("sar-threshold-num", config->sar_threshold_num); acpi_dp_add_integer_array(dp, "nuvoton,sar-threshold", config->sar_threshold, config->sar_threshold_num); acpi_dp_write(dp); acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ printk(BIOS_INFO, "%s: %s address 0%xh irq %d\n", acpi_device_path(dev), dev->chip_ops->name, dev->path.i2c.device, config->irq.pin); } static const char *nau8825_acpi_name(struct device *dev) { return NAU8825_ACPI_NAME; } #endif static struct device_operations nau8825_ops = { .read_resources = DEVICE_NOOP, .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) .acpi_name = &nau8825_acpi_name, .acpi_fill_ssdt_generator = &nau8825_fill_ssdt, #endif }; static void nau8825_enable(struct device *dev) { dev->ops = &nau8825_ops; } struct chip_operations drivers_i2c_nau8825_ops = { CHIP_NAME("Nuvoton NAU8825 Codec") .enable_dev = &nau8825_enable };
void intel_acpi_pcie_hotplug_generator(u8 *hotplug_map, int port_number) { int port; int have_hotplug = 0; for (port = 0; port < port_number; port++) { if (hotplug_map[port]) { have_hotplug = 1; } } if (!have_hotplug) { return; } for (port = 0; port < port_number; port++) { if (hotplug_map[port]) { char scope_name[] = "\\_SB.PCI0.RP0x"; scope_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port; acpigen_write_scope(scope_name); /* Device (SLOT) { Name (_ADR, 0x00) Method (_RMV, 0, NotSerialized) { Return (0x01) } } */ acpigen_write_device("SLOT"); acpigen_write_name_byte("_ADR", 0x00); acpigen_write_method("_RMV", 0); /* ReturnOp */ acpigen_emit_byte (0xa4); /* One */ acpigen_emit_byte (0x01); acpigen_pop_len(); acpigen_pop_len(); acpigen_pop_len(); } } /* Method (_L01, 0, NotSerialized) { If (\_SB.PCI0.RP04.HPCS) { Sleep (100) Store (0x01, \_SB.PCI0.RP04.HPCS) If (\_SB.PCI0.RP04.PDC) { Store (0x01, \_SB.PCI0.RP04.PDC) Notify (\_SB.PCI0.RP04, 0x00) } } } */ acpigen_write_scope("\\_GPE"); acpigen_write_method("_L01", 0); for (port = 0; port < port_number; port++) { if (hotplug_map[port]) { char reg_name[] = "\\_SB.PCI0.RP0x.HPCS"; reg_name[sizeof("\\_SB.PCI0.RP0x") - 2] = '1' + port; acpigen_emit_byte(0xa0); /* IfOp. */ acpigen_write_len_f(); acpigen_emit_namestring(reg_name); /* Sleep (100) */ acpigen_emit_byte(0x5b); /* SleepOp. */ acpigen_emit_byte(0x22); acpigen_write_byte(100); /* Store (0x01, \_SB.PCI0.RP04.HPCS) */ acpigen_emit_byte(0x70); acpigen_emit_byte(0x01); acpigen_emit_namestring(reg_name); memcpy(reg_name + sizeof("\\_SB.PCI0.RP0x.") - 1, "PDC", 4); /* If (\_SB.PCI0.RP04.PDC) */ acpigen_emit_byte(0xa0); /* IfOp. */ acpigen_write_len_f(); acpigen_emit_namestring(reg_name); /* Store (0x01, \_SB.PCI0.RP04.PDC) */ acpigen_emit_byte(0x70); acpigen_emit_byte(0x01); acpigen_emit_namestring(reg_name); reg_name[sizeof("\\_SB.PCI0.RP0x") - 1] = '\0'; /* Notify(\_SB.PCI0.RP04, 0x00) */ acpigen_emit_byte(0x86); acpigen_emit_namestring(reg_name); acpigen_emit_byte(0x00); acpigen_pop_len(); acpigen_pop_len(); } } acpigen_pop_len(); acpigen_pop_len(); }
static void spi_acpi_fill_ssdt_generator(struct device *dev) { struct drivers_spi_acpi_config *config = dev->chip_info; const char *scope = acpi_device_scope(dev); const char *path = acpi_device_path(dev); struct acpi_spi spi = { .device_select = dev->path.spi.cs, .speed = config->speed ? : 1 * MHz, .resource = scope, .device_select_polarity = SPI_POLARITY_LOW, .wire_mode = SPI_4_WIRE_MODE, .data_bit_length = 8, .clock_phase = SPI_CLOCK_PHASE_FIRST, .clock_polarity = SPI_POLARITY_LOW, }; int curr_index = 0; int irq_gpio_index = -1; int reset_gpio_index = -1; int enable_gpio_index = -1; if (!dev->enabled || !scope) return; if (spi_acpi_get_bus(dev) == -1) { printk(BIOS_ERR, "%s: ERROR: Cannot get bus for device.\n", dev_path(dev)); return; } if (!config->hid) { printk(BIOS_ERR, "%s: ERROR: HID required.\n", dev_path(dev)); return; } /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); acpigen_write_name_string("_HID", config->hid); if (config->cid) acpigen_write_name_string("_CID", config->cid); acpigen_write_name_integer("_UID", config->uid); if (config->desc) acpigen_write_name_string("_DDN", config->desc); /* Resources */ acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpi_device_write_spi(&spi); /* Use either Interrupt() or GpioInt() */ if (config->irq_gpio.pin_count) irq_gpio_index = spi_acpi_write_gpio(&config->irq_gpio, &curr_index); else acpi_device_write_interrupt(&config->irq); /* Add enable/reset GPIOs if needed */ if (spi_acpi_add_gpios_to_crs(config)) { reset_gpio_index = spi_acpi_write_gpio(&config->reset_gpio, &curr_index); enable_gpio_index = spi_acpi_write_gpio(&config->enable_gpio, &curr_index); } acpigen_write_resourcetemplate_footer(); /* Wake capabilities */ if (config->wake) { acpigen_write_name_integer("_S0W", 4); acpigen_write_PRW(config->wake, 3); }; /* Write device properties if needed */ if (config->compat_string || irq_gpio_index >= 0 || reset_gpio_index >= 0 || enable_gpio_index >= 0) { struct acpi_dp *dsd = acpi_dp_new_table("_DSD"); if (config->compat_string) acpi_dp_add_string(dsd, "compatible", config->compat_string); if (irq_gpio_index >= 0) acpi_dp_add_gpio(dsd, "irq-gpios", path, irq_gpio_index, 0, config->irq_gpio.polarity); if (reset_gpio_index >= 0) acpi_dp_add_gpio(dsd, "reset-gpios", path, reset_gpio_index, 0, config->reset_gpio.polarity); if (enable_gpio_index >= 0) acpi_dp_add_gpio(dsd, "enable-gpios", path, enable_gpio_index, 0, config->enable_gpio.polarity); acpi_dp_write(dsd); } /* Power Resource */ if (config->has_power_resource) acpi_device_add_power_res( &config->reset_gpio, config->reset_delay_ms, &config->enable_gpio, config->enable_delay_ms); acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ printk(BIOS_INFO, "%s: %s at %s\n", path, config->desc ? : dev->chip_ops->name, dev_path(dev)); } static const char *spi_acpi_name(struct device *dev) { struct drivers_spi_acpi_config *config = dev->chip_info; static char name[5]; if (config->name) return config->name; snprintf(name, sizeof(name), "S%03.3X", spi_acpi_get_bus(dev)); name[4] = '\0'; return name; } static struct device_operations spi_acpi_ops = { .read_resources = DEVICE_NOOP, .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, .acpi_name = &spi_acpi_name, .acpi_fill_ssdt_generator = &spi_acpi_fill_ssdt_generator, }; static void spi_acpi_enable(struct device *dev) { dev->ops = &spi_acpi_ops; } struct chip_operations drivers_spi_acpi_ops = { CHIP_NAME("SPI Device") .enable_dev = &spi_acpi_enable };
static void camera_fill_ssdt(struct device *dev) { struct drivers_intel_mipi_camera_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, }; if (!dev->enabled || !scope) return; /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); acpigen_write_name_string("_HID", config->acpi_hid); acpigen_write_name_integer("_UID", config->acpi_uid); acpigen_write_name_string("_DDN", config->chip_name); acpigen_write_STA(acpi_device_status(dev)); /* Resources */ acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpi_device_write_i2c(&i2c); acpigen_write_resourcetemplate_footer(); /* Mark it as Camera related device */ acpigen_write_name_integer("CAMD", config->device_type); /* Create Device specific data */ if (config->device_type == INTEL_ACPI_CAMERA_SENSOR) { acpigen_write_method_serialized("SSDB", 0); acpigen_write_return_byte_buffer((uint8_t *)&config->ssdb, sizeof(config->ssdb)); acpigen_pop_len(); /* Method */ } /* Fill Power Sequencing Data */ acpigen_write_method_serialized("PWDB", 0); acpigen_write_return_byte_buffer((uint8_t *)&config->pwdb, (sizeof(struct intel_pwdb) * config->num_pwdb_entries)); acpigen_pop_len(); /* Method */ acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ printk(BIOS_INFO, "%s: %s address 0%xh\n", acpi_device_path(dev), dev->chip_ops->name, dev->path.i2c.device); } static const char *camera_acpi_name(const struct device *dev) { struct drivers_intel_mipi_camera_config *config = dev->chip_info; return config->acpi_name; } static struct device_operations camera_ops = { .read_resources = DEVICE_NOOP, .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, .acpi_name = &camera_acpi_name, .acpi_fill_ssdt_generator = &camera_fill_ssdt, }; static void camera_enable(struct device *dev) { dev->ops = &camera_ops; } struct chip_operations drivers_intel_mipi_camera_ops = { CHIP_NAME("Intel MIPI Camera Device") .enable_dev = &camera_enable };
static void i2c_generic_fill_ssdt(struct device *dev) { struct drivers_i2c_generic_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 = config->speed ? : I2C_SPEED_FAST, .resource = scope, }; if (!dev->enabled || !scope) return; if (!config->hid) { printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev)); return; } /* Device */ acpigen_write_scope(scope); acpigen_write_device(acpi_device_name(dev)); acpigen_write_name_string("_HID", config->hid); acpigen_write_name_integer("_UID", config->uid); acpigen_write_name_string("_DDN", config->desc); acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON); /* Resources */ acpigen_write_name("_CRS"); acpigen_write_resourcetemplate_header(); acpi_device_write_i2c(&i2c); acpi_device_write_interrupt(&config->irq); acpigen_write_resourcetemplate_footer(); /* Wake capabilities */ if (config->wake) { acpigen_write_name_integer("_S0W", 4); acpigen_write_PRW(config->wake, 3); } 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)); } /* Use name specified in config or build one from I2C address */ static const char *i2c_generic_acpi_name(struct device *dev) { struct drivers_i2c_generic_config *config = dev->chip_info; static char name[5]; if (config->name) return name; snprintf(name, sizeof(name), "D%03.3X", dev->path.i2c.device); name[4] = '\0'; return name; } #endif static struct device_operations i2c_generic_ops = { .read_resources = DEVICE_NOOP, .set_resources = DEVICE_NOOP, .enable_resources = DEVICE_NOOP, #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) .acpi_name = &i2c_generic_acpi_name, .acpi_fill_ssdt_generator = &i2c_generic_fill_ssdt, #endif }; static void i2c_generic_enable(struct device *dev) { struct drivers_i2c_generic_config *config = dev->chip_info; /* Check if device is present by reading GPIO */ if (config->device_present_gpio) { int present = gpio_get(config->device_present_gpio); present ^= config->device_present_gpio_invert; printk(BIOS_INFO, "%s is %spresent\n", dev->chip_ops->name, present ? "" : "not "); if (!present) { dev->enabled = 0; return; } } dev->ops = &i2c_generic_ops; } struct chip_operations drivers_i2c_generic_ops = { CHIP_NAME("I2C Device") .enable_dev = &i2c_generic_enable };