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(); }
static int generate_P_state_entries(int core, int cores_per_package) { int len, len_pss; int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2; int coord_type, power_max, power_unit, num_entries; int ratio, power, clock, clock_max; int vid, vid_turbo, vid_min, vid_max, vid_range_2; u32 control_status; const struct pattrs *pattrs = pattrs_get(); msr_t msr; /* Inputs from CPU attributes */ ratio_max = pattrs->iacore_ratios[IACORE_MAX]; ratio_min = pattrs->iacore_ratios[IACORE_LFM]; vid_max = pattrs->iacore_vids[IACORE_MAX]; vid_min = pattrs->iacore_vids[IACORE_LFM]; /* Hardware coordination of P-states */ coord_type = HW_ALL; /* Max Non-Turbo Frequency */ clock_max = (ratio_max * pattrs->bclk_khz) / 1000; /* Calculate CPU TDP in mW */ msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); power_unit = 1 << (msr.lo & 0xf); msr = rdmsr(MSR_PKG_POWER_LIMIT); power_max = ((msr.lo & 0x7fff) / power_unit) * 1000; /* Write _PCT indicating use of FFixedHW */ len = acpigen_write_empty_PCT(); /* Write _PPC with NVS specified limit on supported P-state */ len += acpigen_write_PPC_NVS(); /* Write PSD indicating configured coordination type */ len += acpigen_write_PSD_package(core, 1, coord_type); /* Add P-state entries in _PSS table */ len += acpigen_write_name("_PSS"); /* Determine ratio points */ ratio_step = 1; num_entries = (ratio_max - ratio_min) / ratio_step; while (num_entries > 15) { /* ACPI max is 15 ratios */ ratio_step <<= 1; num_entries >>= 1; } /* P[T] is Turbo state if enabled */ if (get_turbo_state() == TURBO_ENABLED) { /* _PSS package count including Turbo */ len_pss = acpigen_write_package(num_entries + 2); ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO]; vid_turbo = pattrs->iacore_vids[IACORE_TURBO]; control_status = (ratio_turbo << 8) | vid_turbo; /* Add entry for Turbo ratio */ len_pss += acpigen_write_PSS_package( clock_max + 1, /*MHz*/ power_max, /*mW*/ 10, /*lat1*/ 10, /*lat2*/ control_status, /*control*/ control_status); /*status*/ } else { /* _PSS package count without Turbo */ len_pss = acpigen_write_package(num_entries + 1); ratio_turbo = ratio_max; vid_turbo = vid_max; } /* First regular entry is max non-turbo ratio */ control_status = (ratio_max << 8) | vid_max; len_pss += acpigen_write_PSS_package( clock_max, /*MHz*/ power_max, /*mW*/ 10, /*lat1*/ 10, /*lat2*/ control_status, /*control */ control_status); /*status*/ /* Set up ratio and vid ranges for VID calculation */ ratio_range_2 = (ratio_turbo - ratio_min) * 2; vid_range_2 = (vid_turbo - vid_min) * 2; /* Generate the remaining entries */ for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min; ratio -= ratio_step) { /* Calculate VID for this ratio */ vid = ((ratio - ratio_min) * vid_range_2) / ratio_range_2 + vid_min; /* Round up if remainder */ if (((ratio - ratio_min) * vid_range_2) % ratio_range_2) vid++; /* Calculate power at this ratio */ power = calculate_power(power_max, ratio_max, ratio); clock = (ratio * pattrs->bclk_khz) / 1000; control_status = (ratio << 8) | (vid & 0xff); len_pss += acpigen_write_PSS_package( clock, /*MHz*/ power, /*mW*/ 10, /*lat1*/ 10, /*lat2*/ control_status, /*control*/ control_status); /*status*/ } /* Fix package length */ len_pss--; acpigen_patch_len(len_pss); return len + len_pss; }