Exemplo n.º 1
0
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();
}
Exemplo n.º 2
0
/* 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 */
}
Exemplo n.º 3
0
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());
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
/* 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();
}
Exemplo n.º 6
0
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();
}
Exemplo n.º 7
0
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();
	}
}
Exemplo n.º 8
0
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();
}
Exemplo n.º 9
0
Arquivo: acpi.c Projeto: af00/coreboot
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();
	}
}
Exemplo n.º 10
0
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();
	}
}
Exemplo n.º 11
0
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();
	}
}
Exemplo n.º 12
0
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());
}
Exemplo n.º 13
0
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();
	}
}
Exemplo n.º 14
0
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 */
}
Exemplo n.º 15
0
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
};
Exemplo n.º 16
0
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
};
Exemplo n.º 17
0
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
};
Exemplo n.º 18
0
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();

}
Exemplo n.º 19
0
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
};
Exemplo n.º 20
0
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
};
Exemplo n.º 21
0
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
};