x86: apl: Add PMC driver
Add a driver for the Apollo Lake SoC. It supports the basic operations and can use device tree or of-platdata. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
#include <acpi_s3.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/intel_pinctrl.h>
|
||||
#endif
|
||||
#include <asm/io.h>
|
||||
#include <power/acpi_pmc.h>
|
||||
|
||||
@@ -34,6 +37,59 @@ enum {
|
||||
TCO1_CNT_HLT = 1 << 11,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
static int gpe0_shift(struct acpi_pmc_upriv *upriv, int regnum)
|
||||
{
|
||||
return upriv->gpe0_dwx_shift_base + regnum * 4;
|
||||
}
|
||||
|
||||
int pmc_gpe_init(struct udevice *dev)
|
||||
{
|
||||
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
|
||||
struct udevice *itss;
|
||||
u32 *dw;
|
||||
u32 gpio_cfg_mask;
|
||||
u32 gpio_cfg;
|
||||
int ret, i;
|
||||
u32 mask;
|
||||
|
||||
if (device_get_uclass_id(dev) != UCLASS_ACPI_PMC)
|
||||
return log_msg_ret("uclass", -EPROTONOSUPPORT);
|
||||
dw = upriv->gpe0_dw;
|
||||
mask = upriv->gpe0_dwx_mask;
|
||||
gpio_cfg_mask = 0;
|
||||
for (i = 0; i < upriv->gpe0_count; i++) {
|
||||
gpio_cfg_mask |= mask << gpe0_shift(upriv, i);
|
||||
if (dw[i] & ~mask)
|
||||
return log_msg_ret("Base GPE0 value", -EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Route the GPIOs to the GPE0 block. Determine that all values
|
||||
* are different and if they aren't, use the reset values.
|
||||
*/
|
||||
if (dw[0] == dw[1] || dw[1] == dw[2]) {
|
||||
log_info("PMC: Using default GPE route");
|
||||
gpio_cfg = readl(upriv->gpe_cfg);
|
||||
for (i = 0; i < upriv->gpe0_count; i++)
|
||||
dw[i] = gpio_cfg >> gpe0_shift(upriv, i);
|
||||
} else {
|
||||
gpio_cfg = 0;
|
||||
for (i = 0; i < upriv->gpe0_count; i++)
|
||||
gpio_cfg |= dw[i] << gpe0_shift(upriv, i);
|
||||
clrsetbits_le32(upriv->gpe_cfg, gpio_cfg_mask, gpio_cfg);
|
||||
}
|
||||
|
||||
/* Set the routes in the GPIO communities as well */
|
||||
ret = uclass_first_device_err(UCLASS_IRQ, &itss);
|
||||
if (ret)
|
||||
return log_msg_ret("Cannot find itss", ret);
|
||||
pinctrl_route_gpe(itss, dw[0], dw[1], dw[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_X86 */
|
||||
|
||||
static void pmc_fill_pm_reg_info(struct udevice *dev)
|
||||
{
|
||||
struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(dev);
|
||||
|
||||
Reference in New Issue
Block a user