From patchwork Thu Apr 20 19:12:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= X-Patchwork-Id: 752970 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3w87nY3X20z9s76 for ; Fri, 21 Apr 2017 05:13:37 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="gDwRJiUd"; dkim-atps=neutral Received: by lists.denx.de (Postfix, from userid 105) id 34692C21C7C; Thu, 20 Apr 2017 19:11:44 +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=FREEMAIL_FROM, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, 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 CD196C21C4F; Thu, 20 Apr 2017 19:10:40 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 35B9CC21C73; Thu, 20 Apr 2017 19:10:30 +0000 (UTC) Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by lists.denx.de (Postfix) with ESMTPS id 69DC1C21C52 for ; Thu, 20 Apr 2017 19:10:26 +0000 (UTC) Received: by mail-wm0-f65.google.com with SMTP id z129so215676wmb.1 for ; Thu, 20 Apr 2017 12:10:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vK9DecxdiDFBednTdrtO1Bc+pE1kdjAN67AeRZQvZlM=; b=gDwRJiUdZmnoKj2IUzmO8aE+NJ8GsojMDKyKNCVvXxhstwMg4fmwnL9MtRUTwEzg+E 2NUxDE+yAdia9ncn/99TNBubkswdrBbc6V2jBUGoXmjr0fyz38bJg+BHZL8auVGNYX+y AVUjUs8w2JTst6LKhlNWMXgTIwFz32S/WWcXOl+p9bg15cx9vM6INyRAn2Pp5uMJ3uMp ELpLsnC1TGQqm6c0bbwi/cJrCSC8iRojkq+FZPS8rdKqd5EQOYzMolWA361AwlPMPxYX AigCMr4stHR8LeSIH2K5Cv/kSo/mIB35cR2yq68SmvyijA6PEIQO4fYGpsSfgxzTAacP HPwA== 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=vK9DecxdiDFBednTdrtO1Bc+pE1kdjAN67AeRZQvZlM=; b=eQyO3H/HFzfOtsKtuOB2Qp88q2xL4BjwFkFXqjIWdy9cT0CrA29a7rhPrS7Xg3LB1X deHsqvBl79E7SYAhO13pshG6W6ojJPbb0uw/O2LMgf5zO4H0iDAAQ/c74RZ0E9k03I0J Wg/qfDcKdZHg2fyiI6FyrwMJynnuIW3Zd5Oxo9k4lOWvXcD59uXKdvfR+Dc2rFsIUubR aX7cFo1+K9USc1Qi22I/deWPGxkVnd+jS5fi5IKiL0lUiTaKnhfiyRnl0LR4MFus/Z3k beMrS9xfp2HtpB7Lc2BwEokgTSXnvzqieFK4khBmC4vEVNXXknBDbDU2ELxqJQlra2zg tsyA== X-Gm-Message-State: AN3rC/4lYTyQt+7A/2oZGufDFDTCnZNTgIhQxh1bYTlAGbaC4ULvyssj molOLeiWAXvxgg== X-Received: by 10.28.156.140 with SMTP id f134mr4438098wme.40.1492715426004; Thu, 20 Apr 2017 12:10:26 -0700 (PDT) Received: from skynet.lan (44.red-83-41-49.dynamicip.rima-tde.net. [83.41.49.44]) by smtp.gmail.com with ESMTPSA id b10sm50332wme.22.2017.04.20.12.10.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 20 Apr 2017 12:10:25 -0700 (PDT) From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= To: u-boot@lists.denx.de, daniel.schwierzeck@gmail.com, sjg@chromium.org Date: Thu, 20 Apr 2017 21:12:17 +0200 Message-Id: <1492715545-3010-7-git-send-email-noltari@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1492715545-3010-1-git-send-email-noltari@gmail.com> References: <1492715545-3010-1-git-send-email-noltari@gmail.com> MIME-Version: 1.0 Subject: [U-Boot] [PATCH v4 06/14] cpu: add CPU driver for Broadcom MIPS SoCs 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" Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Simon Glass --- v4: No changes. v3: Several improvements: - Probe driver correctly. - Allocate size for priv struct. - Cosmetic fixes. v2: Introduce changes suggested by Daniel Schwierzeck: - Split BMIPS support patches. - Get register base from DT. drivers/cpu/Makefile | 2 + drivers/cpu/bmips_cpu.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 drivers/cpu/bmips_cpu.c diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile index 8710160..db515f6 100644 --- a/drivers/cpu/Makefile +++ b/drivers/cpu/Makefile @@ -5,3 +5,5 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-$(CONFIG_CPU) += cpu-uclass.o + +obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o diff --git a/drivers/cpu/bmips_cpu.c b/drivers/cpu/bmips_cpu.c new file mode 100644 index 0000000..d95f51a --- /dev/null +++ b/drivers/cpu/bmips_cpu.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas + * + * Derived from linux/arch/mips/bcm63xx/cpu.c: + * Copyright (C) 2008 Maxime Bizon + * Copyright (C) 2009 Florian Fainelli + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define REV_CHIPID_SHIFT 16 +#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT) +#define REV_REVID_SHIFT 0 +#define REV_REVID_MASK (0xff << REV_REVID_SHIFT) + +#define REG_BCM6328_OTP 0x62c +#define BCM6328_TP1_DISABLED BIT(9) + +#define REG_BCM6328_MISC_STRAPBUS 0x1a40 +#define STRAPBUS_6328_FCVO_SHIFT 7 +#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT) + +#define REG_BCM6358_DDR_DMIPSPLLCFG 0x12b8 +#define DMIPSPLLCFG_6358_M1_SHIFT 0 +#define DMIPSPLLCFG_6358_M1_MASK (0xff << DMIPSPLLCFG_6358_M1_SHIFT) +#define DMIPSPLLCFG_6358_N1_SHIFT 23 +#define DMIPSPLLCFG_6358_N1_MASK (0x3f << DMIPSPLLCFG_6358_N1_SHIFT) +#define DMIPSPLLCFG_6358_N2_SHIFT 29 +#define DMIPSPLLCFG_6358_N2_MASK (0x7 << DMIPSPLLCFG_6358_N2_SHIFT) + +#define REG_BCM63268_MISC_STRAPBUS 0x1814 +#define STRAPBUS_63268_FCVO_SHIFT 21 +#define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT) + +struct bmips_cpu_priv; + +struct bmips_cpu_hw { + ulong (*get_cpu_freq)(struct bmips_cpu_priv *); + int (*get_cpu_count)(struct bmips_cpu_priv *); +}; + +struct bmips_cpu_priv { + void __iomem *regs; + const struct bmips_cpu_hw *hw; +}; + +/* Specific CPU Ops */ +static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv) +{ + unsigned int mips_pll_fcvo; + + mips_pll_fcvo = __raw_readl(priv->regs + REG_BCM6328_MISC_STRAPBUS); + mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6328_FCVO_MASK) + >> STRAPBUS_6328_FCVO_SHIFT; + + switch (mips_pll_fcvo) { + case 0x12: + case 0x14: + case 0x19: + return 160000000; + case 0x1c: + return 192000000; + case 0x13: + case 0x15: + return 200000000; + case 0x1a: + return 384000000; + case 0x16: + return 400000000; + default: + return 320000000; + } +} + +static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv) +{ + unsigned int tmp, n1, n2, m1; + + tmp = __raw_readl(priv->regs + REG_BCM6358_DDR_DMIPSPLLCFG); + n1 = (tmp & DMIPSPLLCFG_6358_N1_MASK) >> DMIPSPLLCFG_6358_N1_SHIFT; + n2 = (tmp & DMIPSPLLCFG_6358_N2_MASK) >> DMIPSPLLCFG_6358_N2_SHIFT; + m1 = (tmp & DMIPSPLLCFG_6358_M1_MASK) >> DMIPSPLLCFG_6358_M1_SHIFT; + + return (16 * 1000000 * n1 * n2) / m1; +} + +static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv) +{ + unsigned mips_pll_fcvo; + + mips_pll_fcvo = __raw_readl(priv->regs + REG_BCM63268_MISC_STRAPBUS); + mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_63268_FCVO_MASK) + >> STRAPBUS_63268_FCVO_SHIFT; + + switch (mips_pll_fcvo) { + case 0x3: + case 0xe: + return 320000000; + case 0xa: + return 333000000; + case 0x2: + case 0xb: + case 0xf: + return 400000000; + default: + return 0; + } +} + +static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv) +{ + u32 val = __raw_readl(priv->regs + REG_BCM6328_OTP); + + if (val & BCM6328_TP1_DISABLED) + return 1; + else + return 2; +} + +static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv) +{ + return 2; +} + +static const struct bmips_cpu_hw bmips_cpu_bcm6328 = { + .get_cpu_freq = bcm6328_get_cpu_freq, + .get_cpu_count = bcm6328_get_cpu_count, +}; + +static const struct bmips_cpu_hw bmips_cpu_bcm6358 = { + .get_cpu_freq = bcm6358_get_cpu_freq, + .get_cpu_count = bcm6358_get_cpu_count, +}; + +static const struct bmips_cpu_hw bmips_cpu_bcm63268 = { + .get_cpu_freq = bcm63268_get_cpu_freq, + .get_cpu_count = bcm6358_get_cpu_count, +}; + +/* Generic CPU Ops */ +static int bmips_cpu_get_desc(struct udevice *dev, char *buf, int size) +{ + struct bmips_cpu_priv *priv = dev_get_priv(dev); + u32 cpu_revid; + u16 cpu_id; + u8 cpu_rev; + + cpu_revid = __raw_readl(priv->regs); + cpu_id = (cpu_revid & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT; + cpu_rev = (cpu_revid & REV_REVID_MASK) >> REV_REVID_SHIFT; + + snprintf(buf, size, "BCM%04X%02X", cpu_id, cpu_rev); + + return 0; +} + +static int bmips_cpu_get_info(struct udevice *dev, struct cpu_info *info) +{ + struct bmips_cpu_priv *priv = dev_get_priv(dev); + const struct bmips_cpu_hw *hw = priv->hw; + + info->cpu_freq = hw->get_cpu_freq(priv); + info->features = BIT(CPU_FEAT_L1_CACHE); + info->features |= BIT(CPU_FEAT_MMU); + info->features |= BIT(CPU_FEAT_DEVICE_ID); + + return 0; +} + +static int bmips_cpu_get_count(struct udevice *dev) +{ + struct bmips_cpu_priv *priv = dev_get_priv(dev); + const struct bmips_cpu_hw *hw = priv->hw; + + return hw->get_cpu_count(priv); +} + +static int bmips_cpu_get_vendor(struct udevice *dev, char *buf, int size) +{ + snprintf(buf, size, "Broadcom"); + + return 0; +} + +static const struct cpu_ops bmips_cpu_ops = { + .get_desc = bmips_cpu_get_desc, + .get_info = bmips_cpu_get_info, + .get_count = bmips_cpu_get_count, + .get_vendor = bmips_cpu_get_vendor, +}; + +/* BMIPS CPU driver */ +int bmips_cpu_bind(struct udevice *dev) +{ + struct cpu_platdata *plat = dev_get_parent_platdata(dev); + + plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "reg", -1); + plat->device_id = read_c0_prid(); + + return 0; +} + +int bmips_cpu_probe(struct udevice *dev) +{ + struct bmips_cpu_priv *priv = dev_get_priv(dev); + const struct bmips_cpu_hw *hw = + (const struct bmips_cpu_hw *)dev_get_driver_data(dev); + fdt_addr_t addr; + fdt_size_t size; + + addr = dev_get_addr_size_index(dev_get_parent(dev), 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = ioremap(addr, size); + priv->hw = hw; + + return 0; +} + +static const struct udevice_id bmips_cpu_ids[] = { + { + .compatible = "brcm,bcm6328-cpu", + .data = (ulong)&bmips_cpu_bcm6328, + }, { + .compatible = "brcm,bcm6358-cpu", + .data = (ulong)&bmips_cpu_bcm6358, + }, { + .compatible = "brcm,bcm63268-cpu", + .data = (ulong)&bmips_cpu_bcm63268, + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(bmips_cpu_drv) = { + .name = "bmips_cpu", + .id = UCLASS_CPU, + .of_match = bmips_cpu_ids, + .bind = bmips_cpu_bind, + .probe = bmips_cpu_probe, + .priv_auto_alloc_size = sizeof(struct bmips_cpu_priv), + .ops = &bmips_cpu_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + struct cpu_info cpu; + struct udevice *dev; + int err; + char desc[100]; + + err = uclass_get_device(UCLASS_CPU, 0, &dev); + if (err) + return 0; + + err = cpu_get_info(dev, &cpu); + if (err) + return 0; + + err = cpu_get_desc(dev, desc, sizeof(desc)); + if (err) + return 0; + + printf("Chip ID: %s, MIPS: ", desc); + print_freq(cpu.cpu_freq, "\n"); + + return 0; +} +#endif