From patchwork Mon Dec 10 20:35:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 1010671 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) 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=collabora.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43DFJZ044Fz9s9h for ; Tue, 11 Dec 2018 07:38:05 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id BAEB3C223CB; Mon, 10 Dec 2018 20:36:37 +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_DNSWL_NONE, SPF_HELO_PASS, UNPARSEABLE_RELAY 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 EE0BFC22227; Mon, 10 Dec 2018 20:36:17 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 0B6E2C21EBF; Mon, 10 Dec 2018 20:36:14 +0000 (UTC) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lists.denx.de (Postfix) with ESMTPS id A8CA0C21E13 for ; Mon, 10 Dec 2018 20:36:14 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 2BFE3272849 From: Ezequiel Garcia To: u-boot@lists.denx.de Date: Mon, 10 Dec 2018 17:35:57 -0300 Message-Id: <20181210203602.820-2-ezequiel@collabora.com> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181210203602.820-1-ezequiel@collabora.com> References: <20181210203602.820-1-ezequiel@collabora.com> MIME-Version: 1.0 Cc: Marek Vasut , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [U-Boot] [PATCH 1/6] misc: Add JZ47xx efuse 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" From: Paul Burton Add driver for the efuse block in the JZ47xx SOC. Cc: Daniel Schwierzeck Signed-off-by: Paul Burton Signed-off-by: Marek Vasut --- drivers/misc/Kconfig | 6 +++ drivers/misc/Makefile | 1 + drivers/misc/jz4780_efuse.c | 100 ++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 drivers/misc/jz4780_efuse.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 48febc47d263..704c8dd1955f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -120,6 +120,12 @@ config FSL_SEC_MON Security Monitor can be transitioned on any security failures, like software violations or hardware security violations. +config JZ4780_EFUSE + bool "Ingenic JZ4780 eFUSE support" + depends on ARCH_JZ47XX + help + This selects support for the eFUSE on Ingenic JZ4780 SoCs. + config MXC_OCOTP bool "Enable MXC OCOTP Driver" help diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 302d44159274..6bdf5054f475 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -62,3 +62,4 @@ obj-$(CONFIG_TEGRA_CAR) += tegra_car.o obj-$(CONFIG_TWL4030_LED) += twl4030_led.o obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o +obj-$(CONFIG_JZ4780_EFUSE) += jz4780_efuse.o diff --git a/drivers/misc/jz4780_efuse.c b/drivers/misc/jz4780_efuse.c new file mode 100644 index 000000000000..78383f343dce --- /dev/null +++ b/drivers/misc/jz4780_efuse.c @@ -0,0 +1,100 @@ +/* + * JZ4780 EFUSE driver + * + * Copyright (c) 2014 Imagination Technologies + * Author: Alex Smith + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#define EFUSE_EFUCTRL 0xd0 +#define EFUSE_EFUCFG 0xd4 +#define EFUSE_EFUSTATE 0xd8 +#define EFUSE_EFUDATA(n) (0xdc + ((n) * 4)) + +#define EFUSE_EFUCTRL_RD_EN BIT(0) +#define EFUSE_EFUCTRL_LEN_BIT 16 +#define EFUSE_EFUCTRL_LEN_MASK 0x1f +#define EFUSE_EFUCTRL_ADDR_BIT 21 +#define EFUSE_EFUCTRL_ADDR_MASK 0x1ff +#define EFUSE_EFUCTRL_CS BIT(30) + +#define EFUSE_EFUCFG_RD_STROBE_BIT 16 +#define EFUSE_EFUCFG_RD_STROBE_MASK 0xf +#define EFUSE_EFUCFG_RD_ADJ_BIT 20 +#define EFUSE_EFUCFG_RD_ADJ_MASK 0xf + +#define EFUSE_EFUSTATE_RD_DONE BIT(0) + +static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf) +{ + void __iomem *regs = (void __iomem *)NEMC_BASE; + size_t i; + u32 val; + + val = EFUSE_EFUCTRL_RD_EN | + ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) | + (addr << EFUSE_EFUCTRL_ADDR_BIT) | + ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0); + writel(val, regs + EFUSE_EFUCTRL); + /* FIXME -- wait_bit() */ + while (!(readl(regs + EFUSE_EFUSTATE) & EFUSE_EFUSTATE_RD_DONE)) + ; + + if ((count % 4) == 0) { + for (i = 0; i < count / 4; i++) { + val = readl(regs + EFUSE_EFUDATA(i)); + put_unaligned(val, (u32 *)(buf + (i * 4))); + } + } else { + val = readl(regs + EFUSE_EFUDATA(0)); + if (count > 2) + buf[2] = (val >> 16) & 0xff; + if (count > 1) + buf[1] = (val >> 8) & 0xff; + buf[0] = val & 0xff; + } +} + +static inline int jz4780_efuse_chunk_size(size_t count) +{ + if (count >= 32) + return 32; + else if ((count / 4) > 0) + return (count / 4) * 4; + else + return count % 4; +} + +void jz4780_efuse_read(size_t addr, size_t count, u8 *buf) +{ + size_t chunk; + + while (count > 0) { + chunk = jz4780_efuse_chunk_size(count); + jz4780_efuse_read_chunk(addr, chunk, buf); + addr += chunk; + buf += chunk; + count -= chunk; + } +} + +void jz4780_efuse_init(u32 ahb2_rate) +{ + void __iomem *regs = (void __iomem *)NEMC_BASE; + u32 rd_adj, rd_strobe, tmp; + + rd_adj = (((6500 * (ahb2_rate / 1000000)) / 1000000) + 0xf) / 2; + tmp = (((35000 * (ahb2_rate / 1000000)) / 1000000) - 4) - rd_adj; + rd_strobe = ((tmp + 0xf) / 2 < 7) ? 7 : (tmp + 0xf) / 2; + + tmp = (rd_adj << EFUSE_EFUCFG_RD_ADJ_BIT) | + (rd_strobe << EFUSE_EFUCFG_RD_STROBE_BIT); + writel(tmp, regs + EFUSE_EFUCFG); +} From patchwork Mon Dec 10 20:35:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 1010669 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) 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=collabora.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43DFHr1Xftz9s4s for ; Tue, 11 Dec 2018 07:37:28 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id D7515C22398; Mon, 10 Dec 2018 20:36:56 +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_DNSWL_NONE, SPF_HELO_PASS, UNPARSEABLE_RELAY 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 B429AC22286; Mon, 10 Dec 2018 20:36:27 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 287E5C220D6; Mon, 10 Dec 2018 20:36:21 +0000 (UTC) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lists.denx.de (Postfix) with ESMTPS id 7AB80C21EBF for ; Mon, 10 Dec 2018 20:36:17 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id EEA84276FEF From: Ezequiel Garcia To: u-boot@lists.denx.de Date: Mon, 10 Dec 2018 17:35:58 -0300 Message-Id: <20181210203602.820-3-ezequiel@collabora.com> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181210203602.820-1-ezequiel@collabora.com> References: <20181210203602.820-1-ezequiel@collabora.com> MIME-Version: 1.0 Cc: Marek Vasut , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [U-Boot] [PATCH 2/6] gpio: Add JZ47xx GPIO 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" From: Paul Burton Add primitive GPIO controller driver for the JZ47xx SoC. Cc: Daniel Schwierzeck Signed-off-by: Paul Burton Signed-off-by: Marek Vasut --- drivers/gpio/Kconfig | 7 ++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-jz47xx.c | 78 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 drivers/gpio/gpio-jz47xx.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 35344e57c6c6..46c161c99ce9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -322,4 +322,11 @@ config MT7621_GPIO help Say yes here to support MediaTek MT7621 compatible GPIOs. +config JZ47XX_GPIO + bool "Ingenic JZ47xx GPIO driver" + depends on ARCH_JZ47XX + default y + help + Supports GPIO access on Ingenic JZ47xx SoCs. + endmenu diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 7ed9a4ec4221..92310e9ba934 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o +obj-$(CONFIG_JZ47XX_GPIO) += gpio-jz47xx.o diff --git a/drivers/gpio/gpio-jz47xx.c b/drivers/gpio/gpio-jz47xx.c new file mode 100644 index 000000000000..565108192306 --- /dev/null +++ b/drivers/gpio/gpio-jz47xx.c @@ -0,0 +1,78 @@ +/* + * Ingenic JZ47xx GPIO + * + * Copyright (C) 2018 Marek Vasut + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +int gpio_get_value(unsigned gpio) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + int port = gpio / 32; + int pin = gpio % 32; + + return readl(gpio_regs + GPIO_PXPIN(port)) & BIT(pin); +} + +int gpio_set_value(unsigned gpio, int value) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + int port = gpio / 32; + int pin = gpio % 32; + + if (value) + writel(BIT(pin), gpio_regs + GPIO_PXPAT0S(port)); + else + writel(BIT(pin), gpio_regs + GPIO_PXPAT0C(port)); + + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + int port = gpio / 32; + int pin = gpio % 32; + + writel(BIT(pin), gpio_regs + GPIO_PXINTC(port)); + writel(BIT(pin), gpio_regs + GPIO_PXMASKS(port)); + writel(BIT(pin), gpio_regs + GPIO_PXPAT1S(port)); + + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + int port = gpio / 32; + int pin = gpio % 32; + + writel(BIT(pin), gpio_regs + GPIO_PXINTC(port)); + writel(BIT(pin), gpio_regs + GPIO_PXMASKS(port)); + writel(BIT(pin), gpio_regs + GPIO_PXPAT1C(port)); + + gpio_set_value(gpio, value); + + return 0; +} + +int gpio_request(unsigned gpio, const char *label) +{ + int port = gpio / 32; + + if (port >= 6) + return -EINVAL; + + return 0; +} + +int gpio_free(unsigned gpio) +{ + return 0; +} From patchwork Mon Dec 10 20:35:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 1010672 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) 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=collabora.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43DFK96HP0z9s9h for ; Tue, 11 Dec 2018 07:38:35 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 9E38FC22193; Mon, 10 Dec 2018 20:37:16 +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_DNSWL_NONE, SPF_HELO_PASS, UNPARSEABLE_RELAY 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 B716CC2232A; Mon, 10 Dec 2018 20:36:34 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id B7397C220E1; Mon, 10 Dec 2018 20:36:24 +0000 (UTC) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lists.denx.de (Postfix) with ESMTPS id BD86FC222D5 for ; Mon, 10 Dec 2018 20:36:20 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id C1A7F2610F6 From: Ezequiel Garcia To: u-boot@lists.denx.de Date: Mon, 10 Dec 2018 17:35:59 -0300 Message-Id: <20181210203602.820-4-ezequiel@collabora.com> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181210203602.820-1-ezequiel@collabora.com> References: <20181210203602.820-1-ezequiel@collabora.com> MIME-Version: 1.0 Cc: Marek Vasut , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [U-Boot] [PATCH 3/6] mmc: Add JZ47xx SD/MMC controller 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" From: Paul Burton Add driver for the JZ47xx MSC controller. Cc: Daniel Schwierzeck Signed-off-by: Paul Burton Signed-off-by: Marek Vasut Signed-off-by: Ezequiel Garcia --- drivers/mmc/Kconfig | 6 + drivers/mmc/Makefile | 1 + drivers/mmc/jz_mmc. | 0 drivers/mmc/jz_mmc.c | 491 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 498 insertions(+) create mode 100644 drivers/mmc/jz_mmc. create mode 100644 drivers/mmc/jz_mmc.c diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index fbd13964a084..496b2cba6405 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -332,6 +332,12 @@ config MMC_BCM2835 If unsure, say N. +config JZ47XX_MMC + bool "Ingenic JZ47xx SD/MMC Host Controller support" + depends on ARCH_JZ47XX + help + This selects support for the SD Card Controller on Ingenic JZ47xx SoCs. + config MMC_SANDBOX bool "Sandbox MMC support" depends on SANDBOX diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 801a26d82192..7892c468f05c 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_MMC_SANDBOX) += sandbox_mmc.o obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_SH_SDHI) += sh_sdhi.o obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o +obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI) += sdhci.o diff --git a/drivers/mmc/jz_mmc. b/drivers/mmc/jz_mmc. new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c new file mode 100644 index 000000000000..18c1810ff42c --- /dev/null +++ b/drivers/mmc/jz_mmc.c @@ -0,0 +1,491 @@ +/* + * Ingenic JZ MMC driver + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define MSC_STRPCL 0x000 +#define MSC_STAT 0x004 +#define MSC_CLKRT 0x008 +#define MSC_CMDAT 0x00c +#define MSC_RESTO 0x010 +#define MSC_RDTO 0x014 +#define MSC_BLKLEN 0x018 +#define MSC_NOB 0x01c +#define MSC_SNOB 0x020 +#define MSC_IMASK 0x024 +#define MSC_IREG 0x028 +#define MSC_CMD 0x02c +#define MSC_ARG 0x030 +#define MSC_RES 0x034 +#define MSC_RXFIFO 0x038 +#define MSC_TXFIFO 0x03c +#define MSC_LPM 0x040 +#define MSC_DMAC 0x044 +#define MSC_DMANDA 0x048 +#define MSC_DMADA 0x04c +#define MSC_DMALEN 0x050 +#define MSC_DMACMD 0x054 +#define MSC_CTRL2 0x058 +#define MSC_RTCNT 0x05c +#define MSC_DBG 0x0fc + +/* MSC Clock and Control Register (MSC_STRPCL) */ +#define MSC_STRPCL_EXIT_MULTIPLE BIT(7) +#define MSC_STRPCL_EXIT_TRANSFER BIT(6) +#define MSC_STRPCL_START_READWAIT BIT(5) +#define MSC_STRPCL_STOP_READWAIT BIT(4) +#define MSC_STRPCL_RESET BIT(3) +#define MSC_STRPCL_START_OP BIT(2) +#define MSC_STRPCL_CLOCK_CONTROL_STOP BIT(0) +#define MSC_STRPCL_CLOCK_CONTROL_START BIT(1) + +/* MSC Status Register (MSC_STAT) */ +#define MSC_STAT_AUTO_CMD_DONE BIT(31) +#define MSC_STAT_IS_RESETTING BIT(15) +#define MSC_STAT_SDIO_INT_ACTIVE BIT(14) +#define MSC_STAT_PRG_DONE BIT(13) +#define MSC_STAT_DATA_TRAN_DONE BIT(12) +#define MSC_STAT_END_CMD_RES BIT(11) +#define MSC_STAT_DATA_FIFO_AFULL BIT(10) +#define MSC_STAT_IS_READWAIT BIT(9) +#define MSC_STAT_CLK_EN BIT(8) +#define MSC_STAT_DATA_FIFO_FULL BIT(7) +#define MSC_STAT_DATA_FIFO_EMPTY BIT(6) +#define MSC_STAT_CRC_RES_ERR BIT(5) +#define MSC_STAT_CRC_READ_ERROR BIT(4) +#define MSC_STAT_CRC_WRITE_ERROR BIT(2) +#define MSC_STAT_CRC_WRITE_ERROR_NOSTS BIT(4) +#define MSC_STAT_TIME_OUT_RES BIT(1) +#define MSC_STAT_TIME_OUT_READ BIT(0) + +/* MSC Bus Clock Control Register (MSC_CLKRT) */ +#define MSC_CLKRT_CLK_RATE_MASK 0x7 + +/* MSC Command Sequence Control Register (MSC_CMDAT) */ +#define MSC_CMDAT_IO_ABORT BIT(11) +#define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << 9) +#define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << 9) +#define MSC_CMDAT_DMA_EN BIT(8) +#define MSC_CMDAT_INIT BIT(7) +#define MSC_CMDAT_BUSY BIT(6) +#define MSC_CMDAT_STREAM_BLOCK BIT(5) +#define MSC_CMDAT_WRITE BIT(4) +#define MSC_CMDAT_DATA_EN BIT(3) +#define MSC_CMDAT_RESPONSE_MASK (0x7 << 0) +#define MSC_CMDAT_RESPONSE_NONE (0x0 << 0) /* No response */ +#define MSC_CMDAT_RESPONSE_R1 (0x1 << 0) /* Format R1 and R1b */ +#define MSC_CMDAT_RESPONSE_R2 (0x2 << 0) /* Format R2 */ +#define MSC_CMDAT_RESPONSE_R3 (0x3 << 0) /* Format R3 */ +#define MSC_CMDAT_RESPONSE_R4 (0x4 << 0) /* Format R4 */ +#define MSC_CMDAT_RESPONSE_R5 (0x5 << 0) /* Format R5 */ +#define MSC_CMDAT_RESPONSE_R6 (0x6 << 0) /* Format R6 */ + +/* MSC Interrupts Mask Register (MSC_IMASK) */ +#define MSC_IMASK_TIME_OUT_RES BIT(9) +#define MSC_IMASK_TIME_OUT_READ BIT(8) +#define MSC_IMASK_SDIO BIT(7) +#define MSC_IMASK_TXFIFO_WR_REQ BIT(6) +#define MSC_IMASK_RXFIFO_RD_REQ BIT(5) +#define MSC_IMASK_END_CMD_RES BIT(2) +#define MSC_IMASK_PRG_DONE BIT(1) +#define MSC_IMASK_DATA_TRAN_DONE BIT(0) + +/* MSC Interrupts Status Register (MSC_IREG) */ +#define MSC_IREG_TIME_OUT_RES BIT(9) +#define MSC_IREG_TIME_OUT_READ BIT(8) +#define MSC_IREG_SDIO BIT(7) +#define MSC_IREG_TXFIFO_WR_REQ BIT(6) +#define MSC_IREG_RXFIFO_RD_REQ BIT(5) +#define MSC_IREG_END_CMD_RES BIT(2) +#define MSC_IREG_PRG_DONE BIT(1) +#define MSC_IREG_DATA_TRAN_DONE BIT(0) + +struct jz_mmc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +struct jz_mmc_priv { + void __iomem *regs; + u32 flags; +/* priv flags */ +#define JZ_MMC_BUS_WIDTH_MASK 0x3 +#define JZ_MMC_BUS_WIDTH_1 0x0 +#define JZ_MMC_BUS_WIDTH_4 0x2 +#define JZ_MMC_BUS_WIDTH_8 0x3 +#define JZ_MMC_SENT_INIT BIT(2) +}; + +static int jz_mmc_clock_rate(void) +{ + return 24000000; +} + +static int jz_mmc_send_cmd(struct mmc *mmc, struct jz_mmc_priv *priv, + struct mmc_cmd *cmd, struct mmc_data *data) +{ + u32 stat, mask, cmdat = 0; + + /* stop the clock */ + writel(MSC_STRPCL_CLOCK_CONTROL_STOP, priv->regs + MSC_STRPCL); + while (readl(priv->regs + MSC_STAT) & MSC_STAT_CLK_EN) + ; + + writel(0, priv->regs + MSC_DMAC); + + /* setup command */ + writel(cmd->cmdidx, priv->regs + MSC_CMD); + writel(cmd->cmdarg, priv->regs + MSC_ARG); + + if (data) { + /* setup data */ + cmdat |= MSC_CMDAT_DATA_EN; + if (data->flags & MMC_DATA_WRITE) + cmdat |= MSC_CMDAT_WRITE; + + writel(data->blocks, priv->regs + MSC_NOB); + writel(data->blocksize, priv->regs + MSC_BLKLEN); + } else { + writel(0, priv->regs + MSC_NOB); + writel(0, priv->regs + MSC_BLKLEN); + } + + /* setup response */ + switch (cmd->resp_type) { + case MMC_RSP_NONE: + break; + case MMC_RSP_R1: + case MMC_RSP_R1b: + cmdat |= MSC_CMDAT_RESPONSE_R1; + break; + case MMC_RSP_R2: + cmdat |= MSC_CMDAT_RESPONSE_R2; + break; + case MMC_RSP_R3: + cmdat |= MSC_CMDAT_RESPONSE_R3; + break; + default: + break; + } + + if (cmd->resp_type & MMC_RSP_BUSY) + cmdat |= MSC_CMDAT_BUSY; + + /* set init for the first command only */ + if (!(priv->flags & JZ_MMC_SENT_INIT)) { + cmdat |= MSC_CMDAT_INIT; + priv->flags |= JZ_MMC_SENT_INIT; + } + + cmdat |= (priv->flags & JZ_MMC_BUS_WIDTH_MASK) << 9; + + /* write the data setup */ + writel(cmdat, priv->regs + MSC_CMDAT); + + /* unmask interrupts */ + mask = 0xffffffff & ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_TIME_OUT_RES); + if (data) { + mask &= ~MSC_IMASK_DATA_TRAN_DONE; + if (data->flags & MMC_DATA_WRITE) { + mask &= ~MSC_IMASK_TXFIFO_WR_REQ; + } else { + mask &= ~(MSC_IMASK_RXFIFO_RD_REQ | + MSC_IMASK_TIME_OUT_READ); + } + } + writel(mask, priv->regs + MSC_IMASK); + + /* clear interrupts */ + writel(0xffffffff, priv->regs + MSC_IREG); + + /* start the command (& the clock) */ + writel(MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START, + priv->regs + MSC_STRPCL); + + /* wait for completion */ + for (;;) { + stat = readl(priv->regs + MSC_IREG); + stat &= MSC_IREG_END_CMD_RES | MSC_IREG_TIME_OUT_RES; + if (stat) + break; + mdelay(1); + } + writel(stat, priv->regs + MSC_IREG); + if (stat & MSC_IREG_TIME_OUT_RES) + return -ETIMEDOUT; + + if (cmd->resp_type & MMC_RSP_PRESENT) { + /* read the response */ + if (cmd->resp_type & MMC_RSP_136) { + u16 a, b, c, i; + + a = readw(priv->regs + MSC_RES); + for (i = 0; i < 4; i++) { + b = readw(priv->regs + MSC_RES); + c = readw(priv->regs + MSC_RES); + cmd->response[i] = + (a << 24) | (b << 8) | (c >> 8); + a = c; + } + } else { + cmd->response[0] = readw(priv->regs + MSC_RES) << 24; + cmd->response[0] |= readw(priv->regs + MSC_RES) << 8; + cmd->response[0] |= readw(priv->regs + MSC_RES) & 0xff; + } + } + + if (data && (data->flags & MMC_DATA_WRITE)) { + /* write the data */ + int sz = DIV_ROUND_UP(data->blocks * data->blocksize, 4); + const void *buf = data->src; + + while (sz--) { + u32 val = get_unaligned_le32(buf); + + while (!(readl(priv->regs + MSC_IREG) & + MSC_IREG_TXFIFO_WR_REQ)) + ; + writel(val, priv->regs + MSC_TXFIFO); + buf += 4; + } + } else if (data && (data->flags & MMC_DATA_READ)) { + /* read the data */ + int sz = data->blocks * data->blocksize; + void *buf = data->dest; + + do { + stat = readl(priv->regs + MSC_STAT); + + if (stat & MSC_STAT_TIME_OUT_READ) + return -ETIMEDOUT; + if (stat & MSC_STAT_CRC_READ_ERROR) + return -EINVAL; + if (stat & MSC_STAT_DATA_FIFO_EMPTY) { + udelay(10); + continue; + } + do { + u32 val = readl(priv->regs + MSC_RXFIFO); + + if (sz == 1) + *(u8 *)buf = (u8)val; + else if (sz == 2) + put_unaligned_le16(val, buf); + else if (sz >= 4) + put_unaligned_le32(val, buf); + buf += 4; + sz -= 4; + stat = readl(priv->regs + MSC_STAT); + } while (!(stat & MSC_STAT_DATA_FIFO_EMPTY)); + } while (!(stat & MSC_STAT_DATA_TRAN_DONE)); + } + + return 0; +} + +static int jz_mmc_set_ios(struct mmc *mmc, struct jz_mmc_priv *priv) +{ + u32 real_rate = jz_mmc_clock_rate(); + u8 clk_div = 0; + + /* calculate clock divide */ + while ((real_rate > mmc->clock) && (clk_div < 7)) { + real_rate >>= 1; + clk_div++; + } + writel(clk_div & MSC_CLKRT_CLK_RATE_MASK, priv->regs + MSC_CLKRT); + + /* set the bus width for the next command */ + priv->flags &= ~JZ_MMC_BUS_WIDTH_MASK; + if (mmc->bus_width == 8) + priv->flags |= JZ_MMC_BUS_WIDTH_8; + else if (mmc->bus_width == 4) + priv->flags |= JZ_MMC_BUS_WIDTH_4; + else + priv->flags |= JZ_MMC_BUS_WIDTH_1; + + return 0; +} + +static int jz_mmc_core_init(struct mmc *mmc) +{ + struct jz_mmc_priv *priv = mmc->priv; + unsigned int timeout = 1000; + u32 status; + + /* Reset */ + writel(MSC_STRPCL_RESET, priv->regs + MSC_STRPCL); + udelay(10); + do { + status = readl(priv->regs + MSC_STAT); + } while (status & MSC_STAT_IS_RESETTING && --timeout); + + if (!timeout) { + printf("jz_mmc: timeout on reset\n"); + return -ETIMEDOUT; + } + + /* Maximum timeouts */ + writel(0xffff, priv->regs + MSC_RESTO); + writel(0xffffffff, priv->regs + MSC_RDTO); + + /* Enable low power mode */ + writel(0x1, priv->regs + MSC_LPM); + + return 0; +} + +#if !CONFIG_IS_ENABLED(DM_MMC) + +static int jz_mmc_legacy_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct jz_mmc_priv *priv = mmc->priv; + + return jz_mmc_send_cmd(mmc, priv, cmd, data); +} + +static int jz_mmc_legacy_set_ios(struct mmc *mmc) +{ + struct jz_mmc_priv *priv = mmc->priv; + + return jz_mmc_set_ios(mmc, priv); +}; + +static const struct mmc_ops jz_msc_ops = { + .send_cmd = jz_mmc_legacy_send_cmd, + .set_ios = jz_mmc_legacy_set_ios, + .init = jz_mmc_core_init, +}; + +static struct jz_mmc_priv jz_mmc_priv_static; +static struct jz_mmc_plat jz_mmc_plat_static = { + .cfg = { + .name = "MSC", + .ops = &jz_msc_ops, + + .voltages = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | + MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | + MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36, + .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS, + + .f_min = 375000, + .f_max = 48000000, + .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, + }, +}; + +int jz_mmc_init(void __iomem *base) +{ + struct mmc *mmc; + + jz_mmc_priv_static.regs = base; + + mmc = mmc_create(&jz_mmc_plat_static.cfg, &jz_mmc_priv_static); + + return mmc ? 0 : -ENODEV; +} + +#else /* CONFIG_DM_MMC */ + +#include +DECLARE_GLOBAL_DATA_PTR; + +static int jz_mmc_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct jz_mmc_priv *priv = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return jz_mmc_send_cmd(mmc, priv, cmd, data); +} + +static int jz_mmc_dm_set_ios(struct udevice *dev) +{ + struct jz_mmc_priv *priv = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return jz_mmc_set_ios(mmc, priv); +}; + +static const struct dm_mmc_ops jz_msc_ops = { + .send_cmd = jz_mmc_dm_send_cmd, + .set_ios = jz_mmc_dm_set_ios, +}; + +static int jz_mmc_ofdata_to_platdata(struct udevice *dev) +{ + struct jz_mmc_priv *priv = dev_get_priv(dev); + struct jz_mmc_plat *plat = dev_get_platdata(dev); + struct mmc_config *cfg; + int ret; + + priv->regs = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); + cfg = &plat->cfg; + + cfg->name = "MSC"; + cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; + + ret = mmc_of_parse(dev, cfg); + if (ret < 0) { + dev_err(dev, "failed to parse host caps\n"); + return ret; + } + + cfg->f_min = 400000; + cfg->f_max = 52000000; + + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + return 0; +} + +static int jz_mmc_bind(struct udevice *dev) +{ + struct jz_mmc_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + +static int jz_mmc_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct jz_mmc_priv *priv = dev_get_priv(dev); + struct jz_mmc_plat *plat = dev_get_platdata(dev); + + plat->mmc.priv = priv; + upriv->mmc = &plat->mmc; + return jz_mmc_core_init(&plat->mmc); +} + +static const struct udevice_id jz_mmc_ids[] = { + { .compatible = "ingenic,jz4780-mmc" }, + { } +}; + +U_BOOT_DRIVER(jz_mmc_drv) = { + .name = "jz_mmc", + .id = UCLASS_MMC, + .of_match = jz_mmc_ids, + .ofdata_to_platdata = jz_mmc_ofdata_to_platdata, + .bind = jz_mmc_bind, + .probe = jz_mmc_probe, + .priv_auto_alloc_size = sizeof(struct jz_mmc_priv), + .platdata_auto_alloc_size = sizeof(struct jz_mmc_plat), + .ops = &jz_msc_ops, +}; +#endif /* CONFIG_DM_MMC */ From patchwork Mon Dec 10 20:36:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 1010676 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) 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=collabora.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43DFMr1ThZz9s4s for ; Tue, 11 Dec 2018 07:40:56 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id C369EC22227; Mon, 10 Dec 2018 20:40:35 +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_DNSWL_NONE, SPF_HELO_PASS, UNPARSEABLE_RELAY 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 3C1B5C22012; Mon, 10 Dec 2018 20:36:59 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 895BEC22193; Mon, 10 Dec 2018 20:36:27 +0000 (UTC) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lists.denx.de (Postfix) with ESMTPS id 07FB2C22366 for ; Mon, 10 Dec 2018 20:36:24 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 10080272849 From: Ezequiel Garcia To: u-boot@lists.denx.de Date: Mon, 10 Dec 2018 17:36:00 -0300 Message-Id: <20181210203602.820-5-ezequiel@collabora.com> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181210203602.820-1-ezequiel@collabora.com> References: <20181210203602.820-1-ezequiel@collabora.com> MIME-Version: 1.0 Cc: Marek Vasut , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [U-Boot] [PATCH 4/6] mips: Add SPL header 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" From: Paul Burton Add header with SPL boot mode and type definitions. Cc: Daniel Schwierzeck Signed-off-by: Paul Burton Signed-off-by: Marek Vasut --- arch/mips/include/asm/spl.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 arch/mips/include/asm/spl.h diff --git a/arch/mips/include/asm/spl.h b/arch/mips/include/asm/spl.h new file mode 100644 index 000000000000..01baab606606 --- /dev/null +++ b/arch/mips/include/asm/spl.h @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2012 + * Texas Instruments, + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _ASM_SPL_H_ +#define _ASM_SPL_H_ + +enum { + BOOT_DEVICE_RAM, + BOOT_DEVICE_MMC1, + BOOT_DEVICE_MMC2, + BOOT_DEVICE_MMC2_2, + BOOT_DEVICE_NAND, + BOOT_DEVICE_ONENAND, + BOOT_DEVICE_NOR, + BOOT_DEVICE_UART, + BOOT_DEVICE_SPI, + BOOT_DEVICE_USB, + BOOT_DEVICE_SATA, + BOOT_DEVICE_I2C, + BOOT_DEVICE_BOARD, + BOOT_DEVICE_NONE +}; + +/* Linker symbols. */ +extern char __bss_start[]; +extern ulong __bss_end; + +#ifndef CONFIG_DM +extern gd_t gdata; +#endif + +#endif From patchwork Mon Dec 10 20:36:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 1010673 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) 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=collabora.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43DFK96HL2z9s4s for ; Tue, 11 Dec 2018 07:38:33 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 73B7EC22334; Mon, 10 Dec 2018 20:38:06 +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_DNSWL_NONE, SPF_HELO_PASS, UNPARSEABLE_RELAY 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 C5F8AC222D5; Mon, 10 Dec 2018 20:36:40 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 28184C22381; Mon, 10 Dec 2018 20:36:33 +0000 (UTC) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lists.denx.de (Postfix) with ESMTPS id 3369EC2237C for ; Mon, 10 Dec 2018 20:36:29 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 50DEE276FEF From: Ezequiel Garcia To: u-boot@lists.denx.de Date: Mon, 10 Dec 2018 17:36:01 -0300 Message-Id: <20181210203602.820-6-ezequiel@collabora.com> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181210203602.820-1-ezequiel@collabora.com> References: <20181210203602.820-1-ezequiel@collabora.com> MIME-Version: 1.0 Cc: Marek Vasut , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [U-Boot] [PATCH 5/6] mips: jz47xx: Add JZ4780 SoC support 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" From: Paul Burton Add initial support for the Ingenic JZ47xx MIPS SoC. Cc: Daniel Schwierzeck Signed-off-by: Paul Burton Signed-off-by: Marek Vasut Signed-off-by: Ezequiel Garcia --- arch/mips/Kconfig | 7 + arch/mips/Makefile | 1 + arch/mips/dts/jz4780.dtsi | 162 ++++++ arch/mips/mach-jz47xx/Kconfig | 15 + arch/mips/mach-jz47xx/Makefile | 7 + arch/mips/mach-jz47xx/include/mach/jz4780.h | 104 ++++ .../mach-jz47xx/include/mach/jz4780_dram.h | 457 +++++++++++++++ arch/mips/mach-jz47xx/jz4780/Makefile | 5 + arch/mips/mach-jz47xx/jz4780/jz4780.c | 142 +++++ arch/mips/mach-jz47xx/jz4780/pll.c | 528 ++++++++++++++++++ arch/mips/mach-jz47xx/jz4780/sdram.c | 271 +++++++++ arch/mips/mach-jz47xx/jz4780/timer.c | 238 ++++++++ arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds | 52 ++ arch/mips/mach-jz47xx/start.S | 99 ++++ include/dt-bindings/clock/jz4780-cgu.h | 88 +++ 15 files changed, 2176 insertions(+) create mode 100644 arch/mips/dts/jz4780.dtsi create mode 100644 arch/mips/mach-jz47xx/Kconfig create mode 100644 arch/mips/mach-jz47xx/Makefile create mode 100644 arch/mips/mach-jz47xx/include/mach/jz4780.h create mode 100644 arch/mips/mach-jz47xx/include/mach/jz4780_dram.h create mode 100644 arch/mips/mach-jz47xx/jz4780/Makefile create mode 100644 arch/mips/mach-jz47xx/jz4780/jz4780.c create mode 100644 arch/mips/mach-jz47xx/jz4780/pll.c create mode 100644 arch/mips/mach-jz47xx/jz4780/sdram.c create mode 100644 arch/mips/mach-jz47xx/jz4780/timer.c create mode 100644 arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds create mode 100644 arch/mips/mach-jz47xx/start.S create mode 100644 include/dt-bindings/clock/jz4780-cgu.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1b1b1d7d0031..44b25460b8cc 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -88,6 +88,12 @@ config ARCH_MT7620 select SUPPORTS_LITTLE_ENDIAN select SYSRESET +config ARCH_JZ47XX + bool "Support Ingenic JZ47xx" + select SUPPORT_SPL + select OF_CONTROL + select DM + config MACH_PIC32 bool "Support Microchip PIC32" select DM @@ -139,6 +145,7 @@ source "board/micronas/vct/Kconfig" source "board/qemu-mips/Kconfig" source "arch/mips/mach-ath79/Kconfig" source "arch/mips/mach-bmips/Kconfig" +source "arch/mips/mach-jz47xx/Kconfig" source "arch/mips/mach-pic32/Kconfig" source "arch/mips/mach-mt7620/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 802244a06e5d..a294e9b1e8b9 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -13,6 +13,7 @@ libs-y += arch/mips/lib/ machine-$(CONFIG_ARCH_ATH79) += ath79 machine-$(CONFIG_ARCH_BMIPS) += bmips +machine-$(CONFIG_ARCH_JZ47XX) += jz47xx machine-$(CONFIG_MACH_PIC32) += pic32 machine-$(CONFIG_ARCH_MT7620) += mt7620 diff --git a/arch/mips/dts/jz4780.dtsi b/arch/mips/dts/jz4780.dtsi new file mode 100644 index 000000000000..e34f8d359036 --- /dev/null +++ b/arch/mips/dts/jz4780.dtsi @@ -0,0 +1,162 @@ +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ingenic,jz4780"; + + cpuintc: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: interrupt-controller@10001000 { + compatible = "ingenic,jz4780-intc"; + reg = <0x10001000 0x50>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + rtc: rtc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + cgu: jz4780-cgu@10000000 { + compatible = "ingenic,jz4780-cgu"; + reg = <0x10000000 0x100>; + + clocks = <&ext>, <&rtc>; + clock-names = "ext", "rtc"; + + #clock-cells = <1>; + }; + + mmc0: mmc@13450000 { + compatible = "ingenic,jz4780-mmc"; + reg = <0x13450000 0x1000>; + + status = "disabled"; + + clocks = <&cgu JZ4780_CLK_MSC0>; + clock-names = "mmc"; + }; + + mmc1: mmc@13460000 { + compatible = "ingenic,jz4780-mmc"; + reg = <0x13460000 0x1000>; + + clocks = <&cgu JZ4780_CLK_MSC1>; + clock-names = "mmc"; + + status = "disabled"; + }; + + uart0: serial@10030000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10030000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <51>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART0>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart1: serial@10031000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10031000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <50>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART1>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart2: serial@10032000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10032000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <49>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART2>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart3: serial@10033000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10033000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <48>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART3>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + uart4: serial@10034000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10034000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <34>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART4>; + clock-names = "baud", "module"; + + status = "disabled"; + }; + + nemc: nemc@13410000 { + compatible = "ingenic,jz4780-nemc"; + reg = <0x13410000 0x10000>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <1 0 0x1b000000 0x1000000 + 2 0 0x1a000000 0x1000000 + 3 0 0x19000000 0x1000000 + 4 0 0x18000000 0x1000000 + 5 0 0x17000000 0x1000000 + 6 0 0x16000000 0x1000000>; + + clocks = <&cgu JZ4780_CLK_NEMC>; + + status = "disabled"; + }; + + bch: bch@134d0000 { + compatible = "ingenic,jz4780-bch"; + reg = <0x134d0000 0x10000>; + + clocks = <&cgu JZ4780_CLK_BCH>; + + status = "disabled"; + }; +}; diff --git a/arch/mips/mach-jz47xx/Kconfig b/arch/mips/mach-jz47xx/Kconfig new file mode 100644 index 000000000000..cd6944cfc252 --- /dev/null +++ b/arch/mips/mach-jz47xx/Kconfig @@ -0,0 +1,15 @@ +menu "Ingenic JZ47xx platforms" + depends on ARCH_JZ47XX + +config SYS_SOC + default "jz47xx" + +config SOC_JZ4780 + bool + select SUPPORTS_LITTLE_ENDIAN + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + help + Support for Ingenic JZ4780 family SoCs. + +endmenu diff --git a/arch/mips/mach-jz47xx/Makefile b/arch/mips/mach-jz47xx/Makefile new file mode 100644 index 000000000000..5eee9acf559d --- /dev/null +++ b/arch/mips/mach-jz47xx/Makefile @@ -0,0 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +extra-$(CONFIG_SPL_BUILD) := start.o + +obj-$(CONFIG_SOC_JZ4780) += jz4780/ diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780.h b/arch/mips/mach-jz47xx/include/mach/jz4780.h new file mode 100644 index 000000000000..86a6cc44d7c7 --- /dev/null +++ b/arch/mips/mach-jz47xx/include/mach/jz4780.h @@ -0,0 +1,104 @@ +/* + * JZ4780 definitions + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __JZ4780_H__ +#define __JZ4780_H__ + +/* AHB0 BUS Devices */ +#define DDRC_BASE 0xb3010000 + +/* AHB2 BUS Devices */ +#define NEMC_BASE 0xb3410000 +#define BCH_BASE 0xb34d0000 + +/* APB BUS Devices */ +#define CPM_BASE 0xb0000000 +#define TCU_BASE 0xb0002000 +#define WDT_BASE 0xb0002000 +#define GPIO_BASE 0xb0010000 +#define UART0_BASE 0xb0030000 +#define UART1_BASE 0xb0031000 +#define UART2_BASE 0xb0032000 +#define UART3_BASE 0xb0033000 +#define MSC0_BASE 0xb3450000 +#define MSC1_BASE 0xb3460000 +#define MSC2_BASE 0xb3470000 + +/* + * GPIO + */ +/* n = 0,1,2,3,4,5 */ +#define GPIO_PXPIN(n) (0x00 + (n) * 0x100) +#define GPIO_PXINT(n) (0x10 + (n) * 0x100) +#define GPIO_PXINTS(n) (0x14 + (n) * 0x100) +#define GPIO_PXINTC(n) (0x18 + (n) * 0x100) +#define GPIO_PXMASK(n) (0x20 + (n) * 0x100) +#define GPIO_PXMASKS(n) (0x24 + (n) * 0x100) +#define GPIO_PXMASKC(n) (0x28 + (n) * 0x100) +#define GPIO_PXPAT1(n) (0x30 + (n) * 0x100) +#define GPIO_PXPAT1S(n) (0x34 + (n) * 0x100) +#define GPIO_PXPAT1C(n) (0x38 + (n) * 0x100) +#define GPIO_PXPAT0(n) (0x40 + (n) * 0x100) +#define GPIO_PXPAT0S(n) (0x44 + (n) * 0x100) +#define GPIO_PXPAT0C(n) (0x48 + (n) * 0x100) +#define GPIO_PXFLG(n) (0x50 + (n) * 0x100) +#define GPIO_PXFLGC(n) (0x54 + (n) * 0x100) +#define GPIO_PXOEN(n) (0x60 + (n) * 0x100) +#define GPIO_PXOENS(n) (0x64 + (n) * 0x100) +#define GPIO_PXOENC(n) (0x68 + (n) * 0x100) +#define GPIO_PXPEN(n) (0x70 + (n) * 0x100) +#define GPIO_PXPENS(n) (0x74 + (n) * 0x100) +#define GPIO_PXPENC(n) (0x78 + (n) * 0x100) +#define GPIO_PXDS(n) (0x80 + (n) * 0x100) +#define GPIO_PXDSS(n) (0x84 + (n) * 0x100) +#define GPIO_PXDSC(n) (0x88 + (n) * 0x100) + +/* PLL setup */ +#define JZ4780_SYS_EXTAL 48000000 +#define JZ4780_SYS_MEM_SPEED (CONFIG_SYS_MHZ * 1000000) +#define JZ4780_SYS_MEM_DIV 3 +#define JZ4780_SYS_AUDIO_SPEED (768 * 1000000) + +#define JZ4780_APLL_M 1 +#define JZ4780_APLL_N 1 +#define JZ4780_APLL_OD 1 + +#define JZ4780_MPLL_M (JZ4780_SYS_MEM_SPEED / JZ4780_SYS_EXTAL * 2) +#define JZ4780_MPLL_N 2 +#define JZ4780_MPLL_OD 1 + +#define JZ4780_EPLL_M (JZ4780_SYS_AUDIO_SPEED * 2 / JZ4780_SYS_EXTAL) +#define JZ4780_EPLL_N 1 +#define JZ4780_EPLL_OD 2 + +#define JZ4780_VPLL_M ((888 * 1000000) * 2 / JZ4780_SYS_EXTAL) +#define JZ4780_VPLL_N 1 +#define JZ4780_VPLL_OD 2 + +#ifndef __ASSEMBLY__ + +u32 sdram_size(int bank); + +const u32 jz4780_clk_get_efuse_clk(void); +void jz4780_clk_ungate_ethernet(void); +void jz4780_clk_ungate_mmc(void); +void jz4780_clk_ungate_uart(const unsigned int uart); + +void jz4780_efuse_read(size_t addr, size_t count, u8 *buf); +void jz4780_efuse_init(u32 ahb2_rate); + +void jz4780_tcu_wdt_start(void); + +#ifdef CONFIG_SPL_BUILD +int jz_mmc_init(void __iomem *base); +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __JZ4780_H__ */ diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h b/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h new file mode 100644 index 000000000000..0bcc2157693e --- /dev/null +++ b/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h @@ -0,0 +1,457 @@ +/* + * JZ4780 DDR initialization - parameters definitions + * + * Copyright (c) 2015 Imagination Technologies + * Author: Matt Redfearn + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __JZ4780_DRAM_H__ +#define __JZ4780_DRAM_H__ + +/* + * DDR + */ +#define DDRC_ST 0x0 +#define DDRC_CFG 0x4 +#define DDRC_CTRL 0x8 +#define DDRC_LMR 0xc +#define DDRC_REFCNT 0x18 +#define DDRC_DQS 0x1c +#define DDRC_DQS_ADJ 0x20 +#define DDRC_MMAP0 0x24 +#define DDRC_MMAP1 0x28 +#define DDRC_MDELAY 0x2c +#define DDRC_CKEL 0x30 +#define DDRC_PMEMCTRL0 0x54 +#define DDRC_PMEMCTRL1 0x50 +#define DDRC_PMEMCTRL2 0x58 +#define DDRC_PMEMCTRL3 0x5c + +#define DDRC_TIMING(n) (0x60 + 4 * (n)) +#define DDRC_REMMAP(n) (0x9c + 4 * (n)) + +/* + * DDR PHY + */ +#define DDR_MEM_PHY_BASE 0x20000000 +#define DDR_PHY_OFFSET 0x1000 + +#define DDRP_PIR 0x4 +#define DDRP_PGCR 0x8 +#define DDRP_PGSR 0xc + +#define DDRP_PTR0 0x18 +#define DDRP_PTR1 0x1c +#define DDRP_PTR2 0x20 + +#define DDRP_ACIOCR 0x24 +#define DDRP_DXCCR 0x28 +#define DDRP_DSGCR 0x2c +#define DDRP_DCR 0x30 + +#define DDRP_DTPR0 0x34 +#define DDRP_DTPR1 0x38 +#define DDRP_DTPR2 0x3c +#define DDRP_MR0 0x40 +#define DDRP_MR1 0x44 +#define DDRP_MR2 0x48 +#define DDRP_MR3 0x4c + +#define DDRP_ODTCR 0x50 +#define DDRP_DTAR 0x54 +#define DDRP_DTDR0 0x58 +#define DDRP_DTDR1 0x5c + +#define DDRP_DCUAR 0xc0 +#define DDRP_DCUDR 0xc4 +#define DDRP_DCURR 0xc8 +#define DDRP_DCULR 0xcc +#define DDRP_DCUGCR 0xd0 +#define DDRP_DCUTPR 0xd4 +#define DDRP_DCUSR0 0xd8 +#define DDRP_DCUSR1 0xdc + +#define DDRP_ZQXCR0(n) (0x180 + ((n) * 0x10)) +#define DDRP_ZQXCR1(n) (0x184 + ((n) * 0x10)) +#define DDRP_ZQXSR0(n) (0x188 + ((n) * 0x10)) +#define DDRP_ZQXSR1(n) (0x18c + ((n) * 0x10)) + +#define DDRP_DXGCR(n) (0x1c0 + ((n) * 0x40)) +#define DDRP_DXGSR0(n) (0x1c4 + ((n) * 0x40)) +#define DDRP_DXGSR1(n) (0x1c8 + ((n) * 0x40)) +#define DDRP_DXDQSTR(n) (0x1d4 + ((n) * 0x40)) + +/* DDRC Status Register */ +#define DDRC_ST_ENDIAN BIT(7) +#define DDRC_ST_DPDN BIT(5) +#define DDRC_ST_PDN BIT(4) +#define DDRC_ST_AREF BIT(3) +#define DDRC_ST_SREF BIT(2) +#define DDRC_ST_CKE1 BIT(1) +#define DDRC_ST_CKE0 BIT(0) + +/* DDRC Configure Register */ +#define DDRC_CFG_ROW1_BIT 27 +#define DDRC_CFG_ROW1_MASK (0x7 << DDRC_CFG_ROW1_BIT) +#define DDRC_CFG_COL1_BIT 24 +#define DDRC_CFG_COL1_MASK (0x7 << DDRC_CFG_COL1_BIT) +#define DDRC_CFG_BA1 BIT(23) +#define DDRC_CFG_IMBA BIT(22) +#define DDRC_CFG_BL_8 BIT(21) + +#define DDRC_CFG_TYPE_BIT 17 +#define DDRC_CFG_TYPE_MASK (0x7 << DDRC_CFG_TYPE_BIT) +#define DDRC_CFG_TYPE_DDR1 (2 << DDRC_CFG_TYPE_BIT) +#define DDRC_CFG_TYPE_MDDR (3 << DDRC_CFG_TYPE_BIT) +#define DDRC_CFG_TYPE_DDR2 (4 << DDRC_CFG_TYPE_BIT) +#define DDRC_CFG_TYPE_LPDDR2 (5 << DDRC_CFG_TYPE_BIT) +#define DDRC_CFG_TYPE_DDR3 (6 << DDRC_CFG_TYPE_BIT) + +#define DDRC_CFG_ODT_EN BIT(16) + +#define DDRC_CFG_MPRT BIT(15) + +#define DDRC_CFG_ROW_BIT 11 +#define DDRC_CFG_ROW_MASK (0x7 << DDRC_CFG_ROW_BIT) +#define DDRC_CFG_ROW_12 (0 << DDRC_CFG_ROW_BIT) +#define DDRC_CFG_ROW_13 (1 << DDRC_CFG_ROW_BIT) +#define DDRC_CFG_ROW_14 (2 << DDRC_CFG_ROW_BIT) + +#define DDRC_CFG_COL_BIT 8 +#define DDRC_CFG_COL_MASK (0x7 << DDRC_CFG_COL_BIT) +#define DDRC_CFG_COL_8 (0 << DDRC_CFG_COL_BIT) +#define DDRC_CFG_COL_9 (1 << DDRC_CFG_COL_BIT) +#define DDRC_CFG_COL_10 (2 << DDRC_CFG_COL_BIT) +#define DDRC_CFG_COL_11 (3 << DDRC_CFG_COL_BIT) + +#define DDRC_CFG_CS1EN BIT(7) +#define DDRC_CFG_CS0EN BIT(6) +#define DDRC_CFG_CL_BIT 2 +#define DDRC_CFG_CL_MASK (0xf << DDRC_CFG_CL_BIT) +#define DDRC_CFG_CL_3 (0 << DDRC_CFG_CL_BIT) +#define DDRC_CFG_CL_4 (1 << DDRC_CFG_CL_BIT) +#define DDRC_CFG_CL_5 (2 << DDRC_CFG_CL_BIT) +#define DDRC_CFG_CL_6 (3 << DDRC_CFG_CL_BIT) + +#define DDRC_CFG_BA BIT(1) +#define DDRC_CFG_DW BIT(0) + +/* DDRC Control Register */ +#define DDRC_CTRL_DFI_RST BIT(23) +#define DDRC_CTRL_DLL_RST BIT(22) +#define DDRC_CTRL_CTL_RST BIT(21) +#define DDRC_CTRL_CFG_RST BIT(20) +#define DDRC_CTRL_ACTPD BIT(15) +#define DDRC_CTRL_PDT_BIT 12 +#define DDRC_CTRL_PDT_MASK (0x7 << DDRC_CTRL_PDT_BIT) +#define DDRC_CTRL_PDT_DIS (0 << DDRC_CTRL_PDT_BIT) +#define DDRC_CTRL_PDT_8 (1 << DDRC_CTRL_PDT_BIT) +#define DDRC_CTRL_PDT_16 (2 << DDRC_CTRL_PDT_BIT) +#define DDRC_CTRL_PDT_32 (3 << DDRC_CTRL_PDT_BIT) +#define DDRC_CTRL_PDT_64 (4 << DDRC_CTRL_PDT_BIT) +#define DDRC_CTRL_PDT_128 (5 << DDRC_CTRL_PDT_BIT) + +#define DDRC_CTRL_PRET_BIT 8 +#define DDRC_CTRL_PRET_MASK (0x7 << DDRC_CTRL_PRET_BIT) +#define DDRC_CTRL_PRET_DIS (0 << DDRC_CTRL_PRET_BIT) +#define DDRC_CTRL_PRET_8 (1 << DDRC_CTRL_PRET_BIT) +#define DDRC_CTRL_PRET_16 (2 << DDRC_CTRL_PRET_BIT) +#define DDRC_CTRL_PRET_32 (3 << DDRC_CTRL_PRET_BIT) +#define DDRC_CTRL_PRET_64 (4 << DDRC_CTRL_PRET_BIT) +#define DDRC_CTRL_PRET_128 (5 << DDRC_CTRL_PRET_BIT) + +#define DDRC_CTRL_DPD BIT(6) +#define DDRC_CTRL_SR BIT(5) +#define DDRC_CTRL_UNALIGN BIT(4) +#define DDRC_CTRL_ALH BIT(3) +#define DDRC_CTRL_RDC BIT(2) +#define DDRC_CTRL_CKE BIT(1) +#define DDRC_CTRL_RESET BIT(0) + +/* DDRC Load-Mode-Register */ +#define DDRC_LMR_DDR_ADDR_BIT 16 +#define DDRC_LMR_DDR_ADDR_MASK (0x3fff << DDRC_LMR_DDR_ADDR_BIT) + +#define DDRC_LMR_BA_BIT 8 +#define DDRC_LMR_BA_MASK (0x7 << DDRC_LMR_BA_BIT) +/* For DDR2 */ +#define DDRC_LMR_BA_MRS (0 << DDRC_LMR_BA_BIT) +#define DDRC_LMR_BA_EMRS1 (1 << DDRC_LMR_BA_BIT) +#define DDRC_LMR_BA_EMRS2 (2 << DDRC_LMR_BA_BIT) +#define DDRC_LMR_BA_EMRS3 (3 << DDRC_LMR_BA_BIT) +/* For mobile DDR */ +#define DDRC_LMR_BA_M_MRS (0 << DDRC_LMR_BA_BIT) +#define DDRC_LMR_BA_M_EMRS (2 << DDRC_LMR_BA_BIT) +#define DDRC_LMR_BA_M_SR (1 << DDRC_LMR_BA_BIT) +/* For Normal DDR1 */ +#define DDRC_LMR_BA_N_MRS (0 << DDRC_LMR_BA_BIT) +#define DDRC_LMR_BA_N_EMRS (1 << DDRC_LMR_BA_BIT) + +#define DDRC_LMR_CMD_BIT 4 +#define DDRC_LMR_CMD_MASK (0x3 << DDRC_LMR_CMD_BIT) +#define DDRC_LMR_CMD_PREC (0 << DDRC_LMR_CMD_BIT) +#define DDRC_LMR_CMD_AUREF (1 << DDRC_LMR_CMD_BIT) +#define DDRC_LMR_CMD_LMR (2 << DDRC_LMR_CMD_BIT) + +#define DDRC_LMR_START BIT(0) + +/* DDRC Timing Config Register 1 */ +#define DDRC_TIMING1_TRTP_BIT 24 +#define DDRC_TIMING1_TRTP_MASK (0x3f << DDRC_TIMING1_TRTP_BIT) +#define DDRC_TIMING1_TWTR_BIT 16 +#define DDRC_TIMING1_TWTR_MASK (0x3f << DDRC_TIMING1_TWTR_BIT) +#define DDRC_TIMING1_TWTR_1 (0 << DDRC_TIMING1_TWTR_BIT) +#define DDRC_TIMING1_TWTR_2 (1 << DDRC_TIMING1_TWTR_BIT) +#define DDRC_TIMING1_TWTR_3 (2 << DDRC_TIMING1_TWTR_BIT) +#define DDRC_TIMING1_TWTR_4 (3 << DDRC_TIMING1_TWTR_BIT) +#define DDRC_TIMING1_TWR_BIT 8 +#define DDRC_TIMING1_TWR_MASK (0x3f << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWR_1 (0 << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWR_2 (1 << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWR_3 (2 << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWR_4 (3 << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWR_5 (4 << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWR_6 (5 << DDRC_TIMING1_TWR_BIT) +#define DDRC_TIMING1_TWL_BIT 0 +#define DDRC_TIMING1_TWL_MASK (0x3f << DDRC_TIMING1_TWL_BIT) + +/* DDRC Timing Config Register 2 */ +#define DDRC_TIMING2_TCCD_BIT 24 +#define DDRC_TIMING2_TCCD_MASK (0x3f << DDRC_TIMING2_TCCD_BIT) +#define DDRC_TIMING2_TRAS_BIT 16 +#define DDRC_TIMING2_TRAS_MASK (0x3f << DDRC_TIMING2_TRAS_BIT) +#define DDRC_TIMING2_TRCD_BIT 8 +#define DDRC_TIMING2_TRCD_MASK (0x3f << DDRC_TIMING2_TRCD_BIT) +#define DDRC_TIMING2_TRL_BIT 0 +#define DDRC_TIMING2_TRL_MASK (0x3f << DDRC_TIMING2_TRL_BIT) + +/* DDRC Timing Config Register 3 */ +#define DDRC_TIMING3_ONUM 27 +#define DDRC_TIMING3_TCKSRE_BIT 24 +#define DDRC_TIMING3_TCKSRE_MASK (0x3f << DDRC_TIMING3_TCKSRE_BIT) +#define DDRC_TIMING3_TRP_BIT 16 +#define DDRC_TIMING3_TRP_MASK (0x3f << DDRC_TIMING3_TRP_BIT) +#define DDRC_TIMING3_TRRD_BIT 8 +#define DDRC_TIMING3_TRRD_MASK (0x3f << DDRC_TIMING3_TRRD_BIT) +#define DDRC_TIMING3_TRRD_DISABLE (0 << DDRC_TIMING3_TRRD_BIT) +#define DDRC_TIMING3_TRRD_2 (1 << DDRC_TIMING3_TRRD_BIT) +#define DDRC_TIMING3_TRRD_3 (2 << DDRC_TIMING3_TRRD_BIT) +#define DDRC_TIMING3_TRRD_4 (3 << DDRC_TIMING3_TRRD_BIT) +#define DDRC_TIMING3_TRC_BIT 0 +#define DDRC_TIMING3_TRC_MASK (0x3f << DDRC_TIMING3_TRC_BIT) + +/* DDRC Timing Config Register 4 */ +#define DDRC_TIMING4_TRFC_BIT 24 +#define DDRC_TIMING4_TRFC_MASK (0x3f << DDRC_TIMING4_TRFC_BIT) +#define DDRC_TIMING4_TEXTRW_BIT 21 +#define DDRC_TIMING4_TEXTRW_MASK (0x7 << DDRC_TIMING4_TEXTRW_BIT) +#define DDRC_TIMING4_TRWCOV_BIT 19 +#define DDRC_TIMING4_TRWCOV_MASK (0x3 << DDRC_TIMING4_TRWCOV_BIT) +#define DDRC_TIMING4_TCKE_BIT 16 +#define DDRC_TIMING4_TCKE_MASK (0x7 << DDRC_TIMING4_TCKE_BIT) +#define DDRC_TIMING4_TMINSR_BIT 8 +#define DDRC_TIMING4_TMINSR_MASK (0xf << DDRC_TIMING4_TMINSR_BIT) +#define DDRC_TIMING4_TXP_BIT 4 +#define DDRC_TIMING4_TXP_MASK (0x7 << DDRC_TIMING4_TXP_BIT) +#define DDRC_TIMING4_TMRD_BIT 0 +#define DDRC_TIMING4_TMRD_MASK (0x3 << DDRC_TIMING4_TMRD_BIT) + +/* DDRC Timing Config Register 5 */ +#define DDRC_TIMING5_TCTLUPD_BIT 24 +#define DDRC_TIMING4_TCTLUPD_MASK (0x3f << DDRC_TIMING5_TCTLUDP_BIT) +#define DDRC_TIMING5_TRTW_BIT 16 +#define DDRC_TIMING5_TRTW_MASK (0x3f << DDRC_TIMING5_TRTW_BIT) +#define DDRC_TIMING5_TRDLAT_BIT 8 +#define DDRC_TIMING5_TRDLAT_MASK (0x3f << DDRC_TIMING5_TRDLAT_BIT) +#define DDRC_TIMING5_TWDLAT_BIT 0 +#define DDRC_TIMING5_TWDLAT_MASK (0x3f << DDRC_TIMING5_TWDLAT_BIT) + +/* DDRC Timing Config Register 6 */ +#define DDRC_TIMING6_TXSRD_BIT 24 +#define DDRC_TIMING6_TXSRD_MASK (0x3f << DDRC_TIMING6_TXSRD_BIT) +#define DDRC_TIMING6_TFAW_BIT 16 +#define DDRC_TIMING6_TFAW_MASK (0x3f << DDRC_TIMING6_TFAW_BIT) +#define DDRC_TIMING6_TCFGW_BIT 8 +#define DDRC_TIMING6_TCFGW_MASK (0x3f << DDRC_TIMING6_TCFGW_BIT) +#define DDRC_TIMING6_TCFGR_BIT 0 +#define DDRC_TIMING6_TCFGR_MASK (0x3f << DDRC_TIMING6_TCFGR_BIT) + +/* DDRC Auto-Refresh Counter */ +#define DDRC_REFCNT_CON_BIT 16 +#define DDRC_REFCNT_CON_MASK (0xff << DDRC_REFCNT_CON_BIT) +#define DDRC_REFCNT_CNT_BIT 8 +#define DDRC_REFCNT_CNT_MASK (0xff << DDRC_REFCNT_CNT_BIT) +#define DDRC_REFCNT_CLKDIV_BIT 1 +#define DDRC_REFCNT_CLKDIV_MASK (0x7 << DDRC_REFCNT_CLKDIV_BIT) +#define DDRC_REFCNT_REF_EN BIT(0) + +/* DDRC DQS Delay Control Register */ +#define DDRC_DQS_ERROR BIT(29) +#define DDRC_DQS_READY BIT(28) +#define DDRC_DQS_AUTO BIT(23) +#define DDRC_DQS_DET BIT(24) +#define DDRC_DQS_SRDET BIT(25) +#define DDRC_DQS_CLKD_BIT 16 +#define DDRC_DQS_CLKD_MASK (0x3f << DDRC_DQS_CLKD_BIT) +#define DDRC_DQS_WDQS_BIT 8 +#define DDRC_DQS_WDQS_MASK (0x3f << DDRC_DQS_WDQS_BIT) +#define DDRC_DQS_RDQS_BIT 0 +#define DDRC_DQS_RDQS_MASK (0x3f << DDRC_DQS_RDQS_BIT) + +/* DDRC DQS Delay Adjust Register */ +#define DDRC_DQS_ADJWDQS_BIT 8 +#define DDRC_DQS_ADJWDQS_MASK (0x1f << DDRC_DQS_ADJWDQS_BIT) +#define DDRC_DQS_ADJRDQS_BIT 0 +#define DDRC_DQS_ADJRDQS_MASK (0x1f << DDRC_DQS_ADJRDQS_BIT) + +/* DDRC Memory Map Config Register */ +#define DDRC_MMAP_BASE_BIT 8 +#define DDRC_MMAP_BASE_MASK (0xff << DDRC_MMAP_BASE_BIT) +#define DDRC_MMAP_MASK_BIT 0 +#define DDRC_MMAP_MASK_MASK (0xff << DDRC_MMAP_MASK_BIT) + +#define DDRC_MMAP0_BASE (0x20 << DDRC_MMAP_BASE_BIT) +#define DDRC_MMAP1_BASE_64M (0x24 << DDRC_MMAP_BASE_BIT) +#define DDRC_MMAP1_BASE_128M (0x28 << DDRC_MMAP_BASE_BIT) +#define DDRC_MMAP1_BASE_256M (0x30 << DDRC_MMAP_BASE_BIT) + +#define DDRC_MMAP_MASK_64_64 (0xfc << DDRC_MMAP_MASK_BIT) +#define DDRC_MMAP_MASK_128_128 (0xf8 << DDRC_MMAP_MASK_BIT) +#define DDRC_MMAP_MASK_256_256 (0xf0 << DDRC_MMAP_MASK_BIT) + +/* DDRP PHY Initialization Register */ +#define DDRP_PIR_INIT BIT(0) +#define DDRP_PIR_DLLSRST BIT(1) +#define DDRP_PIR_DLLLOCK BIT(2) +#define DDRP_PIR_ZCAL BIT(3) +#define DDRP_PIR_ITMSRST BIT(4) +#define DDRP_PIR_DRAMRST BIT(5) +#define DDRP_PIR_DRAMINT BIT(6) +#define DDRP_PIR_QSTRN BIT(7) +#define DDRP_PIR_EYETRN BIT(8) +#define DDRP_PIR_DLLBYP BIT(17) +/* DDRP PHY General Configurate Register */ +#define DDRP_PGCR_ITMDMD BIT(0) +#define DDRP_PGCR_DQSCFG BIT(1) +#define DDRP_PGCR_DFTCMP BIT(2) +#define DDRP_PGCR_DFTLMT_BIT 3 +#define DDRP_PGCR_DTOSEL_BIT 5 +#define DDRP_PGCR_CKEN_BIT 9 +#define DDRP_PGCR_CKDV_BIT 12 +#define DDRP_PGCR_CKINV BIT(14) +#define DDRP_PGCR_RANKEN_BIT 18 +#define DDRP_PGCR_ZCKSEL_32 (2 << 22) +#define DDRP_PGCR_PDDISDX BIT(24) +/* DDRP PHY General Status Register */ +#define DDRP_PGSR_IDONE BIT(0) +#define DDRP_PGSR_DLDONE BIT(1) +#define DDRP_PGSR_ZCDONE BIT(2) +#define DDRP_PGSR_DIDONE BIT(3) +#define DDRP_PGSR_DTDONE BIT(4) +#define DDRP_PGSR_DTERR BIT(5) +#define DDRP_PGSR_DTIERR BIT(6) +#define DDRP_PGSR_DFTEERR BIT(7) +/* DDRP DRAM Configuration Register */ +#define DDRP_DCR_TYPE_BIT 0 +#define DDRP_DCR_TYPE_MASK (0x7 << DDRP_DCR_TYPE_BIT) +#define DDRP_DCR_TYPE_MDDR (0 << DDRP_DCR_TYPE_BIT) +#define DDRP_DCR_TYPE_DDR (1 << DDRP_DCR_TYPE_BIT) +#define DDRP_DCR_TYPE_DDR2 (2 << DDRP_DCR_TYPE_BIT) +#define DDRP_DCR_TYPE_DDR3 (3 << DDRP_DCR_TYPE_BIT) +#define DDRP_DCR_TYPE_LPDDR2 (4 << DDRP_DCR_TYPE_BIT) +#define DDRP_DCR_DDR8BNK_BIT 3 +#define DDRP_DCR_DDR8BNK_MASK (1 << DDRP_DCR_DDR8BNK_BIT) +#define DDRP_DCR_DDR8BNK (1 << DDRP_DCR_DDR8BNK_BIT) +#define DDRP_DCR_DDR8BNK_DIS (0 << DDRP_DCR_DDR8BNK_BIT) + +#define DRP_DTRP1_RTODT BIT(11) + +#define DDRP_DXGCR_DXEN BIT(0) + +#define DDRP_ZQXCR_ZDEN_BIT 28 +#define DDRP_ZQXCR_ZDEN (1 << DDRP_ZQXCR_ZDEN_BIT) +#define DDRP_ZQXCR_PULLUP_IMPE_BIT 5 +#define DDRP_ZQXCR_PULLDOWN_IMPE_BIT 0 + +/* DDR3 Mode Register Set */ +#define DDR3_MR0_BL_BIT 0 +#define DDR3_MR0_BL_MASK (3 << DDR3_MR0_BL_BIT) +#define DDR3_MR0_BL_8 (0 << DDR3_MR0_BL_BIT) +#define DDR3_MR0_BL_fly (1 << DDR3_MR0_BL_BIT) +#define DDR3_MR0_BL_4 (2 << DDR3_MR0_BL_BIT) +#define DDR3_MR0_BT_BIT 3 +#define DDR3_MR0_BT_MASK (1 << DDR3_MR0_BT_BIT) +#define DDR3_MR0_BT_SEQ (0 << DDR3_MR0_BT_BIT) +#define DDR3_MR0_BT_INTER (1 << DDR3_MR0_BT_BIT) +#define DDR3_MR0_WR_BIT 9 + +#define DDR3_MR1_DLL_DISABLE 1 +#define DDR3_MR1_DIC_6 (0 << 5 | 0 << 1) +#define DDR3_MR1_DIC_7 (0 << 5 | BIT(1)) +#define DDR3_MR1_RTT_DIS (0 << 9 | 0 << 6 | 0 << 2) +#define DDR3_MR1_RTT_4 (0 << 9 | 0 << 6 | BIT(2)) +#define DDR3_MR1_RTT_2 (0 << 9 | BIT(6) | 0 << 2) +#define DDR3_MR1_RTT_6 (0 << 9 | BIT(6) | BIT(2)) +#define DDR3_MR1_RTT_12 (BIT(9) | 0 << 6 | 0 << 2) +#define DDR3_MR1_RTT_8 (BIT(9) | 0 << 6 | BIT(2)) + +#define DDR3_MR2_CWL_BIT 3 + +/* Paramters common to all RAM devices used */ + +/* Chip Select */ +/* CSEN : whether a ddr chip exists 0 - un-used, 1 - used */ +#define DDR_CS0EN 1 +/* CSEN : whether a ddr chip exists 0 - un-used, 1 - used */ +#define DDR_CS1EN 0 + +/* ROW : 12 to 18 row address, 1G only 512MB */ +#define DDR_ROW 15 +/* COL : 8 to 14 column address */ +#define DDR_COL 10 +/* Banks each chip: 0-4bank, 1-8bank */ +#define DDR_BANK8 1 +/* 0 - 16-bit data width, 1 - 32-bit data width */ +#define DDR_DW32 1 + +/* Refresh period: 64ms / 32768 = 1.95 us , 2 ^ 15 = 32768 */ +#define DDR_tREFI 7800 +/* Clock Divider */ +#define DDR_CLK_DIV 1 + +/* DDR3 Burst length: 0 - 8 burst, 2 - 4 burst , 1 - 4 or 8 (on the fly) */ +#define DDR_BL 8 + +/* CAS latency: 5 to 14, tCK */ +#define DDR_CL 6 +/* DDR3 only: CAS Write Latency, 5 to 8 */ +#define DDR_tCWL (DDR_CL - 1) + +/* Structure representing per-RAM type configuration */ + +struct jz4780_ddr_config { + u32 timing[6]; /* Timing1..6 register value */ + + /* DDR PHY control */ + u16 mr0; /* Mode Register 0 */ + u16 mr1; /* Mode Register 1 */ + + u32 ptr0; /* PHY Timing Register 0 */ + u32 ptr1; /* PHY Timing Register 1 */ + u32 ptr2; /* PHY Timing Register 1 */ + + u32 dtpr0; /* DRAM Timing Parameters Register 0 */ + u32 dtpr1; /* DRAM Timing Parameters Register 1 */ + u32 dtpr2; /* DRAM Timing Parameters Register 2 */ + + u8 pullup; /* PHY pullup impedance */ + u8 pulldn; /* PHY pulldown impedance */ +}; + +void pll_init(void); +void sdram_init(void); + +#endif /* __JZ4780_DRAM_H__ */ + diff --git a/arch/mips/mach-jz47xx/jz4780/Makefile b/arch/mips/mach-jz47xx/jz4780/Makefile new file mode 100644 index 000000000000..683eea65c2f1 --- /dev/null +++ b/arch/mips/mach-jz47xx/jz4780/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := jz4780.o pll.o sdram.o timer.o diff --git a/arch/mips/mach-jz47xx/jz4780/jz4780.c b/arch/mips/mach-jz47xx/jz4780/jz4780.c new file mode 100644 index 000000000000..bbc4eaa53bbb --- /dev/null +++ b/arch/mips/mach-jz47xx/jz4780/jz4780.c @@ -0,0 +1,142 @@ +/* + * JZ4780 common routines + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SPL_BUILD +/* Pointer to the global data structure for SPL */ +DECLARE_GLOBAL_DATA_PTR; +gd_t gdata __attribute__ ((section(".bss"))); + +void board_init_f(ulong dummy) +{ + typedef void __noreturn (*image_entry_noargs_t)(void); + struct mmc *mmc; + unsigned long count; + struct image_header *header; + int ret; + + /* Set global data pointer */ + gd = &gdata; + + timer_init(); + pll_init(); + sdram_init(); + enable_caches(); + + /* Clear the BSS */ + memset(__bss_start, 0, (char *)&__bss_end - __bss_start); + + gd->flags |= GD_FLG_SPL_INIT; + + ret = mmc_initialize(NULL); + if (ret) + hang(); + + mmc = find_mmc_device(BOOT_DEVICE_MMC1); + if (ret) + hang(); + + ret = mmc_init(mmc); + if (ret) + hang(); + + header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - + sizeof(struct image_header)); + + count = blk_dread(mmc_get_blk_desc(mmc), + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, + 0x800, header); + if (count == 0) + hang(); + + image_entry_noargs_t image_entry = + (image_entry_noargs_t)CONFIG_SYS_TEXT_BASE; + + image_entry(); + + hang(); +} +#endif /* CONFIG_SPL_BUILD */ + +ulong board_get_usable_ram_top(ulong total_size) +{ + return CONFIG_SYS_SDRAM_BASE + (256 * 1024 * 1024); +} + +int print_cpuinfo(void) +{ + printf("CPU: Ingenic JZ4780\n"); + return 0; +} + +/* WDT */ +#define WDT_TDR 0x00 +#define WDT_TCER 0x04 +#define WDT_TCNT 0x08 +#define WDT_TCSR 0x0C + +/* Register definition */ +#define WDT_TCSR_PRESCALE_BIT 3 +#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT) + #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT) +#define WDT_TCSR_EXT_EN BIT(2) +#define WDT_TCSR_RTC_EN BIT(1) +#define WDT_TCSR_PCK_EN BIT(0) + +#define WDT_TCER_TCEN BIT(0) + +void _machine_restart(void) +{ + void __iomem *wdt_regs = (void __iomem *)WDT_BASE; + + mdelay(100); + + /* + * Select the EXTAL as the timer clock input, and make each + * WDT clock tick equal 4 ticks of the system clock. + */ + writew(WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN, wdt_regs + WDT_TCSR); + + /* Reset the WDT counter to zero. */ + writew(0, wdt_regs + WDT_TCNT); + + /* + * Reset after 4ms + * + * 1 sec CONFIG_SYS_EXTAL ticks + * 4ms * ------- * ---------------------- = Number of WDT clock ticks + * 1000 ms 1 sec + * + * As noted above the number of system clock ticks have been + * effectively multiplied by 4. All that's left here for the + * computation of WDT clock ticks is to divide by 1000 + * (one thousand). + */ + writew(JZ4780_SYS_EXTAL / 1000, wdt_regs + WDT_TDR); + + jz4780_tcu_wdt_start(); + + /* WDT start */ + writeb(WDT_TCER_TCEN, wdt_regs + WDT_TCER); + + for (;;) + ; +} diff --git a/arch/mips/mach-jz47xx/jz4780/pll.c b/arch/mips/mach-jz47xx/jz4780/pll.c new file mode 100644 index 000000000000..52071f8538cb --- /dev/null +++ b/arch/mips/mach-jz47xx/jz4780/pll.c @@ -0,0 +1,528 @@ +/* + * JZ4780 PLL setup + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#define CPM_CPCCR 0x00 +#define CPM_LCR 0x04 +#define CPM_RSR 0x08 +#define CPM_CPPCR 0x0c +#define CPM_CPAPCR 0x10 +#define CPM_CPMPCR 0x14 +#define CPM_CPEPCR 0x18 +#define CPM_CPVPCR 0x1c +#define CPM_CLKGR0 0x20 +#define CPM_OPCR 0x24 +#define CPM_CLKGR1 0x28 +#define CPM_DDCDR 0x2c +#define CPM_VPUCDR 0x30 +#define CPM_CPSPR 0x34 +#define CPM_CPSPPR 0x38 +#define CPM_USBPCR 0x3c +#define CPM_USBRDT 0x40 +#define CPM_USBVBFIL 0x44 +#define CPM_USBPCR1 0x48 +#define CPM_USBCDR 0x50 +#define CPM_LPCDR 0x54 +#define CPM_I2SCDR 0x60 +#define CPM_LPCDR1 0x64 +#define CPM_MSCCDR 0x68 +#define CPM_UHCCDR 0x6c +#define CPM_SSICDR 0x74 +#define CPM_CIMCDR 0x7c +#define CPM_PCMCDR 0x84 +#define CPM_GPUCDR 0x88 +#define CPM_HDMICDR 0x8c +#define CPM_I2S1CDR 0xa0 +#define CPM_MSCCDR1 0xa4 +#define CPM_MSCCDR2 0xa8 +#define CPM_BCHCDR 0xac +#define CPM_SPCR0 0xb8 +#define CPM_SPCR1 0xbc +#define CPM_CPCSR 0xd4 +#define CPM_PSWCST(n) ((0x4 * (n)) + 0x90) + +/* Clock control register */ +#define CPM_CPCCR_SEL_SRC_BIT 30 +#define CPM_CPCCR_SEL_SRC_MASK (0x3 << CPM_CPCCR_SEL_SRC_BIT) +#define CPM_SRC_SEL_STOP 0 +#define CPM_SRC_SEL_APLL 1 +#define CPM_SRC_SEL_EXCLK 2 +#define CPM_SRC_SEL_RTCLK 3 +#define CPM_CPCCR_SEL_CPLL_BIT 28 +#define CPM_CPCCR_SEL_CPLL_MASK (0x3 << CPM_CPCCR_SEL_CPLL_BIT) +#define CPM_CPCCR_SEL_H0PLL_BIT 26 +#define CPM_CPCCR_SEL_H0PLL_MASK (0x3 << CPM_CPCCR_SEL_H0PLL_BIT) +#define CPM_CPCCR_SEL_H2PLL_BIT 24 +#define CPM_CPCCR_SEL_H2PLL_MASK (0x3 << CPM_CPCCR_SEL_H2PLL_BIT) +#define CPM_PLL_SEL_STOP 0 +#define CPM_PLL_SEL_SRC 1 +#define CPM_PLL_SEL_MPLL 2 +#define CPM_PLL_SEL_EPLL 3 +#define CPM_CPCCR_CE_CPU (0x1 << 22) +#define CPM_CPCCR_CE_AHB0 (0x1 << 21) +#define CPM_CPCCR_CE_AHB2 (0x1 << 20) +#define CPM_CPCCR_PDIV_BIT 16 +#define CPM_CPCCR_PDIV_MASK (0xf << CPM_CPCCR_PDIV_BIT) +#define CPM_CPCCR_H2DIV_BIT 12 +#define CPM_CPCCR_H2DIV_MASK (0xf << CPM_CPCCR_H2DIV_BIT) +#define CPM_CPCCR_H0DIV_BIT 8 +#define CPM_CPCCR_H0DIV_MASK (0x0f << CPM_CPCCR_H0DIV_BIT) +#define CPM_CPCCR_L2DIV_BIT 4 +#define CPM_CPCCR_L2DIV_MASK (0x0f << CPM_CPCCR_L2DIV_BIT) +#define CPM_CPCCR_CDIV_BIT 0 +#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT) + +/* Clock Status register */ +#define CPM_CPCSR_H2DIV_BUSY BIT(2) +#define CPM_CPCSR_H0DIV_BUSY BIT(1) +#define CPM_CPCSR_CDIV_BUSY BIT(0) + +/* PLL control register */ +#define CPM_CPPCR_PLLST_BIT 0 +#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT) + +/* XPLL control register */ +#define CPM_CPXPCR_XPLLM_BIT 19 +#define CPM_CPXPCR_XPLLM_MASK (0x1fff << CPM_CPXPCR_XPLLM_BIT) +#define CPM_CPXPCR_XPLLN_BIT 13 +#define CPM_CPXPCR_XPLLN_MASK (0x3f << CPM_CPXPCR_XPLLN_BIT) +#define CPM_CPXPCR_XPLLOD_BIT 9 +#define CPM_CPXPCR_XPLLOD_MASK (0xf << CPM_CPXPCR_XPLLOD_BIT) +#define CPM_CPXPCR_XLOCK BIT(6) +#define CPM_CPXPCR_XPLL_ON BIT(4) +#define CPM_CPXPCR_XF_MODE BIT(3) +#define CPM_CPXPCR_XPLLBP BIT(1) +#define CPM_CPXPCR_XPLLEN BIT(0) + +/* CPM scratch protected register */ +#define CPM_CPSPPR_BIT 0 +#define CPM_CPSPPR_MASK (0xffff << CPM_CPSPPR_BIT) + +/* USB parameter control register */ +#define CPM_USBPCR_USB_MODE BIT(31) /* 1: OTG, 0: UDC*/ +#define CPM_USBPCR_AVLD_REG BIT(30) +#define CPM_USBPCR_IDPULLUP_MASK_BIT 28 +#define CPM_USBPCR_IDPULLUP_MASK_MASK (0x02 << IDPULLUP_MASK_BIT) +#define CPM_USBPCR_INCR_MASK BIT(27) +#define CPM_USBPCR_CLK12_EN BIT(26) +#define CPM_USBPCR_COMMONONN BIT(25) +#define CPM_USBPCR_VBUSVLDEXT BIT(24) +#define CPM_USBPCR_VBUSVLDEXTSEL BIT(23) +#define CPM_USBPCR_POR BIT(22) +#define CPM_USBPCR_SIDDQ BIT(21) +#define CPM_USBPCR_OTG_DISABLE BIT(20) +#define CPM_USBPCR_COMPDISTUNE_BIT 17 +#define CPM_USBPCR_COMPDISTUNE_MASK (0x07 << COMPDISTUNE_BIT) +#define CPM_USBPCR_OTGTUNE_BIT 14 +#define CPM_USBPCR_OTGTUNE_MASK (0x07 << OTGTUNE_BIT) +#define CPM_USBPCR_SQRXTUNE_BIT 11 +#define CPM_USBPCR_SQRXTUNE_MASK (0x7x << SQRXTUNE_BIT) +#define CPM_USBPCR_TXFSLSTUNE_BIT 7 +#define CPM_USBPCR_TXFSLSTUNE_MASK (0x0f << TXFSLSTUNE_BIT) +#define CPM_USBPCR_TXPREEMPHTUNE BIT(6) +#define CPM_USBPCR_TXRISETUNE_BIT 4 +#define CPM_USBPCR_TXRISETUNE_MASK (0x03 << TXRISETUNE_BIT) +#define CPM_USBPCR_TXVREFTUNE_BIT 0 +#define CPM_USBPCR_TXVREFTUNE_MASK (0x0f << TXVREFTUNE_BIT) + +/* DDR memory clock divider register */ +#define CPM_DDRCDR_DCS_BIT 30 +#define CPM_DDRCDR_DCS_MASK (0x3 << CPM_DDRCDR_DCS_BIT) +#define CPM_DDRCDR_DCS_STOP (0x0 << CPM_DDRCDR_DCS_BIT) +#define CPM_DDRCDR_DCS_SRC (0x1 << CPM_DDRCDR_DCS_BIT) +#define CPM_DDRCDR_DCS_MPLL (0x2 << CPM_DDRCDR_DCS_BIT) +#define CPM_DDRCDR_CE_DDR BIT(29) +#define CPM_DDRCDR_DDR_BUSY BIT(28) +#define CPM_DDRCDR_DDR_STOP BIT(27) +#define CPM_DDRCDR_DDRDIV_BIT 0 +#define CPM_DDRCDR_DDRDIV_MASK (0xf << CPM_DDRCDR_DDRDIV_BIT) + +/* USB reset detect timer register */ +#define CPM_USBRDT_VBFIL_LD_EN BIT(25) +#define CPM_USBRDT_IDDIG_EN BIT(24) +#define CPM_USBRDT_IDDIG_REG BIT(23) +#define CPM_USBRDT_USBRDT_BIT 0 +#define CPM_USBRDT_USBRDT_MASK (0x7fffff << CPM_USBRDT_USBRDT_BIT) + +/* USB OTG PHY clock divider register */ +#define CPM_USBCDR_UCS BIT(31) +#define CPM_USBCDR_UPCS BIT(30) +#define CPM_USBCDR_CEUSB BIT(29) +#define CPM_USBCDR_USB_BUSY BIT(28) +#define CPM_USBCDR_OTGDIV_BIT 0 +#define CPM_USBCDR_OTGDIV_MASK (0xff << CPM_USBCDR_OTGDIV_BIT) + +/* I2S device clock divider register */ +#define CPM_I2SCDR_I2CS BIT(31) +#define CPM_I2SCDR_I2PCS BIT(30) +#define CPM_I2SCDR_I2SDIV_BIT 0 +#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT) + +/* LCD0 pix clock divider register */ +#define CPM_LPCDR_LPCS_BIT 30 +#define CPM_LPCDR_LPCS_MASK (0x3 << CPM_LPCDR_LPCS_BIT) +#define CPM_LPCDR_CELCD BIT(28) +#define CPM_LPCDR_LCD_BUSY BIT(27) +#define CPM_LPCDR_LCD_STOP BIT(26) +#define CPM_LPCDR_PIXDIV_BIT 0 +#define CPM_LPCDR_PIXDIV_MASK (0xff << CPM_LPCDR_PIXDIV_BIT) + +/* MSC clock divider register */ +#define CPM_MSCCDR_MPCS_BIT 30 +#define CPM_MSCCDR_MPCS_MASK (3 << CPM_MSCCDR_MPCS_BIT) +#define CPM_MSCCDR_MPCS_STOP (0x0 << CPM_MSCCDR_MPCS_BIT) +#define CPM_MSCCDR_MPCS_SRC (0x1 << CPM_MSCCDR_MPCS_BIT) +#define CPM_MSCCDR_MPCS_MPLL (0x2 << CPM_MSCCDR_MPCS_BIT) +#define CPM_MSCCDR_CE BIT(29) +#define CPM_MSCCDR_MSC_BUSY BIT(28) +#define CPM_MSCCDR_MSC_STOP BIT(27) +#define CPM_MSCCDR_MSC_CLK0_SEL BIT(15) +#define CPM_MSCCDR_MSCDIV_BIT 0 +#define CPM_MSCCDR_MSCDIV_MASK (0xff << CPM_MSCCDR_MSCDIV_BIT) + +/* UHC 48M clock divider register */ +#define CPM_UHCCDR_UHCS_BIT 30 +#define CPM_UHCCDR_UHCS_MASK (0x3 << CPM_UHCCDR_UHCS_BIT) +#define CPM_UHCCDR_UHCS_SRC (0x0 << CPM_UHCCDR_UHCS_BIT) +#define CPM_UHCCDR_UHCS_MPLL (0x1 << CPM_UHCCDR_UHCS_BIT) +#define CPM_UHCCDR_UHCS_EPLL (0x2 << CPM_UHCCDR_UHCS_BIT) +#define CPM_UHCCDR_UHCS_OTG (0x3 << CPM_UHCCDR_UHCS_BIT) +#define CPM_UHCCDR_CE_UHC BIT(29) +#define CPM_UHCCDR_UHC_BUSY BIT(28) +#define CPM_UHCCDR_UHC_STOP BIT(27) +#define CPM_UHCCDR_UHCDIV_BIT 0 +#define CPM_UHCCDR_UHCDIV_MASK (0xff << CPM_UHCCDR_UHCDIV_BIT) + +/* SSI clock divider register */ +#define CPM_SSICDR_SCS BIT(31) +#define CPM_SSICDR_SSIDIV_BIT 0 +#define CPM_SSICDR_SSIDIV_MASK (0x3f << CPM_SSICDR_SSIDIV_BIT) + +/* CIM MCLK clock divider register */ +#define CPM_CIMCDR_CIMDIV_BIT 0 +#define CPM_CIMCDR_CIMDIV_MASK (0xff << CPM_CIMCDR_CIMDIV_BIT) + +/* GPS clock divider register */ +#define CPM_GPSCDR_GPCS BIT(31) +#define CPM_GPSCDR_GPSDIV_BIT 0 +#define CPM_GSPCDR_GPSDIV_MASK (0xf << CPM_GPSCDR_GPSDIV_BIT) + +/* PCM device clock divider register */ +#define CPM_PCMCDR_PCMS BIT(31) +#define CPM_PCMCDR_PCMPCS BIT(30) +#define CPM_PCMCDR_PCMDIV_BIT 0 +#define CPM_PCMCDR_PCMDIV_MASK (0x1ff << CPM_PCMCDR_PCMDIV_BIT) + +/* GPU clock divider register */ +#define CPM_GPUCDR_GPCS BIT(31) +#define CPM_GPUCDR_GPUDIV_BIT 0 +#define CPM_GPUCDR_GPUDIV_MASK (0x7 << CPM_GPUCDR_GPUDIV_BIT) + +/* HDMI clock divider register */ +#define CPM_HDMICDR_HPCS_BIT 30 +#define CPM_HDMICDR_HPCS_MASK (0x3 << CPM_HDMICDR_HPCS_BIT) +#define CPM_HDMICDR_CEHDMI BIT(29) +#define CPM_HDMICDR_HDMI_BUSY BIT(28) +#define CPM_HDMICDR_HDMI_STOP BIT(26) +#define CPM_HDMICDR_HDMIDIV_BIT 0 +#define CPM_HDMICDR_HDMIDIV_MASK (0xff << CPM_HDMICDR_HDMIDIV_BIT) + +/* Low Power Control Register */ +#define CPM_LCR_PD_SCPU BIT(31) +#define CPM_LCR_PD_VPU BIT(30) +#define CPM_LCR_PD_GPU BIT(29) +#define CPM_LCR_PD_GPS BIT(28) +#define CPM_LCR_SCPUS BIT(27) +#define CPM_LCR_VPUS BIT(26) +#define CPM_LCR_GPUS BIT(25) +#define CPM_LCR_GPSS BIT(24) +#define CPM_LCR_GPU_IDLE BIT(20) +#define CPM_LCR_PST_BIT 8 +#define CPM_LCR_PST_MASK (0xfff << CPM_LCR_PST_BIT) +#define CPM_LCR_DOZE_DUTY_BIT 3 +#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT) +#define CPM_LCR_DOZE_ON BIT(2) +#define CPM_LCR_LPM_BIT 0 +#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT) +#define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT) +#define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT) + +/* Clock Gate Register0 */ +#define CPM_CLKGR0_DDR1 BIT(31) +#define CPM_CLKGR0_DDR0 BIT(30) +#define CPM_CLKGR0_IPU BIT(29) +#define CPM_CLKGR0_LCD1 BIT(28) +#define CPM_CLKGR0_LCD BIT(27) +#define CPM_CLKGR0_CIM BIT(26) +#define CPM_CLKGR0_I2C2 BIT(25) +#define CPM_CLKGR0_UHC BIT(24) +#define CPM_CLKGR0_MAC BIT(23) +#define CPM_CLKGR0_GPS BIT(22) +#define CPM_CLKGR0_PDMAC BIT(21) +#define CPM_CLKGR0_SSI2 BIT(20) +#define CPM_CLKGR0_SSI1 BIT(19) +#define CPM_CLKGR0_UART3 BIT(18) +#define CPM_CLKGR0_UART2 BIT(17) +#define CPM_CLKGR0_UART1 BIT(16) +#define CPM_CLKGR0_UART0 BIT(15) +#define CPM_CLKGR0_SADC BIT(14) +#define CPM_CLKGR0_KBC BIT(13) +#define CPM_CLKGR0_MSC2 BIT(12) +#define CPM_CLKGR0_MSC1 BIT(11) +#define CPM_CLKGR0_OWI BIT(10) +#define CPM_CLKGR0_TSSI BIT(9) +#define CPM_CLKGR0_AIC BIT(8) +#define CPM_CLKGR0_SCC BIT(7) +#define CPM_CLKGR0_I2C1 BIT(6) +#define CPM_CLKGR0_I2C0 BIT(5) +#define CPM_CLKGR0_SSI0 BIT(4) +#define CPM_CLKGR0_MSC0 BIT(3) +#define CPM_CLKGR0_OTG BIT(2) +#define CPM_CLKGR0_BCH BIT(1) +#define CPM_CLKGR0_NEMC BIT(0) + +/* Clock Gate Register1 */ +#define CPM_CLKGR1_P1 BIT(15) +#define CPM_CLKGR1_X2D BIT(14) +#define CPM_CLKGR1_DES BIT(13) +#define CPM_CLKGR1_I2C4 BIT(12) +#define CPM_CLKGR1_AHB BIT(11) +#define CPM_CLKGR1_UART4 BIT(10) +#define CPM_CLKGR1_HDMI BIT(9) +#define CPM_CLKGR1_OTG1 BIT(8) +#define CPM_CLKGR1_GPVLC BIT(7) +#define CPM_CLKGR1_AIC1 BIT(6) +#define CPM_CLKGR1_COMPRES BIT(5) +#define CPM_CLKGR1_GPU BIT(4) +#define CPM_CLKGR1_PCM BIT(3) +#define CPM_CLKGR1_VPU BIT(2) +#define CPM_CLKGR1_TSSI1 BIT(1) +#define CPM_CLKGR1_I2C3 BIT(0) + +/* Oscillator and Power Control Register */ +#define CPM_OPCR_O1ST_BIT 8 +#define CPM_OPCR_O1ST_MASK (0xff << CPM_OPCR_O1ST_BIT) +#define CPM_OPCR_SPENDN BIT(7) +#define CPM_OPCR_GPSEN BIT(6) +#define CPM_OPCR_SPENDH BIT(5) +#define CPM_OPCR_O1SE BIT(4) +#define CPM_OPCR_ERCS BIT(2) /* 0: select EXCLK/512 clock, 1: RTCLK clock */ +#define CPM_OPCR_USBM BIT(0) /* 0: select EXCLK/512 clock, 1: RTCLK clock */ + +/* Reset Status Register */ +#define CPM_RSR_P0R BIT(2) +#define CPM_RSR_WR BIT(1) +#define CPM_RSR_PR BIT(0) + +/* BCH clock divider register */ +#define CPM_BCHCDR_BPCS_BIT 30 +#define CPM_BCHCDR_BPCS_MASK (0x3 << CPM_BCHCDR_BPCS_BIT) +#define CPM_BCHCDR_BPCS_STOP (0X0 << CPM_BCHCDR_BPCS_BIT) +#define CPM_BCHCDR_BPCS_SRC_CLK (0x1 << CPM_BCHCDR_BPCS_BIT) +#define CPM_BCHCDR_BPCS_MPLL (0x2 << CPM_BCHCDR_BPCS_BIT) +#define CPM_BCHCDR_BPCS_EPLL (0x3 << CPM_BCHCDR_BPCS_BIT) +#define CPM_BCHCDR_CE_BCH BIT(29) +#define CPM_BCHCDR_BCH_BUSY BIT(28) +#define CPM_BCHCDR_BCH_STOP BIT(27) +#define CPM_BCHCDR_BCHCDR_BIT 0 +#define CPM_BCHCDR_BCHCDR_MASK (0x7 << CPM_BCHCDR_BCHCDR_BIT) + +/* CPM scratch pad protected register(CPSPPR) */ +#define CPSPPR_CPSPR_WRITABLE 0x00005a5a +#define RECOVERY_SIGNATURE 0x1a1a /* means "RECY" */ +#define RECOVERY_SIGNATURE_SEC 0x800 /* means "RECY" */ + +#define REBOOT_SIGNATURE 0x3535 /* means reboot */ + +/* XPLL control register */ +#define XLOCK (1 << 6) +#define XPLL_ON (1 << 4) +#define XF_MODE (1 << 3) +#define XPLLBP (1 << 1) +#define XPLLEN (1 << 0) + +enum PLLS { + EXTCLK = 0, + APLL, + MPLL, + EPLL, + VPLL, +}; + +#define M_N_OD(m,n,od) \ + ((((m) - 1) << 19) | (((n) - 1) << 13) | (((od) - 1) << 9)) + +struct cgu_pll_select { + u8 reg; + u8 pll; + u8 pll_shift; +}; + +static void pll_init_one(int pll, int m, int n, int od) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + void __iomem *pll_reg = cpm_regs + CPM_CPAPCR + ((pll - 1) * 4); + + setbits_le32(pll_reg, M_N_OD(m, n, od) | XPLLEN); + + /* FIXME */ + while (!(readl(pll_reg) & XPLL_ON)) + ; +} + +static void cpu_mux_select(int pll) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + u32 clk_ctrl; + unsigned int selectplls[] = { + CPM_PLL_SEL_STOP, + CPM_PLL_SEL_SRC, + CPM_PLL_SEL_MPLL, + CPM_PLL_SEL_EPLL + }; + + /* Init CPU, L2CACHE, AHB0, AHB2, APB clock */ + clk_ctrl = CPM_CPCCR_CE_CPU | CPM_CPCCR_CE_AHB0 | CPM_CPCCR_CE_AHB2 | + ((6 - 1) << CPM_CPCCR_H2DIV_BIT) | + ((3 - 1) << CPM_CPCCR_H0DIV_BIT) | + ((2 - 1) << CPM_CPCCR_L2DIV_BIT) | + ((1 - 1) << CPM_CPCCR_CDIV_BIT); + + if (CONFIG_SYS_MHZ >= 1000) + clk_ctrl |= (12 - 1) << CPM_CPCCR_PDIV_BIT; + else + clk_ctrl |= (6 - 1) << CPM_CPCCR_PDIV_BIT; + + clrsetbits_le32(cpm_regs + CPM_CPCCR, 0x00ffffff, clk_ctrl); + + while (readl(cpm_regs + CPM_CPCSR) & (CPM_CPCSR_CDIV_BUSY | + CPM_CPCSR_H0DIV_BUSY | CPM_CPCSR_H2DIV_BUSY)) + ; + + clk_ctrl = (selectplls[pll] << CPM_CPCCR_SEL_CPLL_BIT) | + (selectplls[MPLL] << CPM_CPCCR_SEL_H0PLL_BIT) | + (selectplls[MPLL] << CPM_CPCCR_SEL_H2PLL_BIT); + if (pll == APLL) + clk_ctrl |= CPM_PLL_SEL_SRC << CPM_CPCCR_SEL_SRC_BIT; + else + clk_ctrl |= CPM_SRC_SEL_EXCLK << CPM_CPCCR_SEL_SRC_BIT; + + clrsetbits_le32(cpm_regs + CPM_CPCCR, 0xff << 24, clk_ctrl); +} + +static void ddr_mux_select(int pll) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + int selectplls[] = { CPM_DDRCDR_DCS_STOP, + CPM_DDRCDR_DCS_SRC, + CPM_DDRCDR_DCS_MPLL}; + + writel(selectplls[pll] | CPM_DDRCDR_CE_DDR | (JZ4780_SYS_MEM_DIV - 1), + cpm_regs + CPM_DDCDR); + + while (readl(cpm_regs + CPM_DDCDR) & CPM_DDRCDR_DDR_BUSY) + ; + + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_DDR0); + + mdelay(200); +} + +static void cgu_mux_init(struct cgu_pll_select *cgu, unsigned int num) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + unsigned int selectplls[] = {0, 1, 2, 3, 2, 6}; + int i; + + for (i = 0; i < num; i++) + writel(selectplls[cgu[i].pll] << cgu[i].pll_shift, + cpm_regs + cgu[i].reg); +} + +void pll_init(void) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + struct cgu_pll_select cgu_mux[] = { + { CPM_MSCCDR, MPLL, 30 }, + { CPM_LPCDR, VPLL, 30 }, + { CPM_LPCDR1, VPLL, 30 }, + { CPM_GPUCDR, MPLL, 30 }, + { CPM_HDMICDR, VPLL, 30 }, + { CPM_I2SCDR, EPLL, 30 }, + { CPM_BCHCDR, MPLL, 30 }, + { CPM_VPUCDR, 0x1, 30 }, + { CPM_UHCCDR, 0x3, 30 }, + { CPM_CIMCDR, 0x1, 31 }, + { CPM_PCMCDR, 0x5, 29 }, + { CPM_SSICDR, 0x3, 30 }, + }; + + /* PLL stable time set to default -- 1ms */ + clrsetbits_le32(cpm_regs + CPM_CPPCR, 0xfffff, (16 << 8) | 0x20); + + pll_init_one(APLL, JZ4780_APLL_M, JZ4780_APLL_N, JZ4780_APLL_OD); + pll_init_one(MPLL, JZ4780_MPLL_M, JZ4780_MPLL_N, JZ4780_MPLL_OD); + pll_init_one(VPLL, JZ4780_VPLL_M, JZ4780_VPLL_N, JZ4780_VPLL_OD); + pll_init_one(EPLL, JZ4780_EPLL_M, JZ4780_EPLL_N, JZ4780_EPLL_OD); + + cpu_mux_select(MPLL); + ddr_mux_select(MPLL); + cgu_mux_init(cgu_mux, ARRAY_SIZE(cgu_mux)); +} + +const u32 jz4780_clk_get_efuse_clk(void) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + u32 cpccr = readl(cpm_regs + CPM_CPCCR); + u32 ahb2_div = ((cpccr & CPM_CPCCR_H2DIV_MASK) >> + CPM_CPCCR_H2DIV_BIT) + 1; + return JZ4780_SYS_MEM_SPEED / ahb2_div; +} + +void jz4780_clk_ungate_ethernet(void) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_MAC); + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_NEMC); +} + +void jz4780_clk_ungate_mmc(void) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + u32 msc_cdr = JZ4780_SYS_MEM_SPEED / 24000000 / 2 - 1; + msc_cdr |= CPM_MSCCDR_MPCS_MPLL | CPM_MSCCDR_CE; + writel(msc_cdr, cpm_regs + CPM_MSCCDR); + writel(msc_cdr, cpm_regs + CPM_MSCCDR1); + writel(msc_cdr, cpm_regs + CPM_MSCCDR2); + + /* The wait_for_bit() won't fit, thus unbounded loop here. */ + while (readl(cpm_regs + CPM_MSCCDR1) & CPM_MSCCDR_MSC_BUSY) + ; +} + +void jz4780_clk_ungate_uart(const unsigned int uart) +{ + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + if (uart == 0) + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART0); + else if (uart == 1) + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART1); + else if (uart == 2) + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART2); + else if (uart == 3) + clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART3); + else if (uart == 4) + clrbits_le32(cpm_regs + CPM_CLKGR1, CPM_CLKGR1_UART4); + else + printf("%s[%i]: Invalid UART %d\n", __func__, __LINE__, uart); +} diff --git a/arch/mips/mach-jz47xx/jz4780/sdram.c b/arch/mips/mach-jz47xx/jz4780/sdram.c new file mode 100644 index 000000000000..8cc3ffc85173 --- /dev/null +++ b/arch/mips/mach-jz47xx/jz4780/sdram.c @@ -0,0 +1,271 @@ +/* + * JZ4780 DDR initialization + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * Based on spl/common/{jz4780_ddr,jz_ddr3_init}.c from X-Boot + * Copyright (c) 2006-2013 Ingenic Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static const u32 get_mem_clk(void) +{ + const u32 mpll_out = ((u64)JZ4780_SYS_EXTAL * JZ4780_MPLL_M) / + (JZ4780_MPLL_N * JZ4780_MPLL_OD); + return mpll_out / JZ4780_SYS_MEM_DIV; +} + +u32 sdram_size(int cs) +{ + u32 dw = DDR_DW32 ? 4 : 2; + u32 banks = DDR_BANK8 ? 8 : 4; + u32 size = 0; + + if ((cs == 0) && DDR_CS0EN) { + size = (1 << (DDR_ROW + DDR_COL)) * dw * banks; + if (DDR_CS1EN && (size > 0x20000000)) + size = 0x20000000; + } else if ((cs == 1) && DDR_CS1EN) { + size = (1 << (DDR_ROW + DDR_COL)) * dw * banks; + } + + return size; +} + +static void ddr_cfg_init(void) +{ + void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE; + u32 ddrc_cfg, tmp; + + tmp = DDR_CL; + if (tmp) + tmp--; + if (tmp > 4) + tmp = 4; + + ddrc_cfg = DDRC_CFG_TYPE_DDR3 | DDRC_CFG_IMBA | + DDR_DW32 | DDRC_CFG_MPRT | ((tmp | 0x8) << 2) | + ((DDR_ROW - 12) << 11) | ((DDR_COL - 8) << 8) | + (DDR_CS0EN << 6) | (DDR_BANK8 << 1) | + ((DDR_ROW - 12) << 27) | ((DDR_COL - 8) << 24) | + (DDR_CS1EN << 7) | (DDR_BANK8 << 23); + + if (DDR_BL > 4) + ddrc_cfg |= BIT(21); + + writel(ddrc_cfg, ddr_ctl_regs + DDRC_CFG); +} + +static void ddr_phy_init(const struct jz4780_ddr_config *ddr_config) +{ + void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE; + void __iomem *ddr_phy_regs = ddr_ctl_regs + DDR_PHY_OFFSET; + unsigned int count = 0, i; + u32 reg, mask; + + writel(DDRP_DCR_TYPE_DDR3 | (DDR_BANK8 << 3), ddr_phy_regs + DDRP_DCR); + + writel(ddr_config->mr0, ddr_phy_regs + DDRP_MR0); + writel(ddr_config->mr1, ddr_phy_regs + DDRP_MR1); + writel(0, ddr_phy_regs + DDRP_ODTCR); + writel(0, ddr_phy_regs + DDRP_MR2); + + writel(ddr_config->ptr0, ddr_phy_regs + DDRP_PTR0); + writel(ddr_config->ptr1, ddr_phy_regs + DDRP_PTR1); + writel(ddr_config->ptr2, ddr_phy_regs + DDRP_PTR2); + + writel(ddr_config->dtpr0, ddr_phy_regs + DDRP_DTPR0); + writel(ddr_config->dtpr1, ddr_phy_regs + DDRP_DTPR1); + writel(ddr_config->dtpr2, ddr_phy_regs + DDRP_DTPR2); + + writel(DDRP_PGCR_DQSCFG | (7 << DDRP_PGCR_CKEN_BIT) | + (2 << DDRP_PGCR_CKDV_BIT) | + (DDR_CS0EN | (DDR_CS1EN << 1)) << DDRP_PGCR_RANKEN_BIT | + DDRP_PGCR_ZCKSEL_32 | DDRP_PGCR_PDDISDX, + ddr_phy_regs + DDRP_PGCR); + + for (i = 0; i < 8; i++) + clrbits_le32(ddr_phy_regs + DDRP_DXGCR(i), 0x3 << 9); + + count = 0; + mask = DDRP_PGSR_IDONE | DDRP_PGSR_DLDONE | DDRP_PGSR_ZCDONE; + for (;;) { + reg = readl(ddr_phy_regs + DDRP_PGSR); + if ((reg == mask) || (reg == 0x1f)) + break; + if (count++ == 10000) + hang(); + } + + /* DQS extension and early set to 1 */ + clrsetbits_le32(ddr_phy_regs + DDRP_DSGCR, 0x7E << 4, 0x12 << 4); + + /* 500 pull up and 500 pull down */ + clrsetbits_le32(ddr_phy_regs + DDRP_DXCCR, 0xFF << 4, 0xC4 << 4); + + /* Initialise phy */ + writel(DDRP_PIR_INIT | DDRP_PIR_DRAMINT | DDRP_PIR_DRAMRST, + ddr_phy_regs + DDRP_PIR); + + count = 0; + mask |= DDRP_PGSR_DIDONE; + for (;;) { + reg = readl(ddr_phy_regs + DDRP_PGSR); + if ((reg == mask) || (reg == 0x1f)) + break; + if (count++ == 20000) + hang(); + } + + writel(DDRP_PIR_INIT | DDRP_PIR_QSTRN, ddr_phy_regs + DDRP_PIR); + + count = 0; + mask |= DDRP_PGSR_DTDONE; + for (;;) { + reg = readl(ddr_phy_regs + DDRP_PGSR); + if (reg == mask) + break; + if (count++ != 50000) + continue; + reg &= DDRP_PGSR_DTDONE | DDRP_PGSR_DTERR | DDRP_PGSR_DTIERR; + if (reg) + hang(); + count = 0; + } + + /* Override impedance */ + clrsetbits_le32(ddr_phy_regs + DDRP_ZQXCR0(0), 0x3ff, + ((ddr_config->pullup & 0x1f) << DDRP_ZQXCR_PULLUP_IMPE_BIT) | + ((ddr_config->pulldn & 0x1f) << DDRP_ZQXCR_PULLDOWN_IMPE_BIT) | + DDRP_ZQXCR_ZDEN); +} + +#define JZBIT(bit) ((bit % 4) * 8) +#define JZMASK(bit) (0x1f << JZBIT(bit)) + +static void remap_swap(int a, int b) +{ + void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE; + u32 remmap[2], tmp[2]; + + remmap[0] = readl(ddr_ctl_regs + DDRC_REMMAP(a / 4)); + remmap[1] = readl(ddr_ctl_regs + DDRC_REMMAP(b / 4)); + + tmp[0] = (remmap[0] & JZMASK(a)) >> JZBIT(a); + tmp[1] = (remmap[1] & JZMASK(b)) >> JZBIT(b); + + remmap[0] &= ~JZMASK(a); + remmap[1] &= ~JZMASK(b); + + writel(remmap[0] | (tmp[1] << JZBIT(a)), + ddr_ctl_regs + DDRC_REMMAP(a / 4)); + writel(remmap[1] | (tmp[0] << JZBIT(b)), + ddr_ctl_regs + DDRC_REMMAP(b / 4)); +} + +static void mem_remap(void) +{ + u32 start = (DDR_ROW + DDR_COL + (DDR_DW32 ? 4 : 2) / 2) - 12; + u32 num = DDR_BANK8 ? 3 : 2; + + if (DDR_CS0EN && DDR_CS1EN) + num++; + + for (; num > 0; num--) + remap_swap(0 + num - 1, start + num - 1); +} + +/* Fetch DRAM config from board file */ +__weak const struct jz4780_ddr_config *jz4780_get_ddr_config(void) +{ + return NULL; +} + +void sdram_init(void) +{ + const struct jz4780_ddr_config *ddr_config = jz4780_get_ddr_config(); + void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE; + void __iomem *ddr_phy_regs = ddr_ctl_regs + DDR_PHY_OFFSET; + void __iomem *cpm_regs = (void __iomem *)CPM_BASE; + u32 mem_clk, tmp, i; + u32 mem_base0, mem_base1; + u32 mem_mask0, mem_mask1; + u32 mem_size0, mem_size1; + + if (!ddr_config) + hang(); + + /* Reset DLL in DDR PHY */ + writel(0x3, cpm_regs + 0xd0); + mdelay(400); + writel(0x1, cpm_regs + 0xd0); + mdelay(400); + + /* Enter reset */ + writel(0xf << 20, ddr_ctl_regs + DDRC_CTRL); + + mem_clk = get_mem_clk(); + + tmp = 1000000000 / mem_clk; + if (1000000000 % mem_clk) + tmp++; + tmp = DDR_tREFI / tmp; + tmp = tmp / (16 * (1 << DDR_CLK_DIV)) - 1; + if (tmp > 0xff) + tmp = 0xff; + if (tmp < 1) + tmp = 1; + + writel(0x0, ddr_ctl_regs + DDRC_CTRL); + + writel(0x150000, ddr_phy_regs + DDRP_DTAR); + ddr_phy_init(ddr_config); + + writel(DDRC_CTRL_CKE | DDRC_CTRL_ALH, ddr_ctl_regs + DDRC_CTRL); + writel(0x0, ddr_ctl_regs + DDRC_CTRL); + + ddr_cfg_init(); + + for (i = 0; i < 6; i++) + writel(ddr_config->timing[i], ddr_ctl_regs + DDRC_TIMING(i)); + + mem_size0 = sdram_size(0); + mem_size1 = sdram_size(1); + + if (!mem_size1 && mem_size0 > 0x20000000) { + mem_base0 = 0x0; + mem_mask0 = ~(((mem_size0 * 2) >> 24) - 1) & DDRC_MMAP_MASK_MASK; + } else { + mem_base0 = (DDR_MEM_PHY_BASE >> 24) & 0xff; + mem_mask0 = ~((mem_size0 >> 24) - 1) & DDRC_MMAP_MASK_MASK; + } + + if (mem_size1) { + mem_mask1 = ~((mem_size1 >> 24) - 1) & DDRC_MMAP_MASK_MASK; + mem_base1 = ((DDR_MEM_PHY_BASE + mem_size0) >> 24) & 0xff; + } else { + mem_mask1 = 0; + mem_base1 = 0xff; + } + + writel(mem_base0 << DDRC_MMAP_BASE_BIT | mem_mask0, + ddr_ctl_regs + DDRC_MMAP0); + writel(mem_base1 << DDRC_MMAP_BASE_BIT | mem_mask1, + ddr_ctl_regs + DDRC_MMAP1); + writel(DDRC_CTRL_CKE | DDRC_CTRL_ALH, ddr_ctl_regs + DDRC_CTRL); + writel((DDR_CLK_DIV << 1) | DDRC_REFCNT_REF_EN | + (tmp << DDRC_REFCNT_CON_BIT), + ddr_ctl_regs + DDRC_REFCNT); + writel((1 << 15) | (4 << 12) | (1 << 11) | (1 << 8) | (0 << 6) | + (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1), + ddr_ctl_regs + DDRC_CTRL); + mem_remap(); + clrbits_le32(ddr_ctl_regs + DDRC_ST, 0x40); +} diff --git a/arch/mips/mach-jz47xx/jz4780/timer.c b/arch/mips/mach-jz47xx/jz4780/timer.c new file mode 100644 index 000000000000..a9fc2cb38e51 --- /dev/null +++ b/arch/mips/mach-jz47xx/jz4780/timer.c @@ -0,0 +1,238 @@ +/* + * JZ4780 timer + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +#define TCU_TSR 0x1C /* Timer Stop Register */ +#define TCU_TSSR 0x2C /* Timer Stop Set Register */ +#define TCU_TSCR 0x3C /* Timer Stop Clear Register */ +#define TCU_TER 0x10 /* Timer Counter Enable Register */ +#define TCU_TESR 0x14 /* Timer Counter Enable Set Register */ +#define TCU_TECR 0x18 /* Timer Counter Enable Clear Register */ +#define TCU_TFR 0x20 /* Timer Flag Register */ +#define TCU_TFSR 0x24 /* Timer Flag Set Register */ +#define TCU_TFCR 0x28 /* Timer Flag Clear Register */ +#define TCU_TMR 0x30 /* Timer Mask Register */ +#define TCU_TMSR 0x34 /* Timer Mask Set Register */ +#define TCU_TMCR 0x38 /* Timer Mask Clear Register */ +/* n = 0,1,2,3,4,5 */ +#define TCU_TDFR(n) (0x40 + (n) * 0x10) /* Timer Data Full Reg */ +#define TCU_TDHR(n) (0x44 + (n) * 0x10) /* Timer Data Half Reg */ +#define TCU_TCNT(n) (0x48 + (n) * 0x10) /* Timer Counter Reg */ +#define TCU_TCSR(n) (0x4C + (n) * 0x10) /* Timer Control Reg */ + +#define TCU_OSTCNTL 0xe4 +#define TCU_OSTCNTH 0xe8 +#define TCU_OSTCSR 0xec +#define TCU_OSTCNTHBUF 0xfc + +/* Register definitions */ +#define TCU_TCSR_PWM_SD BIT(9) +#define TCU_TCSR_PWM_INITL_HIGH BIT(8) +#define TCU_TCSR_PWM_EN BIT(7) +#define TCU_TCSR_PRESCALE_BIT 3 +#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT) +#define TCU_TCSR_EXT_EN BIT(2) +#define TCU_TCSR_RTC_EN BIT(1) +#define TCU_TCSR_PCK_EN BIT(0) + +#define TCU_TER_TCEN5 BIT(5) +#define TCU_TER_TCEN4 BIT(4) +#define TCU_TER_TCEN3 BIT(3) +#define TCU_TER_TCEN2 BIT(2) +#define TCU_TER_TCEN1 BIT(1) +#define TCU_TER_TCEN0 BIT(0) + +#define TCU_TESR_TCST5 BIT(5) +#define TCU_TESR_TCST4 BIT(4) +#define TCU_TESR_TCST3 BIT(3) +#define TCU_TESR_TCST2 BIT(2) +#define TCU_TESR_TCST1 BIT(1) +#define TCU_TESR_TCST0 BIT(0) + +#define TCU_TECR_TCCL5 BIT(5) +#define TCU_TECR_TCCL4 BIT(4) +#define TCU_TECR_TCCL3 BIT(3) +#define TCU_TECR_TCCL2 BIT(2) +#define TCU_TECR_TCCL1 BIT(1) +#define TCU_TECR_TCCL0 BIT(0) + +#define TCU_TFR_HFLAG5 BIT(21) +#define TCU_TFR_HFLAG4 BIT(20) +#define TCU_TFR_HFLAG3 BIT(19) +#define TCU_TFR_HFLAG2 BIT(18) +#define TCU_TFR_HFLAG1 BIT(17) +#define TCU_TFR_HFLAG0 BIT(16) +#define TCU_TFR_FFLAG5 BIT(5) +#define TCU_TFR_FFLAG4 BIT(4) +#define TCU_TFR_FFLAG3 BIT(3) +#define TCU_TFR_FFLAG2 BIT(2) +#define TCU_TFR_FFLAG1 BIT(1) +#define TCU_TFR_FFLAG0 BIT(0) + +#define TCU_TFSR_HFLAG5 BIT(21) +#define TCU_TFSR_HFLAG4 BIT(20) +#define TCU_TFSR_HFLAG3 BIT(19) +#define TCU_TFSR_HFLAG2 BIT(18) +#define TCU_TFSR_HFLAG1 BIT(17) +#define TCU_TFSR_HFLAG0 BIT(16) +#define TCU_TFSR_FFLAG5 BIT(5) +#define TCU_TFSR_FFLAG4 BIT(4) +#define TCU_TFSR_FFLAG3 BIT(3) +#define TCU_TFSR_FFLAG2 BIT(2) +#define TCU_TFSR_FFLAG1 BIT(1) +#define TCU_TFSR_FFLAG0 BIT(0) + +#define TCU_TFCR_HFLAG5 BIT(21) +#define TCU_TFCR_HFLAG4 BIT(20) +#define TCU_TFCR_HFLAG3 BIT(19) +#define TCU_TFCR_HFLAG2 BIT(18) +#define TCU_TFCR_HFLAG1 BIT(17) +#define TCU_TFCR_HFLAG0 BIT(16) +#define TCU_TFCR_FFLAG5 BIT(5) +#define TCU_TFCR_FFLAG4 BIT(4) +#define TCU_TFCR_FFLAG3 BIT(3) +#define TCU_TFCR_FFLAG2 BIT(2) +#define TCU_TFCR_FFLAG1 BIT(1) +#define TCU_TFCR_FFLAG0 BIT(0) + +#define TCU_TMR_HMASK5 BIT(21) +#define TCU_TMR_HMASK4 BIT(20) +#define TCU_TMR_HMASK3 BIT(19) +#define TCU_TMR_HMASK2 BIT(18) +#define TCU_TMR_HMASK1 BIT(17) +#define TCU_TMR_HMASK0 BIT(16) +#define TCU_TMR_FMASK5 BIT(5) +#define TCU_TMR_FMASK4 BIT(4) +#define TCU_TMR_FMASK3 BIT(3) +#define TCU_TMR_FMASK2 BIT(2) +#define TCU_TMR_FMASK1 BIT(1) +#define TCU_TMR_FMASK0 BIT(0) + +#define TCU_TMSR_HMST5 BIT(21) +#define TCU_TMSR_HMST4 BIT(20) +#define TCU_TMSR_HMST3 BIT(19) +#define TCU_TMSR_HMST2 BIT(18) +#define TCU_TMSR_HMST1 BIT(17) +#define TCU_TMSR_HMST0 BIT(16) +#define TCU_TMSR_FMST5 BIT(5) +#define TCU_TMSR_FMST4 BIT(4) +#define TCU_TMSR_FMST3 BIT(3) +#define TCU_TMSR_FMST2 BIT(2) +#define TCU_TMSR_FMST1 BIT(1) +#define TCU_TMSR_FMST0 BIT(0) + +#define TCU_TMCR_HMCL5 BIT(21) +#define TCU_TMCR_HMCL4 BIT(20) +#define TCU_TMCR_HMCL3 BIT(19) +#define TCU_TMCR_HMCL2 BIT(18) +#define TCU_TMCR_HMCL1 BIT(17) +#define TCU_TMCR_HMCL0 BIT(16) +#define TCU_TMCR_FMCL5 BIT(5) +#define TCU_TMCR_FMCL4 BIT(4) +#define TCU_TMCR_FMCL3 BIT(3) +#define TCU_TMCR_FMCL2 BIT(2) +#define TCU_TMCR_FMCL1 BIT(1) +#define TCU_TMCR_FMCL0 BIT(0) + +#define TCU_TSR_WDTS BIT(16) +#define TCU_TSR_STOP5 BIT(5) +#define TCU_TSR_STOP4 BIT(4) +#define TCU_TSR_STOP3 BIT(3) +#define TCU_TSR_STOP2 BIT(2) +#define TCU_TSR_STOP1 BIT(1) +#define TCU_TSR_STOP0 BIT(0) + +#define TCU_TSSR_WDTSS BIT(16) +#define TCU_TSSR_STPS5 BIT(5) +#define TCU_TSSR_STPS4 BIT(4) +#define TCU_TSSR_STPS3 BIT(3) +#define TCU_TSSR_STPS2 BIT(2) +#define TCU_TSSR_STPS1 BIT(1) +#define TCU_TSSR_STPS0 BIT(0) + +#define TCU_TSSR_WDTSC BIT(16) +#define TCU_TSSR_STPC5 BIT(5) +#define TCU_TSSR_STPC4 BIT(4) +#define TCU_TSSR_STPC3 BIT(3) +#define TCU_TSSR_STPC2 BIT(2) +#define TCU_TSSR_STPC1 BIT(1) +#define TCU_TSSR_STPC0 BIT(0) + +#define TER_OSTEN BIT(15) + +#define OSTCSR_CNT_MD BIT(15) +#define OSTCSR_SD BIT(9) +#define OSTCSR_PRESCALE_16 (0x2 << 3) +#define OSTCSR_EXT_EN BIT(2) + +int timer_init(void) +{ + void __iomem *regs = (void __iomem *)TCU_BASE; + + writel(OSTCSR_SD, regs + TCU_OSTCSR); + reset_timer(); + writel(OSTCSR_CNT_MD | OSTCSR_EXT_EN | OSTCSR_PRESCALE_16, + regs + TCU_OSTCSR); + writew(TER_OSTEN, regs + TCU_TESR); + return 0; +} + +void reset_timer(void) +{ + void __iomem *regs = (void __iomem *)TCU_BASE; + + writel(0, regs + TCU_OSTCNTH); + writel(0, regs + TCU_OSTCNTL); +} + +static u64 get_timer64(void) +{ + void __iomem *regs = (void __iomem *)TCU_BASE; + u32 low = readl(regs + TCU_OSTCNTL); + u32 high = readl(regs + TCU_OSTCNTHBUF); + return ((u64)high << 32) | low; +} + +ulong get_timer(ulong base) +{ + return lldiv(get_timer64(), 3000) - base; +} + +void __udelay(unsigned long usec) +{ + /* OST count increments at 3MHz */ + u64 end = get_timer64() + ((u64)usec * 3); + while (get_timer64() < end) + ; +} + +unsigned long long get_ticks(void) +{ + return get_timer64(); +} + +void jz4780_tcu_wdt_start(void) +{ + void __iomem *tcu_regs = (void __iomem *)TCU_BASE; + + /* Enable WDT clock */ + writel(TCU_TSSR_WDTSC, tcu_regs + TCU_TSCR); +} diff --git a/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds new file mode 100644 index 000000000000..f6d2d2d9117a --- /dev/null +++ b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + .text : + { + __image_copy_start = .; + arch/mips/mach-jz47xx/start.o (.text*) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + . = ALIGN(4); + __image_copy_end = .; + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.sbss.*) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } >.sdram + + /DISCARD/ : { + *(.dynbss) + *(.dynstr) + *(.dynamic) + *(.interp) + *(.hash) + *(.gnu.*) + *(.plt) + *(.got.plt) + *(.rel.plt) + *(.rel.dyn) + } +} diff --git a/arch/mips/mach-jz47xx/start.S b/arch/mips/mach-jz47xx/start.S new file mode 100644 index 000000000000..9f70596d3302 --- /dev/null +++ b/arch/mips/mach-jz47xx/start.S @@ -0,0 +1,99 @@ +/* + * Startup Code for MIPS32 XBURST CPU-core + * + * Copyright (c) 2010 Xiangfu Liu + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + + .set noreorder + + .globl _start + .text +_start: +#ifdef CONFIG_SPL_BUILD + + /* magic value ("MSPL") */ + .word 0x4d53504c + + /* Invalidate BTB */ + mfc0 t0, CP0_CONFIG, 7 + nop + ori t0, 2 + mtc0 t0, CP0_CONFIG, 7 + nop + + /* + * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1 + */ + li t0, 0x0040FC04 + mtc0 t0, CP0_STATUS + + /* CAUSE register */ + /* IV=1, use the specical interrupt vector (0x200) */ + li t1, 0x00800000 + mtc0 t1, CP0_CAUSE + +#ifdef CONFIG_SOC_JZ4780 + /* enable bridge radical mode */ + la t0, CPM_BASE + lw t1, 0x24(t0) + ori t1, t1, 0x22 + sw t1, 0x24(t0) +#endif + + /* Set up stack */ + li sp, CONFIG_SPL_STACK + + b board_init_f + nop + +#ifdef CONFIG_SOC_JZ4780 + + .globl enable_caches + .ent enable_caches +enable_caches: + mtc0 zero, CP0_TAGLO + mtc0 zero, CP0_TAGHI + + li t0, KSEG0 + addu t1, t0, CONFIG_SYS_DCACHE_SIZE +1: + cache INDEX_STORE_TAG_D, 0(t0) + bne t0, t1, 1b + addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE + + li t0, KSEG0 + addu t1, t0, CONFIG_SYS_ICACHE_SIZE +2: + cache INDEX_STORE_TAG_I, 0(t0) + bne t0, t1, 2b + addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE + + /* Invalidate BTB */ + mfc0 t0, CP0_CONFIG, 7 + nop + ori t0, 2 + mtc0 t0, CP0_CONFIG, 7 + nop + + /* Enable caches */ + li t0, CONF_CM_CACHABLE_NONCOHERENT + mtc0 t0, CP0_CONFIG + nop + + jr ra + nop + + .end enable_caches + +#endif /* CONFIG_SOC_JZ4780 */ +#endif /* !CONFIG_SPL_BUILD */ diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h new file mode 100644 index 000000000000..467165e3cfee --- /dev/null +++ b/include/dt-bindings/clock/jz4780-cgu.h @@ -0,0 +1,88 @@ +/* + * This header provides clock numbers for the ingenic,jz4780-cgu DT binding. + * + * They are roughly ordered as: + * - external clocks + * - PLLs + * - muxes/dividers in the order they appear in the jz4780 programmers manual + * - gates in order of their bit in the CLKGR* registers + */ + +#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ +#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ + +#define JZ4780_CLK_EXCLK 0 +#define JZ4780_CLK_RTCLK 1 +#define JZ4780_CLK_APLL 2 +#define JZ4780_CLK_MPLL 3 +#define JZ4780_CLK_EPLL 4 +#define JZ4780_CLK_VPLL 5 +#define JZ4780_CLK_OTGPHY 6 +#define JZ4780_CLK_SCLKA 7 +#define JZ4780_CLK_CPUMUX 8 +#define JZ4780_CLK_CPU 9 +#define JZ4780_CLK_L2CACHE 10 +#define JZ4780_CLK_AHB0 11 +#define JZ4780_CLK_AHB2PMUX 12 +#define JZ4780_CLK_AHB2 13 +#define JZ4780_CLK_PCLK 14 +#define JZ4780_CLK_DDR 15 +#define JZ4780_CLK_VPU 16 +#define JZ4780_CLK_I2SPLL 17 +#define JZ4780_CLK_I2S 18 +#define JZ4780_CLK_LCD0PIXCLK 19 +#define JZ4780_CLK_LCD1PIXCLK 20 +#define JZ4780_CLK_MSCMUX 21 +#define JZ4780_CLK_MSC0 22 +#define JZ4780_CLK_MSC1 23 +#define JZ4780_CLK_MSC2 24 +#define JZ4780_CLK_UHC 25 +#define JZ4780_CLK_SSIPLL 26 +#define JZ4780_CLK_SSI 27 +#define JZ4780_CLK_CIMMCLK 28 +#define JZ4780_CLK_PCMPLL 29 +#define JZ4780_CLK_PCM 30 +#define JZ4780_CLK_GPU 31 +#define JZ4780_CLK_HDMI 32 +#define JZ4780_CLK_BCH 33 +#define JZ4780_CLK_NEMC 34 +#define JZ4780_CLK_OTG0 35 +#define JZ4780_CLK_SSI0 36 +#define JZ4780_CLK_SMB0 37 +#define JZ4780_CLK_SMB1 38 +#define JZ4780_CLK_SCC 39 +#define JZ4780_CLK_AIC 40 +#define JZ4780_CLK_TSSI0 41 +#define JZ4780_CLK_OWI 42 +#define JZ4780_CLK_KBC 43 +#define JZ4780_CLK_SADC 44 +#define JZ4780_CLK_UART0 45 +#define JZ4780_CLK_UART1 46 +#define JZ4780_CLK_UART2 47 +#define JZ4780_CLK_UART3 48 +#define JZ4780_CLK_SSI1 49 +#define JZ4780_CLK_SSI2 50 +#define JZ4780_CLK_PDMA 51 +#define JZ4780_CLK_GPS 52 +#define JZ4780_CLK_MAC 53 +#define JZ4780_CLK_SMB2 54 +#define JZ4780_CLK_CIM 55 +#define JZ4780_CLK_LCD 56 +#define JZ4780_CLK_TVE 57 +#define JZ4780_CLK_IPU 58 +#define JZ4780_CLK_DDR0 59 +#define JZ4780_CLK_DDR1 60 +#define JZ4780_CLK_SMB3 61 +#define JZ4780_CLK_TSSI1 62 +#define JZ4780_CLK_COMPRESS 63 +#define JZ4780_CLK_AIC1 64 +#define JZ4780_CLK_GPVLC 65 +#define JZ4780_CLK_OTG1 66 +#define JZ4780_CLK_UART4 67 +#define JZ4780_CLK_AHBMON 68 +#define JZ4780_CLK_SMB4 69 +#define JZ4780_CLK_DES 70 +#define JZ4780_CLK_X2D 71 +#define JZ4780_CLK_CORE1 72 + +#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */ From patchwork Mon Dec 10 20:36:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 1010674 X-Patchwork-Delegate: daniel.schwierzeck@googlemail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) 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=collabora.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43DFLl1v65z9s4s for ; Tue, 11 Dec 2018 07:39:59 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id D651DC2228E; Mon, 10 Dec 2018 20:39:57 +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_DNSWL_NONE, SPF_HELO_PASS, UNPARSEABLE_RELAY 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 F2490C2222F; Mon, 10 Dec 2018 20:36:42 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 34401C21E13; Mon, 10 Dec 2018 20:36:36 +0000 (UTC) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lists.denx.de (Postfix) with ESMTPS id 6EFC5C22375 for ; Mon, 10 Dec 2018 20:36:32 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: ezequiel) with ESMTPSA id 75DC02610F6 From: Ezequiel Garcia To: u-boot@lists.denx.de Date: Mon, 10 Dec 2018 17:36:02 -0300 Message-Id: <20181210203602.820-7-ezequiel@collabora.com> X-Mailer: git-send-email 2.20.0.rc2 In-Reply-To: <20181210203602.820-1-ezequiel@collabora.com> References: <20181210203602.820-1-ezequiel@collabora.com> MIME-Version: 1.0 Cc: Marek Vasut , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [U-Boot] [PATCH 6/6] mips: jz47xx: Add Creator CI20 platform 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" From: Paul Burton Add support for the Creator CI20 platform based on the JZ4780 SoC. Cc: Daniel Schwierzeck Signed-off-by: Paul Burton Signed-off-by: Marek Vasut Signed-off-by: Ezequiel Garcia --- arch/mips/dts/Makefile | 1 + arch/mips/dts/ci20.dts | 120 +++++++++++ arch/mips/mach-jz47xx/Kconfig | 11 + board/imgtec/ci20/Kconfig | 15 ++ board/imgtec/ci20/Makefile | 5 + board/imgtec/ci20/README | 10 + board/imgtec/ci20/ci20.c | 365 ++++++++++++++++++++++++++++++++++ configs/ci20_defconfig | 47 +++++ include/configs/ci20.h | 74 +++++++ 9 files changed, 648 insertions(+) create mode 100644 arch/mips/dts/ci20.dts create mode 100644 board/imgtec/ci20/Kconfig create mode 100644 board/imgtec/ci20/Makefile create mode 100644 board/imgtec/ci20/README create mode 100644 board/imgtec/ci20/ci20.c create mode 100644 configs/ci20_defconfig create mode 100644 include/configs/ci20.h diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index b447141f8717..647d2bf0d53b 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -16,6 +16,7 @@ dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb dtb-$(CONFIG_BOARD_NETGEAR_DGND3700V2) += netgear,dgnd3700v2.dtb dtb-$(CONFIG_BOARD_SAGEM_FAST1704) += sagem,f@st1704.dtb dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb +dtb-$(CONFIG_TARGET_JZ4780_CI20) += ci20.dtb targets += $(dtb-y) diff --git a/arch/mips/dts/ci20.dts b/arch/mips/dts/ci20.dts new file mode 100644 index 000000000000..934d9e96d24d --- /dev/null +++ b/arch/mips/dts/ci20.dts @@ -0,0 +1,120 @@ +/dts-v1/; + +#include "jz4780.dtsi" + +/ { + compatible = "img,ci20", "ingenic,jz4780"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial3 = &uart3; + serial4 = &uart4; + }; + + chosen { + stdout-path = "serial4:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x10000000 + 0x30000000 0x30000000>; + }; +}; + +&ext { + clock-frequency = <48000000>; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&uart4 { + status = "okay"; +}; + +&nemc { + status = "okay"; + + nandc: nand-controller@1 { + compatible = "ingenic,jz4780-nand"; + reg = <1 0 0x1000000>; + + #address-cells = <1>; + #size-cells = <0>; + + ingenic,bch-controller = <&bch>; + + ingenic,nemc-tAS = <10>; + ingenic,nemc-tAH = <5>; + ingenic,nemc-tBP = <10>; + ingenic,nemc-tAW = <15>; + ingenic,nemc-tSTRV = <100>; + + nand@1 { + reg = <1>; + + nand-ecc-step-size = <1024>; + nand-ecc-strength = <24>; + nand-ecc-mode = "hw"; + nand-on-flash-bbt; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <2>; + #size-cells = <2>; + + partition@0 { + label = "u-boot-spl"; + reg = <0x0 0x0 0x0 0x800000>; + }; + + partition@0x800000 { + label = "u-boot"; + reg = <0x0 0x800000 0x0 0x200000>; + }; + + partition@0xa00000 { + label = "u-boot-env"; + reg = <0x0 0xa00000 0x0 0x200000>; + }; + + partition@0xc00000 { + label = "boot"; + reg = <0x0 0xc00000 0x0 0x4000000>; + }; + + partition@0x8c00000 { + label = "system"; + reg = <0x0 0x4c00000 0x1 0xfb400000>; + }; + }; + }; + }; +}; + +&bch { + status = "okay"; +}; + +&mmc0 { + bus-width = <4>; + max-frequency = <50000000>; + status = "okay"; +}; + +&mmc1 { + bus-width = <4>; + max-frequency = <50000000>; + status = "okay"; +}; diff --git a/arch/mips/mach-jz47xx/Kconfig b/arch/mips/mach-jz47xx/Kconfig index cd6944cfc252..dcaac0162866 100644 --- a/arch/mips/mach-jz47xx/Kconfig +++ b/arch/mips/mach-jz47xx/Kconfig @@ -12,4 +12,15 @@ config SOC_JZ4780 help Support for Ingenic JZ4780 family SoCs. +choice + prompt "Board select" + +config TARGET_JZ4780_CI20 + bool "Creator CI20 Reference Board" + select SOC_JZ4780 + +endchoice + +source "board/imgtec/ci20/Kconfig" + endmenu diff --git a/board/imgtec/ci20/Kconfig b/board/imgtec/ci20/Kconfig new file mode 100644 index 000000000000..82bf65d64f1e --- /dev/null +++ b/board/imgtec/ci20/Kconfig @@ -0,0 +1,15 @@ +if TARGET_JZ4780_CI20 + +config SYS_BOARD + default "ci20" + +config SYS_VENDOR + default "imgtec" + +config SYS_CONFIG_NAME + default "ci20" + +config SYS_TEXT_BASE + default 0x80000000 + +endif diff --git a/board/imgtec/ci20/Makefile b/board/imgtec/ci20/Makefile new file mode 100644 index 000000000000..8c00081e660b --- /dev/null +++ b/board/imgtec/ci20/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := ci20.o diff --git a/board/imgtec/ci20/README b/board/imgtec/ci20/README new file mode 100644 index 000000000000..c757d41c7640 --- /dev/null +++ b/board/imgtec/ci20/README @@ -0,0 +1,10 @@ +CI20 U-Boot + +Installation to an SD card: + Repartition your card with an MBR such that the first partition starts at an + offset of no less than 270KB. Then install U-Boot SPL & the full U-Boot image + to the card like so: + + dd if=spl/u-boot-spl.bin of=/dev/sdX obs=512 seek=1 + dd if=u-boot.img of=/dev/sdX obs=1K seek=14 + sync diff --git a/board/imgtec/ci20/ci20.c b/board/imgtec/ci20/ci20.c new file mode 100644 index 000000000000..8e5b11e2679a --- /dev/null +++ b/board/imgtec/ci20/ci20.c @@ -0,0 +1,365 @@ +/* + * CI20 setup code + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define JZ_GPIO(bank, pin) ((32 * (bank)) + (pin)) + +#define CONFIG_JTAG + +struct ci20_otp { + u32 serial_number; + u32 date; + u8 manufacturer[2]; + u8 mac[6]; +} __packed; + +static void ci20_mux_eth(void) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + +#ifdef CONFIG_NAND + /* setup pins (some already setup for NAND) */ + writel(0x04030000, gpio_regs + GPIO_PXINTC(0)); + writel(0x04030000, gpio_regs + GPIO_PXMASKC(0)); + writel(0x04030000, gpio_regs + GPIO_PXPAT1C(0)); + writel(0x04030000, gpio_regs + GPIO_PXPAT0C(0)); + writel(0x04030000, gpio_regs + GPIO_PXPENS(0)); +#else + /* setup pins (as above +NAND CS +RD/WE +SDx +SAx) */ + writel(0x0dff00ff, gpio_regs + GPIO_PXINTC(0)); + writel(0x0dff00ff, gpio_regs + GPIO_PXMASKC(0)); + writel(0x0dff00ff, gpio_regs + GPIO_PXPAT1C(0)); + writel(0x0dff00ff, gpio_regs + GPIO_PXPAT0C(0)); + writel(0x0dff00ff, gpio_regs + GPIO_PXPENS(0)); + writel(0x00000003, gpio_regs + GPIO_PXINTC(1)); + writel(0x00000003, gpio_regs + GPIO_PXMASKC(1)); + writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1)); + writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1)); + writel(0x00000003, gpio_regs + GPIO_PXPENS(1)); +#endif +} + +static void ci20_mux_jtag(void) +{ +#ifdef CONFIG_JTAG + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + + /* enable JTAG */ + writel(3 << 30, gpio_regs + GPIO_PXINTC(0)); + writel(3 << 30, gpio_regs + GPIO_PXMASKC(0)); + writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0)); + writel(3 << 30, gpio_regs + GPIO_PXPAT0C(0)); +#endif +} + +static void ci20_mux_mmc(void) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + + /* setup MSC1 pins */ + writel(0x30f00000, gpio_regs + GPIO_PXINTC(4)); + writel(0x30f00000, gpio_regs + GPIO_PXMASKC(4)); + writel(0x30f00000, gpio_regs + GPIO_PXPAT1C(4)); + writel(0x30f00000, gpio_regs + GPIO_PXPAT0C(4)); + writel(0x30f00000, gpio_regs + GPIO_PXPENC(4)); + jz4780_clk_ungate_mmc(); +} + +static void ci20_mux_nand(void) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + + /* setup pins */ + writel(0x002c00ff, gpio_regs + GPIO_PXINTC(0)); + writel(0x002c00ff, gpio_regs + GPIO_PXMASKC(0)); + writel(0x002c00ff, gpio_regs + GPIO_PXPAT1C(0)); + writel(0x002c00ff, gpio_regs + GPIO_PXPAT0C(0)); + writel(0x002c00ff, gpio_regs + GPIO_PXPENS(0)); + writel(0x00000003, gpio_regs + GPIO_PXINTC(1)); + writel(0x00000003, gpio_regs + GPIO_PXMASKC(1)); + writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1)); + writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1)); + writel(0x00000003, gpio_regs + GPIO_PXPENS(1)); + + /* FRB0_N */ + gpio_direction_input(32 * 0 + 20); + writel(20, gpio_regs + GPIO_PXPENS(0)); + + /* disable write protect */ + gpio_direction_output(JZ_GPIO(5, 22), 1); +} + +static void ci20_mux_uart(void) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + + /* UART0 */ + writel(0x9, gpio_regs + GPIO_PXINTC(5)); + writel(0x9, gpio_regs + GPIO_PXMASKC(5)); + writel(0x9, gpio_regs + GPIO_PXPAT1C(5)); + writel(0x9, gpio_regs + GPIO_PXPAT0C(5)); + writel(0x9, gpio_regs + GPIO_PXPENC(5)); + jz4780_clk_ungate_uart(0); + + /* UART 1 and 2 */ + jz4780_clk_ungate_uart(1); + jz4780_clk_ungate_uart(2); + +#ifndef CONFIG_JTAG + /* UART3 */ + writel(1 << 12, gpio_regs + GPIO_PXINTC(3)); + writel(1 << 12, gpio_regs + GPIO_PXMASKS(3)); + writel(1 << 12, gpio_regs + GPIO_PXPAT1S(3)); + writel(1 << 12, gpio_regs + GPIO_PXPAT0C(3)); + writel(3 << 30, gpio_regs + GPIO_PXINTC(0)); + writel(3 << 30, gpio_regs + GPIO_PXMASKC(0)); + writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0)); + writel(1 << 30, gpio_regs + GPIO_PXPAT0C(0)); + writel(1 << 31, gpio_regs + GPIO_PXPAT0S(0)); + jz4780_clk_ungate_uart(3); +#endif + + /* UART4 */ + writel(0x100400, gpio_regs + GPIO_PXINTC(2)); + writel(0x100400, gpio_regs + GPIO_PXMASKC(2)); + writel(0x100400, gpio_regs + GPIO_PXPAT1S(2)); + writel(0x100400, gpio_regs + GPIO_PXPAT0C(2)); + writel(0x100400, gpio_regs + GPIO_PXPENC(2)); + jz4780_clk_ungate_uart(4); +} + +int board_early_init_f(void) +{ + ci20_mux_jtag(); + ci20_mux_uart(); + + ci20_mux_eth(); + ci20_mux_mmc(); + ci20_mux_nand(); + + /* SYS_POWER_IND high (LED blue, VBUS on) */ + gpio_direction_output(JZ_GPIO(5, 15), 1); + + /* LEDs off */ + gpio_direction_output(JZ_GPIO(2, 0), 0); + gpio_direction_output(JZ_GPIO(2, 1), 0); + gpio_direction_output(JZ_GPIO(2, 2), 0); + gpio_direction_output(JZ_GPIO(2, 3), 0); + + return 0; +} + +#ifndef CONFIG_SPL_BUILD +int misc_init_r(void) +{ + const u32 efuse_clk = jz4780_clk_get_efuse_clk(); + struct ci20_otp otp; + char manufacturer[3]; + + /* Read the board OTP data */ + jz4780_efuse_init(efuse_clk); + jz4780_efuse_read(0x18, 16, (u8 *)&otp); + + /* Set MAC address */ + if (!is_valid_ethaddr(otp.mac)) { + /* no MAC assigned, generate one from the unique chip ID */ + jz4780_efuse_read(0x8, 4, &otp.mac[0]); + jz4780_efuse_read(0x12, 2, &otp.mac[4]); + otp.mac[0] = (otp.mac[0] | 0x02) & ~0x01; + } + eth_env_set_enetaddr("ethaddr", otp.mac); + + /* Put other board information into the environment */ + env_set_ulong("serial#", otp.serial_number); + env_set_ulong("board_date", otp.date); + manufacturer[0] = otp.manufacturer[0]; + manufacturer[1] = otp.manufacturer[1]; + manufacturer[2] = 0; + env_set("board_mfr", manufacturer); + + return 0; +} + +#ifdef CONFIG_DRIVER_DM9000 +int board_eth_init(bd_t *bis) +{ + /* Enable clock */ + jz4780_clk_ungate_ethernet(); + + /* Enable power (PB25) */ + gpio_direction_output(JZ_GPIO(1, 25), 1); + + /* Reset (PF12) */ + mdelay(10); + gpio_direction_output(JZ_GPIO(5, 12), 0); + mdelay(10); + gpio_direction_output(JZ_GPIO(5, 12), 1); + mdelay(10); + + return dm9000_initialize(bis); +} +#endif /* CONFIG_DRIVER_DM9000 */ +#endif + +static u8 ci20_revision(void) +{ + void __iomem *gpio_regs = (void __iomem *)GPIO_BASE; + int val; + + gpio_direction_input(82); + gpio_direction_input(83); + + /* Enable pullups */ + writel(BIT(18) | BIT(19), gpio_regs + GPIO_PXPENC(2)); + + /* Read PC18/19 for version */ + val = (!!gpio_get_value(82)) | ((!!gpio_get_value(83)) << 1); + + if (val == 3) /* Rev 1 boards had no pulldowns - giving 3 */ + return 1; + if (val == 1) /* Rev 2 boards pulldown port C bit 18 giving 1 */ + return 2; + + return 0; +} + +int dram_init(void) +{ + gd->ram_size = sdram_size(0) + sdram_size(1); + return 0; +} + +/* U-Boot common routines */ +int checkboard(void) +{ + printf("Board: Creator CI20 (rev.%d)\n", ci20_revision()); + return 0; +} + +#ifdef CONFIG_SPL_BUILD + +#if defined(CONFIG_SPL_MMC_SUPPORT) +int board_mmc_init(bd_t *bd) +{ + ci20_mux_mmc(); + return jz_mmc_init((void __iomem *)MSC0_BASE); +} +#endif + +static const struct jz4780_ddr_config K4B2G0846Q_48_config = { + .timing = { + (4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) | + (6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT), + + + (4 << DDRC_TIMING2_TCCD_BIT) | (15 << DDRC_TIMING2_TRAS_BIT) | + (6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT), + + (4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) | + (6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) | + (21 << DDRC_TIMING3_TRC_BIT), + + (31 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) | + (4 << DDRC_TIMING4_TCKE_BIT) | (9 << DDRC_TIMING4_TMINSR_BIT) | + (8 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT), + + (8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) | + (4 << DDRC_TIMING5_TWDLAT_BIT), + + (25 << DDRC_TIMING6_TXSRD_BIT) | (12 << DDRC_TIMING6_TFAW_BIT) | + (2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT), + }, + + /* PHY */ + /* Mode Register 0 */ + .mr0 = 0x420, +#ifdef SDRAM_DISABLE_DLL + .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE), +#else + .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS), +#endif + + .ptr0 = 0x002000d4, + .ptr1 = 0x02230d40, + .ptr2 = 0x04013880, + + .dtpr0 = 0x2a8f6690, + .dtpr1 = 0x00400860, + .dtpr2 = 0x10042a00, + + .pullup = 0x0b, + .pulldn = 0x0b, +}; + +static const struct jz4780_ddr_config H5TQ2G83CFR_48_config = { + .timing = { + (4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) | + (6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT), + + (4 << DDRC_TIMING2_TCCD_BIT) | (16 << DDRC_TIMING2_TRAS_BIT) | + (6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT), + + (4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) | + (6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) | + (22 << DDRC_TIMING3_TRC_BIT), + + (42 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) | + (4 << DDRC_TIMING4_TCKE_BIT) | (7 << DDRC_TIMING4_TMINSR_BIT) | + (3 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT), + + (8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) | + (4 << DDRC_TIMING5_TWDLAT_BIT), + + (25 << DDRC_TIMING6_TXSRD_BIT) | (20 << DDRC_TIMING6_TFAW_BIT) | + (2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT), + }, + + /* PHY */ + /* Mode Register 0 */ + .mr0 = 0x420, +#ifdef SDRAM_DISABLE_DLL + .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE), +#else + .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS), +#endif + + .ptr0 = 0x002000d4, + .ptr1 = 0x02d30d40, + .ptr2 = 0x04013880, + + .dtpr0 = 0x2c906690, + .dtpr1 = 0x005608a0, + .dtpr2 = 0x10042a00, + + .pullup = 0x0e, + .pulldn = 0x0e, +}; + +#if (CONFIG_SYS_MHZ != 1200) +#error No DDR configuration for CPU speed +#endif + +const struct jz4780_ddr_config *jz4780_get_ddr_config(void) +{ + const int board_revision = ci20_revision(); + + if (board_revision == 2) + return &K4B2G0846Q_48_config; + else /* Fall back to H5TQ2G83CFR RAM */ + return &H5TQ2G83CFR_48_config; +} +#endif diff --git a/configs/ci20_defconfig b/configs/ci20_defconfig new file mode 100644 index 000000000000..df1a1846667e --- /dev/null +++ b/configs/ci20_defconfig @@ -0,0 +1,47 @@ +CONFIG_MIPS=y +CONFIG_SPL_LDSCRIPT="arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds" +CONFIG_SYS_TEXT_BASE=0x80010000 +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL=y +CONFIG_ARCH_JZ47XX=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_FIT=y +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyS4,115200 rw rootwait root=/dev/mmcblk0p1" +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="ext4load mmc 0:1 0x88000000 /boot/uImage; bootm 0x88000000" +CONFIG_DISPLAY_CPUINFO=y +CONFIG_BOARD_EARLY_INIT_F=y +# CONFIG_SPL_BANNER_PRINT is not set +# CONFIG_TPL_BANNER_PRINT is not set +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +# CONFIG_SPL_DOS_PARTITION is not set +CONFIG_OF_EMBED=y +CONFIG_DEFAULT_DEVICE_TREE="ci20" +CONFIG_ENV_IS_IN_MMC=y +# CONFIG_DM_WARN is not set +# CONFIG_DM_DEVICE_REMOVE is not set +CONFIG_JZ4780_EFUSE=y +CONFIG_MMC=y +CONFIG_MMC_BROKEN_CD=y +CONFIG_DM_MMC=y +# CONFIG_MMC_HW_PARTITIONING is not set +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_HS400_SUPPORT=y +# CONFIG_MMC_VERBOSE is not set +CONFIG_SPL_MMC_TINY=y +CONFIG_JZ47XX_MMC=y +CONFIG_DM_SERIAL=y +CONFIG_SYS_NS16550=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_LZO=y diff --git a/include/configs/ci20.h b/include/configs/ci20.h new file mode 100644 index 000000000000..e600f9dfe0c0 --- /dev/null +++ b/include/configs/ci20.h @@ -0,0 +1,74 @@ +/* + * CI20 configuration + * + * Copyright (c) 2013 Imagination Technologies + * Author: Paul Burton + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_CI20_H__ +#define __CONFIG_CI20_H__ + +#define CONFIG_SKIP_LOWLEVEL_INIT +#define CONFIG_MISC_INIT_R + +/* Ingenic JZ4780 clock configuration. */ +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_MHZ 1200 +#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) + +/* Memory configuration */ +#define CONFIG_SYS_MONITOR_LEN (512 * 1024) +#define CONFIG_SYS_MALLOC_LEN (64 * 1024 * 1024) +#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024) + +#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* cached (KSEG0) address */ +#define CONFIG_SYS_INIT_SP_OFFSET 0x400000 +#define CONFIG_SYS_LOAD_ADDR 0x81000000 +#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR +#define CONFIG_SYS_MEMTEST_START 0x80000000 +#define CONFIG_SYS_MEMTEST_END 0x88000000 + +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE + +/* NS16550-ish UARTs */ +#define CONFIG_SYS_NS16550_CLK 48000000 +#define CONFIG_SYS_CONSOLE_IS_IN_ENV + +/* Ethernet: davicom DM9000 */ +#define CONFIG_DRIVER_DM9000 1 +#define CONFIG_DM9000_BASE 0xb6000000 +#define DM9000_IO CONFIG_DM9000_BASE +#define DM9000_DATA (CONFIG_DM9000_BASE + 2) + +/* Environment */ +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_ENV_SIZE (32 << 10) +#define CONFIG_ENV_OFFSET ((14 + 512) << 10) +#define CONFIG_ENV_OVERWRITE + +/* Command line configuration. */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O buffer size */ +#define CONFIG_SYS_MAXARGS 32 /* Max number of command args */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + /* Boot argument buffer size */ +#define CONFIG_VERSION_VARIABLE /* U-BOOT version */ + +/* Miscellaneous configuration options */ +#define CONFIG_SYS_BOOTM_LEN (64 << 20) + +/* SPL */ +#define CONFIG_SPL_STACK 0xf4008000 /* only max. 2KB spare! */ + +#define CONFIG_SPL_TEXT_BASE 0xf4000a00 +#define CONFIG_SPL_MAX_SIZE ((14 * 1024) - 0xa00) + +#define CONFIG_SPL_BSS_START_ADDR 0xf4004000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x00002000 /* 512KB, arbitrary */ + +#define CONFIG_SPL_START_S_PATH "arch/mips/mach-jz47xx" + +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x1c /* 14 KiB offset */ + +#endif /* __CONFIG_CI20_H__ */