From patchwork Mon Oct 21 03:39:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1180262 X-Patchwork-Delegate: bmeng.cn@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="XIU8/CP8"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46xNdh51Gcz9sPT for ; Mon, 21 Oct 2019 15:17:28 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 5552DC21DED; Mon, 21 Oct 2019 03:58:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 87074C21DAF; Mon, 21 Oct 2019 03:58:06 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 86EE1C21DF8; Mon, 21 Oct 2019 03:40:54 +0000 (UTC) Received: from mail-io1-f66.google.com (mail-io1-f66.google.com [209.85.166.66]) by lists.denx.de (Postfix) with ESMTPS id 63AD8C21DFB for ; Mon, 21 Oct 2019 03:40:54 +0000 (UTC) Received: by mail-io1-f66.google.com with SMTP id i26so4841723iog.9 for ; Sun, 20 Oct 2019 20:40:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=K8VZB82h1ZgGYz0UJUSYvO/kUsQw++VFaNweV/cYlXo=; b=XIU8/CP8dLUq4iMGIdHUayyfbX7kyJE4Z5im6t3S6GlTbS+UbgM8MeBvlf4JsGJzqc CCxcq+dKrF9AQSrDk9FPSzVAieYXNqeNrqoClgHLVeOoOBD7slfErQ8mXhwH6mPKiOyp NjrNY0EgfT5FfvS4Li852VnifO+aE+E1e6ZBs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=K8VZB82h1ZgGYz0UJUSYvO/kUsQw++VFaNweV/cYlXo=; b=nnNYrCzoC6vQ7yEw/g3kJGyotqGv+Q433OLjQkTiVhzlvPkyjHDFaYJaY7xD7XAf3h K4j9xP+zslKjrmNT6tFdnZYcRW8KNr0Kdr7CL2xzVqCq1InCiaMac/bKJVv9b+N7yw2w QWELq1k75gVQT3p28vPxhI8OS1KKl5O8QCTrlQGFtiacqxaqQ9PIeAkGdYlC/lLMwMgk N0Y/Jaj6mZkobfS3UVLRc97yU6L6p3eUAlGzWZkn6RCR8EB7C12yQdozae0AEB70Krml HJURKzFLZ0ffttzfbY8rlpx/JTQ2E9ctggvl07nZB4e64xpVOnJyUa0aILagTXiqgYbQ Qapg== X-Gm-Message-State: APjAAAVvxncP07uMlNvkG1dvDifA6YG1zp6oeQ/pon+BLhoSLTdfXiBz lClRhJarsPtqtH3V/qokFzQ/ZHHfLBS2Jg== X-Google-Smtp-Source: APXvYqx9SVjYtygvuiaeKiIY6X58yuL+96TJEKR5WKIhou9SuyEgXp7CUr78T1VeH5Yp2uVvS8IKWQ== X-Received: by 2002:a02:40c6:: with SMTP id n189mr20683882jaa.121.1571629252972; Sun, 20 Oct 2019 20:40:52 -0700 (PDT) Received: from kiwi.bld.corp.google.com ([2620:15c:183:0:8223:87c:a681:66aa]) by smtp.gmail.com with ESMTPSA id x14sm1947028ion.67.2019.10.20.20.40.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 20 Oct 2019 20:40:52 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Date: Sun, 20 Oct 2019 21:39:03 -0600 Message-Id: <20191021033913.220758-93-sjg@chromium.org> X-Mailer: git-send-email 2.23.0.866.gb869b98d4c-goog In-Reply-To: <20191021033913.220758-22-sjg@chromium.org> References: <20191021033913.220758-22-sjg@chromium.org> MIME-Version: 1.0 Subject: [U-Boot] [PATCH v3 098/108] x86: apollolake: Add LPC driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This driver the LPC and provides a few functions to set up LPC features. These should probably use ioctls() or perhaps, better, have specific uclass methods. Signed-off-by: Simon Glass --- Changes in v3: - Drop unused code in lpc_configure_pads() - Fix value of LPC_BC_LE Changes in v2: None arch/x86/cpu/apollolake/Makefile | 1 + arch/x86/cpu/apollolake/lpc.c | 141 +++++++++++++++++++++ arch/x86/include/asm/arch-apollolake/lpc.h | 61 +++++++++ 3 files changed, 203 insertions(+) create mode 100644 arch/x86/cpu/apollolake/lpc.c create mode 100644 arch/x86/include/asm/arch-apollolake/lpc.h diff --git a/arch/x86/cpu/apollolake/Makefile b/arch/x86/cpu/apollolake/Makefile index edd7e49154b..71c3cd08241 100644 --- a/arch/x86/cpu/apollolake/Makefile +++ b/arch/x86/cpu/apollolake/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SPL_BUILD) += systemagent.o obj-y += gpio.o obj-y += hostbridge.o obj-y += itss.o +obj-y += lpc.o obj-y += lpss.o obj-y += pmc.o obj-y += uart.o diff --git a/arch/x86/cpu/apollolake/lpc.c b/arch/x86/cpu/apollolake/lpc.c new file mode 100644 index 00000000000..1426b182542 --- /dev/null +++ b/arch/x86/cpu/apollolake/lpc.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Google LLC + * + * From coreboot apollolake support lpc.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void lpc_configure_pads(void) +{ + /* All pads are configured by the hostbridge */ +} + +void lpc_enable_fixed_io_ranges(uint io_enables) +{ + pci_x86_clrset_config(PCH_DEV_LPC, LPC_IO_ENABLES, 0, io_enables, + PCI_SIZE_16); +} + +/* + * Find the first unused IO window. + * Returns -1 if not found, 0 for reg 0x84, 1 for reg 0x88 ... + */ +static int find_unused_pmio_window(void) +{ + int i; + ulong lgir; + + for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) { + pci_x86_read_config(PCH_DEV_LPC, LPC_GENERIC_IO_RANGE(i), + &lgir, PCI_SIZE_32); + + if (!(lgir & LPC_LGIR_EN)) + return i; + } + + return -1; +} + +int lpc_open_pmio_window(uint base, uint size) +{ + int i, lgir_reg_num; + u32 lgir_reg_offset, lgir, window_size, alignment; + ulong bridged_size, bridge_base; + ulong reg; + + log_debug("LPC: Trying to open IO window from %x size %x\n", base, + size); + + bridged_size = 0; + bridge_base = base; + + while (bridged_size < size) { + /* Each IO range register can only open a 256-byte window */ + window_size = min(size, (uint)LPC_LGIR_MAX_WINDOW_SIZE); + + /* Window size must be a power of two for the AMASK to work */ + alignment = 1UL << (order_base_2(window_size)); + window_size = ALIGN(window_size, alignment); + + /* Address[15:2] in LGIR[15:12] and Mask[7:2] in LGIR[23:18] */ + lgir = (bridge_base & LPC_LGIR_ADDR_MASK) | LPC_LGIR_EN; + lgir |= ((window_size - 1) << 16) & LPC_LGIR_AMASK_MASK; + + /* Skip programming if same range already programmed */ + for (i = 0; i < LPC_NUM_GENERIC_IO_RANGES; i++) { + pci_x86_read_config(PCH_DEV_LPC, + LPC_GENERIC_IO_RANGE(i), ®, + PCI_SIZE_32); + if (lgir == reg) + return -EALREADY; + } + + lgir_reg_num = find_unused_pmio_window(); + if (lgir_reg_num < 0) { + log_err("LPC: Cannot open IO window: %lx size %lx\n", + bridge_base, size - bridged_size); + log_err("No more IO windows\n"); + + return -ENOSPC; + } + lgir_reg_offset = LPC_GENERIC_IO_RANGE(lgir_reg_num); + + pci_x86_write_config(PCH_DEV_LPC, lgir_reg_offset, lgir, + PCI_SIZE_32); + + log_debug("LPC: Opened IO window LGIR%d: base %lx size %x\n", + lgir_reg_num, bridge_base, window_size); + + bridged_size += window_size; + bridge_base += window_size; + } + + return 0; +} + +void lpc_io_setup_comm_a_b(void) +{ + /* ComA Range 3F8h-3FFh [2:0] */ + u16 com_ranges = LPC_IOD_COMA_RANGE; + u16 com_enable = LPC_IOE_COMA_EN; + + /* ComB Range 2F8h-2FFh [6:4] */ + if (0) { + com_ranges |= LPC_IOD_COMB_RANGE; + com_enable |= LPC_IOE_COMB_EN; + } + + /* Setup I/O Decode Range Register for LPC */ + pci_write_config16(PCH_DEV_LPC, LPC_IO_DECODE, com_ranges); + /* Enable ComA and ComB Port */ + lpc_enable_fixed_io_ranges(com_enable); +} + +static int apl_lpc_probe(struct udevice *dev) +{ + if (spl_phase() == PHASE_TPL) + lpc_configure_pads(); + + return 0; +} + +static const struct udevice_id apl_lpc_ids[] = { + { .compatible = "intel,apl-lpc" }, + { } +}; + +U_BOOT_DRIVER(apl_lpc_drv) = { + .name = "intel_apl_lpc", + .id = UCLASS_LPC, + .of_match = apl_lpc_ids, + .probe = apl_lpc_probe, +}; diff --git a/arch/x86/include/asm/arch-apollolake/lpc.h b/arch/x86/include/asm/arch-apollolake/lpc.h new file mode 100644 index 00000000000..641ccc01ca5 --- /dev/null +++ b/arch/x86/include/asm/arch-apollolake/lpc.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017 Intel Corporation. + * Take from coreboot project file of the same name + */ + +#ifndef __ARCH_LPC_H +#define __ARCH_LPC_H + +#define LPC_SERIRQ_CTL 0x64 +#define LPC_SCNT_EN (1 << 7) +#define LPC_SCNT_MODE (1 << 6) +#define LPC_IO_DECODE 0x80 +#define LPC_IOD_COMA_RANGE (0 << 0) /* 0x3F8 - 0x3FF COMA*/ +#define LPC_IOD_COMB_RANGE (1 << 4) /* 0x2F8 - 0x2FF COMB*/ +/* + * Use IO__ style macros defined in lpc_lib.h + * to enable decoding of I/O locations for a peripheral + */ +#define LPC_IO_ENABLES 0x82 +#define LPC_GENERIC_IO_RANGE(n) ((((n) & 0x3) * 4) + 0x84) +#define LPC_LGIR_AMASK_MASK (0xfc << 16) +#define LPC_LGIR_ADDR_MASK 0xfffc +#define LPC_LGIR_EN (1 << 0) +#define LPC_LGIR_MAX_WINDOW_SIZE 256 +#define LPC_GENERIC_MEM_RANGE 0x98 +#define LPC_LGMR_ADDR_MASK 0xffff0000 +#define LPC_LGMR_EN (1 << 0) +#define LPC_LGMR_WINDOW_SIZE (64 * KiB) +#define LPC_BIOS_CNTL 0xdc +#define LPC_BC_BILD (1 << 7) /* BILD */ +#define LPC_BC_LE (1 << 1) /* LE */ +#define LPC_BC_EISS (1 << 5) /* EISS */ +#define LPC_PCCTL 0xE0 /* PCI Clock Control */ +#define LPC_PCCTL_CLKRUN_EN (1 << 0) + +/* + * IO decode enable macros are in the format IO__. + * For example, to open ports 0x60, 0x64 for the keyboard controller, + * use IOE_KBC_60_64 macro. For IOE_ macros that do not specify a port range, + * the port range is selectable via the IO decodes register. + */ +#define LPC_IOE_EC_4E_4F BIT(13) +#define LPC_IOE_SUPERIO_2E_2F BIT(12) +#define LPC_IOE_EC_62_66 BIT(11) +#define LPC_IOE_KBC_60_64 BIT(10) +#define LPC_IOE_HGE_208 BIT(9) +#define LPC_IOE_LGE_200 BIT(8) +#define LPC_IOE_FDD_EN BIT(3) +#define LPC_IOE_LPT_EN BIT(2) +#define LPC_IOE_COMB_EN BIT(1) +#define LPC_IOE_COMA_EN BIT(0) +#define LPC_NUM_GENERIC_IO_RANGES 4 + +#define LPC_IO_ENABLES 0x82 + +void lpc_enable_fixed_io_ranges(uint io_enables); +int lpc_open_pmio_window(uint base, uint size); +void lpc_io_setup_comm_a_b(void); + +#endif