From aefbc2c2a2bb2c3b0d31a97397dba255c46d20f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 26 Feb 2021 10:30:19 +0100 Subject: [PATCH 01/17] rtc: add armada38x driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add RTC driver for Armada 38x, based on Linux' driver. For now implement only `marvell,armada-380-rtc` compatible. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese Cc: Pali Rohár Cc: Baruch Siach Cc: Chris Packham Cc: Simon Glass Acked-by: Pali Rohár --- drivers/rtc/Kconfig | 7 ++ drivers/rtc/Makefile | 1 + drivers/rtc/armada38x.c | 184 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 drivers/rtc/armada38x.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index aa6d90158c..dafba35279 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -38,6 +38,13 @@ config RTC_ENABLE_32KHZ_OUTPUT Some real-time clocks support the output of 32kHz square waves (such as ds3231), the config symbol choose Real Time Clock device 32Khz output feature. +config RTC_ARMADA38X + bool "Enable Armada 38x Marvell SoC RTC" + depends on DM_RTC && ARCH_MVEBU + help + This adds support for the in-chip RTC that can be found in the + Armada 38x Marvell's SoC devices. + config RTC_PCF2127 bool "Enable PCF2127 driver" depends on DM_RTC diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6a45a9c874..15609e7b18 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_$(SPL_TPL_)DM_RTC) += rtc-uclass.o obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o obj-y += rtc-lib.o +obj-$(CONFIG_RTC_ARMADA38X) += armada38x.o obj-$(CONFIG_RTC_DAVINCI) += davinci.o obj-$(CONFIG_RTC_DS1302) += ds1302.o obj-$(CONFIG_RTC_DS1306) += ds1306.o diff --git a/drivers/rtc/armada38x.c b/drivers/rtc/armada38x.c new file mode 100644 index 0000000000..2d264acf77 --- /dev/null +++ b/drivers/rtc/armada38x.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * RTC driver for the Armada 38x Marvell SoCs + * + * Copyright (C) 2021 Marek Behun + * + * Based on Linux' driver by Gregory Clement and Marvell + */ + +#include +#include +#include +#include + +#define RTC_STATUS 0x0 +#define RTC_TIME 0xC +#define RTC_CONF_TEST 0x1C + +/* Armada38x SoC registers */ +#define RTC_38X_BRIDGE_TIMING_CTL 0x0 +#define RTC_38X_PERIOD_OFFS 0 +#define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS) +#define RTC_38X_READ_DELAY_OFFS 26 +#define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS) + +#define SAMPLE_NR 100 + +struct armada38x_rtc { + void __iomem *regs; + void __iomem *regs_soc; +}; + +/* + * According to Erratum RES-3124064 we have to do some configuration in MBUS. + * To read an RTC register we need to read it 100 times and return the most + * frequent value. + * To write an RTC register we need to write 2x zero into STATUS register, + * followed by the proper write. Linux adds an 5 us delay after this, so we do + * it here as well. + */ +static void update_38x_mbus_timing_params(struct armada38x_rtc *rtc) +{ + u32 reg; + + reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); + reg &= ~RTC_38X_PERIOD_MASK; + reg |= 0x3FF << RTC_38X_PERIOD_OFFS; /* Maximum value */ + reg &= ~RTC_38X_READ_DELAY_MASK; + reg |= 0x1F << RTC_38X_READ_DELAY_OFFS; /* Maximum value */ + writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL); +} + +static void armada38x_rtc_write(u32 val, struct armada38x_rtc *rtc, u8 reg) +{ + writel(0, rtc->regs + RTC_STATUS); + writel(0, rtc->regs + RTC_STATUS); + writel(val, rtc->regs + reg); + udelay(5); +} + +static u32 armada38x_rtc_read(struct armada38x_rtc *rtc, u8 reg) +{ + u8 counts[SAMPLE_NR], max_idx; + u32 samples[SAMPLE_NR], max; + int i, j, last; + + for (i = 0, last = 0; i < SAMPLE_NR; ++i) { + u32 sample = readl(rtc->regs + reg); + + /* find if this value was already read */ + for (j = 0; j < last; ++j) { + if (samples[j] == sample) + break; + } + + if (j < last) { + /* if yes, increment count */ + ++counts[j]; + } else { + /* if not, add */ + samples[last] = sample; + counts[last] = 1; + ++last; + } + } + + /* finally find the sample that was read the most */ + max = 0; + max_idx = 0; + + for (i = 0; i < last; ++i) { + if (counts[i] > max) { + max = counts[i]; + max_idx = i; + } + } + + return samples[max_idx]; +} + +static int armada38x_rtc_get(struct udevice *dev, struct rtc_time *tm) +{ + struct armada38x_rtc *rtc = dev_get_priv(dev); + u32 time; + + time = armada38x_rtc_read(rtc, RTC_TIME); + + rtc_to_tm(time, tm); + + return 0; +} + +static int armada38x_rtc_reset(struct udevice *dev) +{ + struct armada38x_rtc *rtc = dev_get_priv(dev); + u32 reg; + + reg = armada38x_rtc_read(rtc, RTC_CONF_TEST); + + if (reg & 0xff) { + armada38x_rtc_write(0, rtc, RTC_CONF_TEST); + mdelay(500); + armada38x_rtc_write(0, rtc, RTC_TIME); + armada38x_rtc_write(BIT(0) | BIT(1), 0, RTC_STATUS); + } + + return 0; +} + +static int armada38x_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + struct armada38x_rtc *rtc = dev_get_priv(dev); + unsigned long time; + + time = rtc_mktime(tm); + + if (time > U32_MAX) + printf("%s: requested time to set will overflow\n", dev->name); + + armada38x_rtc_reset(dev); + armada38x_rtc_write(time, rtc, RTC_TIME); + + return 0; +} + +static int armada38x_probe(struct udevice *dev) +{ + struct armada38x_rtc *rtc = dev_get_priv(dev); + + rtc->regs = dev_remap_addr_name(dev, "rtc"); + if (!rtc->regs) + goto err; + + rtc->regs_soc = dev_remap_addr_name(dev, "rtc-soc"); + if (!rtc->regs_soc) + goto err; + + update_38x_mbus_timing_params(rtc); + + return 0; +err: + printf("%s: io address missing\n", dev->name); + return -ENODEV; +} + +static const struct rtc_ops armada38x_rtc_ops = { + .get = armada38x_rtc_get, + .set = armada38x_rtc_set, + .reset = armada38x_rtc_reset, +}; + +static const struct udevice_id armada38x_rtc_ids[] = { + { .compatible = "marvell,armada-380-rtc", .data = 0 }, + { } +}; + +U_BOOT_DRIVER(rtc_armada38x) = { + .name = "rtc-armada38x", + .id = UCLASS_RTC, + .of_match = armada38x_rtc_ids, + .probe = armada38x_probe, + .priv_auto = sizeof(struct armada38x_rtc), + .ops = &armada38x_rtc_ops, +}; From 1972d58e9765c9fc75cf1e1317bc5f522f0e45ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 26 Feb 2021 10:30:20 +0100 Subject: [PATCH 02/17] arm: mvebu: turris_omnia: Enable DM_RTC and RTC_ARMADA38X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this the date command is available on Turris Omnia. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese Cc: Pali Rohár Acked-by: Pali Rohár --- configs/turris_omnia_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 4b8843d7be..810eacefc2 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -73,6 +73,8 @@ CONFIG_MII=y CONFIG_PCI=y CONFIG_PCI_MVEBU=y CONFIG_SCSI=y +CONFIG_DM_RTC=y +CONFIG_RTC_ARMADA38X=y CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550=y CONFIG_KIRKWOOD_SPI=y From 33691d9c8238b4f349b8b878f5ee3288ab309f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 26 Feb 2021 10:30:21 +0100 Subject: [PATCH 03/17] arm: mvebu: turris_omnia: Enable CMD_WDT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This command can be sometimes used for debugging. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese Cc: Pali Rohár Acked-by: Pali Rohár --- configs/turris_omnia_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 810eacefc2..295f05f3b3 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -46,6 +46,7 @@ CONFIG_CMD_SATA=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_WDT=y CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y CONFIG_CMD_AES=y From d86609baab3dc2585bfbd2245a0fa56b6e703798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 26 Feb 2021 10:30:22 +0100 Subject: [PATCH 04/17] arm: mvebu: turris_omnia: Enable CMD_FS_UUID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This command can be useful for U-Boot scripts. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese Cc: Pali Rohár Acked-by: Pali Rohár --- configs/turris_omnia_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 295f05f3b3..a8218da1a0 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -52,6 +52,7 @@ CONFIG_CMD_TIME=y CONFIG_CMD_AES=y CONFIG_CMD_HASH=y CONFIG_CMD_BTRFS=y +CONFIG_CMD_FS_UUID=y # CONFIG_SPL_PARTITION_UUIDS is not set CONFIG_ENV_OVERWRITE=y CONFIG_USE_ENV_SPI_MAX_HZ=y From 08511d129ee7d3f40d1d06bec64c4805cc80733c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 3 Mar 2021 01:55:22 +0100 Subject: [PATCH 05/17] arm: mvebu: ds414: Add a Kconfig defining some strings A rather cosmetic change to conform with other board definitions. Signed-off-by: Phil Sutter Reviewed-by: Stefan Roese --- board/Synology/ds414/Kconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 board/Synology/ds414/Kconfig diff --git a/board/Synology/ds414/Kconfig b/board/Synology/ds414/Kconfig new file mode 100644 index 0000000000..4d30852554 --- /dev/null +++ b/board/Synology/ds414/Kconfig @@ -0,0 +1,12 @@ +if TARGET_DS414 + +config SYS_BOARD + default "ds414" + +config SYS_VENDOR + default "Synology" + +config SYS_CONFIG_NAME + default "ds414" + +endif From c57f92050429779ae04357f88e1c7e5d02c6d315 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 7 Mar 2021 22:21:23 +0100 Subject: [PATCH 06/17] arm: mvebu: configs: ds414: Enable XHCI_PCI by default With the recent fixes in pci_mvebu and xhci-pci drivers, the two rear USB3 ports are finally usable and accessing them no longer hangs the system. Signed-off-by: Phil Sutter Reviewed-by: Stefan Roese --- configs/ds414_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 3e6dcec3ed..412559256e 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -65,5 +65,8 @@ CONFIG_SYS_NS16550=y CONFIG_KIRKWOOD_SPI=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_MVEBU is not set +CONFIG_USB_XHCI_PCI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y From e471ddf0f3472423e8cdf8cc7d06a0b8e2abfebc Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 7 Mar 2021 22:22:27 +0100 Subject: [PATCH 07/17] arm: mvebu: board/Synology: Unify legacy kernel support Move the relevant bits from ds109.{c,h} into common/ and adjust the code to fit both DS109 and DS414. Moreover: * Introduce syno_board_id() which translates CONFIG_MACH_TYPE into the expected board ID tag value. * Properly initialize isusbhost, mac and mtu fields from env variables. * Set the right bootargs/bootcmd to correctly boot legacy kernel out of the (DS414) box. Getting the ramdisk location right is a bit tedious. Cc: Walter Schweizer Signed-off-by: Phil Sutter Reviewed-by: Stefan Roese --- board/Synology/common/Makefile | 5 +++ board/Synology/common/legacy.c | 76 ++++++++++++++++++++++++++++++++++ board/Synology/common/legacy.h | 33 +++++++++++++++ board/Synology/ds109/ds109.c | 32 -------------- board/Synology/ds109/ds109.h | 17 -------- configs/ds414_defconfig | 5 +-- include/configs/ds109.h | 3 +- include/configs/ds414.h | 15 ++++++- 8 files changed, 132 insertions(+), 54 deletions(-) create mode 100644 board/Synology/common/Makefile create mode 100644 board/Synology/common/legacy.c create mode 100644 board/Synology/common/legacy.h diff --git a/board/Synology/common/Makefile b/board/Synology/common/Makefile new file mode 100644 index 0000000000..62354cc2e8 --- /dev/null +++ b/board/Synology/common/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2021 Phil Sutter + +obj-y += legacy.o diff --git a/board/Synology/common/legacy.c b/board/Synology/common/legacy.c new file mode 100644 index 0000000000..3c89e92ae7 --- /dev/null +++ b/board/Synology/common/legacy.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 + * Walter Schweizer + * Phil Sutter + */ + +#include +#include +#include +#include +#include + +#include "legacy.h" + +static unsigned int syno_board_id(void) +{ + switch (CONFIG_MACH_TYPE) { + case 527: + return SYNO_DS109_ID; + case 3036: + return SYNO_AXP_4BAY_2BAY; + default: + return 0; + } +} + +static unsigned int usb_port_modes(void) +{ + unsigned int i, ret = 0; + char var[32], *val; + + for (i = 0; i < USBPORT_MAX; i++) { + snprintf(var, 32, "usb%dMode", i); + val = env_get(var); + + if (!val || strcasecmp(val, "host")) + continue; + + ret |= 1 << i; + } + return ret; +} + +/* Support old kernels */ +void setup_board_tags(struct tag **in_params) +{ + struct tag_mv_uboot *t; + struct tag *params; + int i; + + debug("Synology board tags...\n"); + + params = *in_params; + t = (struct tag_mv_uboot *)¶ms->u; + + t->uboot_version = VER_NUM | syno_board_id(); + t->tclk = CONFIG_SYS_TCLK; + t->sysclk = CONFIG_SYS_TCLK * 2; + t->isusbhost = usb_port_modes(); + + for (i = 0; i < ETHADDR_MAX; i++) { + char addrvar[16], mtuvar[16]; + + sprintf(addrvar, i ? "eth%daddr" : "ethaddr", i); + sprintf(mtuvar, i ? "eth%dmtu" : "ethmtu", i); + + eth_env_get_enetaddr(addrvar, t->macaddr[i]); + t->mtu[i] = env_get_ulong(mtuvar, 10, 0); + } + + params->hdr.tag = ATAG_MV_UBOOT; + params->hdr.size = tag_size(tag_mv_uboot); + params = tag_next(params); + *in_params = params; +} diff --git a/board/Synology/common/legacy.h b/board/Synology/common/legacy.h new file mode 100644 index 0000000000..0a814324d0 --- /dev/null +++ b/board/Synology/common/legacy.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2021 + * Walter Schweizer + * Phil Sutter + */ + +#ifndef __SYNO_LEGACY_H +#define __SYNO_LEGACY_H + +/* Marvell uboot parameters */ +#define ATAG_MV_UBOOT 0x41000403 +#define VER_NUM 0x03040400 /* 3.4.4 */ + +#define BOARD_ID_BASE 0x0 +#define SYNO_DS109_ID (BOARD_ID_BASE + 0x15) +#define SYNO_AXP_4BAY_2BAY (0xf + 1) + +#define ETHADDR_MAX 4 +#define USBPORT_MAX 3 + +struct tag_mv_uboot { + u32 uboot_version; + u32 tclk; + u32 sysclk; + u32 isusbhost; + u8 macaddr[ETHADDR_MAX][ETH_ALEN]; + u16 mtu[ETHADDR_MAX]; + u32 fw_image_base; + u32 fw_image_size; +}; + +#endif /* __SYNO_LEGACY_H */ diff --git a/board/Synology/ds109/ds109.c b/board/Synology/ds109/ds109.c index eaac95460c..3914faaf37 100644 --- a/board/Synology/ds109/ds109.c +++ b/board/Synology/ds109/ds109.c @@ -114,38 +114,6 @@ void reset_misc(void) SOFTWARE_REBOOT); } -/* Support old kernels */ -void setup_board_tags(struct tag **in_params) -{ - unsigned int boardId; - struct tag *params; - struct tag_mv_uboot *t; - int i; - - printf("Synology board tags..."); - params = *in_params; - t = (struct tag_mv_uboot *)¶ms->u; - - t->uboot_version = VER_NUM; - - boardId = SYNO_DS109_ID; - t->uboot_version |= boardId; - - t->tclk = CONFIG_SYS_TCLK; - t->sysclk = CONFIG_SYS_TCLK*2; - - t->isusbhost = 1; - for (i = 0; i < 4; i++) { - memset(t->macaddr[i], 0, sizeof(t->macaddr[i])); - t->mtu[i] = 0; - } - - params->hdr.tag = ATAG_MV_UBOOT; - params->hdr.size = tag_size(tag_mv_uboot); - params = tag_next(params); - *in_params = params; -} - #ifdef CONFIG_RESET_PHY_R /* Configure and enable MV88E1116 PHY */ void reset_phy(void) diff --git a/board/Synology/ds109/ds109.h b/board/Synology/ds109/ds109.h index cc6ef991f3..0cf05257c8 100644 --- a/board/Synology/ds109/ds109.h +++ b/board/Synology/ds109/ds109.h @@ -23,21 +23,4 @@ #define MV88E1116_RGMII_TXTM_CTRL (1 << 4) #define MV88E1116_RGMII_RXTM_CTRL (1 << 5) -/* Marvell uboot parameters */ -#define ATAG_MV_UBOOT 0x41000403 -#define VER_NUM 0x03040400 /* 3.4.4 */ -#define BOARD_ID_BASE 0x0 -#define SYNO_DS109_ID (BOARD_ID_BASE+0x15) - -struct tag_mv_uboot { - u32 uboot_version; - u32 tclk; - u32 sysclk; - u32 isusbhost; - char macaddr[4][6]; - u16 mtu[4]; - u32 fw_image_base; - u32 fw_image_size; -}; - #endif /* __DS109_H */ diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 412559256e..8ef2e79dc9 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -20,9 +20,8 @@ CONFIG_DEFAULT_DEVICE_TREE="armada-xp-synology-ds414" CONFIG_DEBUG_UART=y CONFIG_BOOTDELAY=3 CONFIG_USE_BOOTARGS=y -CONFIG_BOOTARGS="console=ttyS0,115200" -CONFIG_USE_PREBOOT=y -CONFIG_PREBOOT="usb start; sf probe" +CONFIG_BOOTARGS="console=ttyS0,115200 ip=off initrd=0x8000040,8M root=/dev/md0 rw syno_hw_version=DS414r1 ihd_num=4 netif_num=2 flash_size=8 SataLedSpecial=1 HddHotplug=1" +# CONFIG_USE_PREBOOT is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_I2C_SUPPORT=y diff --git a/include/configs/ds109.h b/include/configs/ds109.h index 1f033ababf..35d85361b4 100644 --- a/include/configs/ds109.h +++ b/include/configs/ds109.h @@ -44,7 +44,8 @@ "x_bootcmd_kernel=fatload usb 0 0x6400000 uImage\0" \ "x_bootargs=console=ttyS0,115200\0" \ "x_bootargs_root=root=/dev/sda2 rootdelay=10\0" \ - "ipaddr=192.168.1.5\0" + "ipaddr=192.168.1.5\0" \ + "usb0Mode=host\0" /* * Ethernet Driver configuration diff --git a/include/configs/ds414.h b/include/configs/ds414.h index 8aa2d47bec..a2248cf75a 100644 --- a/include/configs/ds414.h +++ b/include/configs/ds414.h @@ -6,6 +6,9 @@ #ifndef _CONFIG_SYNOLOGY_DS414_H #define _CONFIG_SYNOLOGY_DS414_H +/* Vendor kernel expects this MACH_TYPE */ +#define CONFIG_MACH_TYPE 3036 + /* * High Level Configuration Options (easy to change) */ @@ -74,8 +77,18 @@ #define CONFIG_DDR_32BIT /* Default Environment */ -#define CONFIG_BOOTCOMMAND "sf read ${loadaddr} 0xd0000 0x700000; bootm" #define CONFIG_LOADADDR 0x80000 +#define CONFIG_BOOTCOMMAND \ + "sf probe; " \ + "sf read ${loadaddr} 0xd0000 0x2d0000; " \ + "sf read ${ramdisk_addr_r} 0x3a0000 0x430000; " \ + "bootm ${loadaddr} ${ramdisk_addr_r}" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "initrd_high=0xffffffff\0" \ + "ramdisk_addr_r=0x8000000\0" \ + "usb0Mode=host\0usb1Mode=host\0usb2Mode=device\0" \ + "ethmtu=1500\0eth1mtu=1500\0" /* increase autoneg timeout, my NIC sucks */ #define PHY_ANEG_TIMEOUT 16000 From a770159f88214846a66c7d7b6ee894de428e8fae Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 5 Mar 2021 21:05:11 +0100 Subject: [PATCH 08/17] arm: mvebu: ds414: Auto-populate env if appropriate Define a misc_init_r() which calls "syno populate_env" if the environment seems incomplete (or default), indicated by missing "ethaddr" variable. With this in place, no random MAC address fallback is needed anymore. Signed-off-by: Phil Sutter --- board/Synology/ds414/cmd_syno.c | 9 +++------ board/Synology/ds414/cmd_syno.h | 17 +++++++++++++++++ board/Synology/ds414/ds414.c | 11 +++++++++++ configs/ds414_defconfig | 2 +- 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 board/Synology/ds414/cmd_syno.h diff --git a/board/Synology/ds414/cmd_syno.c b/board/Synology/ds414/cmd_syno.c index a120c3123f..a62658a2eb 100644 --- a/board/Synology/ds414/cmd_syno.c +++ b/board/Synology/ds414/cmd_syno.c @@ -17,12 +17,9 @@ #include #include "../drivers/ddr/marvell/axp/ddr3_init.h" -#define ETHADDR_MAX 4 -#define SYNO_SN_TAG "SN=" -#define SYNO_CHKSUM_TAG "CHK=" +#include "cmd_syno.h" - -static int do_syno_populate(int argc, char *const argv[]) +int do_syno_populate(int argc, char *const argv[]) { unsigned int bus = CONFIG_SF_DEFAULT_BUS; unsigned int cs = CONFIG_SF_DEFAULT_CS; @@ -57,7 +54,7 @@ static int do_syno_populate(int argc, char *const argv[]) goto out_unmap; } - for (n = 0; n < ETHADDR_MAX; n++) { + for (n = 0; n < SYNO_ETHADDR_MAX; n++) { char ethaddr[ETH_ALEN]; int i, sum = 0; unsigned char csum = 0; diff --git a/board/Synology/ds414/cmd_syno.h b/board/Synology/ds414/cmd_syno.h new file mode 100644 index 0000000000..42e435c803 --- /dev/null +++ b/board/Synology/ds414/cmd_syno.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Commands to deal with Synology specifics. + * + * Copyright (C) 2021 Phil Sutter + */ + +#ifndef _CMD_SYNO_H +#define _CMD_SYNO_H + +#define SYNO_ETHADDR_MAX 4 +#define SYNO_SN_TAG "SN=" +#define SYNO_CHKSUM_TAG "CHK=" + +int do_syno_populate(int argc, char *const argv[]); + +#endif /* _CMD_SYNO_H */ diff --git a/board/Synology/ds414/ds414.c b/board/Synology/ds414/ds414.c index 9c4ce670dd..abe6f9eb5e 100644 --- a/board/Synology/ds414/ds414.c +++ b/board/Synology/ds414/ds414.c @@ -18,6 +18,8 @@ #include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h" #include "../arch/arm/mach-mvebu/serdes/axp/board_env_spec.h" +#include "cmd_syno.h" + DECLARE_GLOBAL_DATA_PTR; /* GPP and MPP settings as found in mvBoardEnvSpec.c of Synology's U-Boot */ @@ -179,6 +181,15 @@ int board_init(void) return 0; } +int misc_init_r(void) +{ + if (!env_get("ethaddr")) { + puts("Incomplete environment, populating from SPI flash\n"); + do_syno_populate(0, NULL); + } + return 0; +} + int checkboard(void) { puts("Board: DS414\n"); diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 8ef2e79dc9..e1c0f693f3 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -24,6 +24,7 @@ CONFIG_BOOTARGS="console=ttyS0,115200 ip=off initrd=0x8000040,8M root=/dev/md0 r # CONFIG_USE_PREBOOT is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_MISC_INIT_R=y CONFIG_SPL_I2C_SUPPORT=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_I2C=y @@ -46,7 +47,6 @@ CONFIG_ENV_OVERWRITE=y CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_SYS_RELOC_GD_ENV_ADDR=y -CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_BLK=y # CONFIG_MMC is not set From a751f83bb2fd17ed200073c2dd99d6fc579aab98 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 5 Mar 2021 21:05:45 +0100 Subject: [PATCH 09/17] arm: mvebu: ds414: Add sample u-boot update command Call 'run update_uboot' to fetch u-boot-spl.kwb via TFTP and write it into the correct SPI flash location. The latter's size is defined in DS414's DTB file, so hard-coding it should be acceptable here. Take care to not append garbage from RAM to the written image and to stay within assigned flash boundaries even if an oversized image was fetched. Signed-off-by: Phil Sutter --- include/configs/ds414.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/configs/ds414.h b/include/configs/ds414.h index a2248cf75a..c8b45066cc 100644 --- a/include/configs/ds414.h +++ b/include/configs/ds414.h @@ -88,7 +88,12 @@ "initrd_high=0xffffffff\0" \ "ramdisk_addr_r=0x8000000\0" \ "usb0Mode=host\0usb1Mode=host\0usb2Mode=device\0" \ - "ethmtu=1500\0eth1mtu=1500\0" + "ethmtu=1500\0eth1mtu=1500\0" \ + "update_uboot=sf probe; dhcp; " \ + "mw.b ${loadaddr} 0x0 0xd0000; " \ + "tftpboot ${loadaddr} u-boot-spl.kwb; " \ + "sf update ${loadaddr} 0x0 0xd0000\0" + /* increase autoneg timeout, my NIC sucks */ #define PHY_ANEG_TIMEOUT 16000 From 16acff8cfcff51edc987572bfe937d1ae36be444 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:35 +0200 Subject: [PATCH 10/17] configs: remove unused CONFIG_SYS_MMC_BASE defs These boards use an MMC driver that does not use this definition Signed-off-by: Harm Berntsen Reviewed-by: Stefan Roese CC: Stefan Roese CC: Mario Six CC: Dennis Gilmore --- include/configs/clearfog.h | 5 ----- include/configs/controlcenterdc.h | 5 ----- include/configs/db-88f6820-gp.h | 5 ----- include/configs/helios4.h | 5 ----- 4 files changed, 20 deletions(-) diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h index 5441da8c9c..c9852a72b9 100644 --- a/include/configs/clearfog.h +++ b/include/configs/clearfog.h @@ -19,11 +19,6 @@ */ #define CONFIG_SYS_TCLK 250000000 /* 250MHz */ -/* - * SDIO/MMC Card Configuration - */ -#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE - /* USB/EHCI configuration */ #define CONFIG_EHCI_IS_TDI diff --git a/include/configs/controlcenterdc.h b/include/configs/controlcenterdc.h index f53d48d427..869b94bc9b 100644 --- a/include/configs/controlcenterdc.h +++ b/include/configs/controlcenterdc.h @@ -24,11 +24,6 @@ #define CONFIG_LOADADDR 1000000 -/* - * SDIO/MMC Card Configuration - */ -#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE - /* * SATA/SCSI/AHCI configuration */ diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index d4207be1d3..ed851bc670 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -19,11 +19,6 @@ #define CONFIG_SYS_I2C_SLAVE 0x0 #define CONFIG_SYS_I2C_SPEED 100000 -/* - * SDIO/MMC Card Configuration - */ -#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE - /* * SATA/SCSI/AHCI configuration */ diff --git a/include/configs/helios4.h b/include/configs/helios4.h index 396870a67f..2cda05c85a 100644 --- a/include/configs/helios4.h +++ b/include/configs/helios4.h @@ -19,11 +19,6 @@ */ #define CONFIG_SYS_TCLK 250000000 /* 250MHz */ -/* - * SDIO/MMC Card Configuration - */ -#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE - /* USB/EHCI configuration */ #define CONFIG_EHCI_IS_TDI From 90534ea56e059e89e40d5030c07a3089dede156e Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:36 +0200 Subject: [PATCH 11/17] configs: openrd: remove non-dm MMC driver Unfortunately this board has no DM support at all. We are also way past the deadline for driver model support for various devices on this board. Signed-off-by: Harm Berntsen Reviewed-by: Stefan Roese CC: Stefan Roese --- include/configs/openrd.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/configs/openrd.h b/include/configs/openrd.h index e9fd0fc749..03b9393c9b 100644 --- a/include/configs/openrd.h +++ b/include/configs/openrd.h @@ -74,9 +74,4 @@ #define CONFIG_SYS_ATA_IDE1_OFFSET MV_SATA_PORT1_OFFSET #endif /*CONFIG_MVSATA_IDE*/ -#ifdef CONFIG_CMD_MMC -#define CONFIG_MVEBU_MMC -#define CONFIG_SYS_MMC_BASE KW_SDIO_BASE -#endif /* CONFIG_CMD_MMC */ - #endif /* _CONFIG_OPENRD_BASE_H */ From 426948df2a23a1b4d5c2df2bf2c13ddc3989f823 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:37 +0200 Subject: [PATCH 12/17] configs: sheevaplug: remove non-dm MMC driver This will be replaced with the driver model version Signed-off-by: Harm Berntsen Reviewed-by: Stefan Roese CC: Prafulla Wadaskar CC: Stefan Roese CC: Tom Rini --- include/configs/sheevaplug.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h index e1f8fb8ac8..abe8418984 100644 --- a/include/configs/sheevaplug.h +++ b/include/configs/sheevaplug.h @@ -50,14 +50,6 @@ #define CONFIG_PHY_BASE_ADR 0 #endif /* CONFIG_CMD_NET */ -/* - * SDIO/MMC Card Configuration - */ -#ifdef CONFIG_CMD_MMC -#define CONFIG_MVEBU_MMC -#define CONFIG_SYS_MMC_BASE KW_SDIO_BASE -#endif /* CONFIG_CMD_MMC */ - /* * SATA driver configuration */ From af1ecc592586565ffbdf2037f18c439c7eb90b9b Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:38 +0200 Subject: [PATCH 13/17] arm: kirkwood: remove non-dm MMC driver init No board uses this driver any more: remove it. Signed-off-by: Harm Berntsen Reviewed-by: Stefan Roese CC: Gerald Kerma CC: Stefan Roese CC: Pantelis Antoniou --- arch/arm/mach-kirkwood/cpu.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm/mach-kirkwood/cpu.c b/arch/arm/mach-kirkwood/cpu.c index 9c818fa45e..339ae7fd20 100644 --- a/arch/arm/mach-kirkwood/cpu.c +++ b/arch/arm/mach-kirkwood/cpu.c @@ -279,10 +279,3 @@ int cpu_eth_init(struct bd_info *bis) } #endif -#ifdef CONFIG_MVEBU_MMC -int board_mmc_init(struct bd_info *bis) -{ - mvebu_mmc_init(bis); - return 0; -} -#endif /* CONFIG_MVEBU_MMC */ From 594412c79e486ae997406f13d7a3b0181d2dce8a Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:39 +0200 Subject: [PATCH 14/17] configs: remove obsolete CONFIG_SYS_MMC_BASE All usages of this have been removed Signed-off-by: Harm Berntsen Reviewed-by: Simon Glass CC: Simon Glass --- scripts/config_whitelist.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index b693925d20..6d77564b50 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -2906,7 +2906,6 @@ CONFIG_SYS_MIPS_TIMER_FREQ CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR -CONFIG_SYS_MMC_BASE CONFIG_SYS_MMC_CD_PIN CONFIG_SYS_MMC_CLK_OD CONFIG_SYS_MMC_MAX_BLK_COUNT From 4a8eac62456d2125785e820f9c0a6d58a8b7fd32 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:40 +0200 Subject: [PATCH 15/17] configs: remove obsolete CONFIG_MVEBU_MMC All usages of this have been removed Signed-off-by: Harm Berntsen Reviewed-by: Simon Glass CC: Simon Glass Reviewed-by: Stefan Roese --- scripts/config_whitelist.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 6d77564b50..6859d17654 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1076,7 +1076,6 @@ CONFIG_MTD_UBI_GLUEBI CONFIG_MTD_UBI_MODULE CONFIG_MULTI_CS CONFIG_MUSB_HOST -CONFIG_MVEBU_MMC CONFIG_MVGBE_PORTS CONFIG_MVMFP_V2 CONFIG_MVS From c689ae044bf7dc22811a37818988a4533699a541 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:41 +0200 Subject: [PATCH 16/17] mmc: mvebu: convert to driver model This is a straightforward conversion of the old, non-dm driver. It was done in-place as the deadline for non-dm MMC has passed. Previous commits ensured that no board depends on the old, non-dm variant. Tested on a Kirkwood based board with eMMC. Signed-off-by: Harm Berntsen Tested-by: Harm Berntsen Reviewed-by: Simon Glass Reviewed-by: Stefan Roese CC: Pantelis Antoniou CC: Stefan Roese CC: Gerald Kerma CC: Simon Glass Reviewed-by: Jaehoon Chung --- drivers/mmc/Kconfig | 9 ++ drivers/mmc/mvebu_mmc.c | 309 +++++++++++++++++++++++----------------- include/mvebu_mmc.h | 13 +- 3 files changed, 194 insertions(+), 137 deletions(-) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 492567575e..197aa82040 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -327,6 +327,15 @@ config MMC_OCTEONTX If unsure, say N. +config MVEBU_MMC + bool "Kirkwood MMC controller support" + depends on DM_MMC && BLK && ARCH_KIRKWOOD + help + Support for MMC host controller on Kirkwood SoCs. + If you are on a Kirkwood architecture, say Y here. + + If unsure, say N. + config PXA_MMC_GENERIC bool "Support for MMC controllers on PXA" help diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c index 8ec1f57a1b..fea55c61ed 100644 --- a/drivers/mmc/mvebu_mmc.c +++ b/drivers/mmc/mvebu_mmc.c @@ -11,60 +11,67 @@ #include #include #include +#include +#include #include #include -#include #include #include #include #include - -DECLARE_GLOBAL_DATA_PTR; - -#define DRIVER_NAME "MVEBU_MMC" +#include #define MVEBU_TARGET_DRAM 0 #define TIMEOUT_DELAY 5*CONFIG_SYS_HZ /* wait 5 seconds */ -static void mvebu_mmc_write(u32 offs, u32 val) +static inline void *get_regbase(const struct mmc *mmc) { - writel(val, CONFIG_SYS_MMC_BASE + (offs)); + struct mvebu_mmc_plat *pdata = mmc->priv; + + return pdata->iobase; } -static u32 mvebu_mmc_read(u32 offs) +static void mvebu_mmc_write(const struct mmc *mmc, u32 offs, u32 val) { - return readl(CONFIG_SYS_MMC_BASE + (offs)); + writel(val, get_regbase(mmc) + (offs)); } -static int mvebu_mmc_setup_data(struct mmc_data *data) +static u32 mvebu_mmc_read(const struct mmc *mmc, u32 offs) { + return readl(get_regbase(mmc) + (offs)); +} + +static int mvebu_mmc_setup_data(struct udevice *dev, struct mmc_data *data) +{ + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; u32 ctrl_reg; - debug("%s, data %s : blocks=%d blksz=%d\n", DRIVER_NAME, - (data->flags & MMC_DATA_READ) ? "read" : "write", - data->blocks, data->blocksize); + dev_dbg(dev, "data %s : blocks=%d blksz=%d\n", + (data->flags & MMC_DATA_READ) ? "read" : "write", + data->blocks, data->blocksize); /* default to maximum timeout */ - ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL); + ctrl_reg = mvebu_mmc_read(mmc, SDIO_HOST_CTRL); ctrl_reg |= SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX); - mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg); + mvebu_mmc_write(mmc, SDIO_HOST_CTRL, ctrl_reg); if (data->flags & MMC_DATA_READ) { - mvebu_mmc_write(SDIO_SYS_ADDR_LOW, (u32)data->dest & 0xffff); - mvebu_mmc_write(SDIO_SYS_ADDR_HI, (u32)data->dest >> 16); + mvebu_mmc_write(mmc, SDIO_SYS_ADDR_LOW, (u32)data->dest & 0xffff); + mvebu_mmc_write(mmc, SDIO_SYS_ADDR_HI, (u32)data->dest >> 16); } else { - mvebu_mmc_write(SDIO_SYS_ADDR_LOW, (u32)data->src & 0xffff); - mvebu_mmc_write(SDIO_SYS_ADDR_HI, (u32)data->src >> 16); + mvebu_mmc_write(mmc, SDIO_SYS_ADDR_LOW, (u32)data->src & 0xffff); + mvebu_mmc_write(mmc, SDIO_SYS_ADDR_HI, (u32)data->src >> 16); } - mvebu_mmc_write(SDIO_BLK_COUNT, data->blocks); - mvebu_mmc_write(SDIO_BLK_SIZE, data->blocksize); + mvebu_mmc_write(mmc, SDIO_BLK_COUNT, data->blocks); + mvebu_mmc_write(mmc, SDIO_BLK_SIZE, data->blocksize); return 0; } -static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, +static int mvebu_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { ulong start; @@ -72,12 +79,14 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, ushort resptype = 0; ushort xfertype = 0; ushort resp_indx = 0; + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; - debug("%s: cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n", - DRIVER_NAME, cmd->cmdidx, cmd->resp_type, cmd->cmdarg); + dev_dbg(dev, "cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n", + cmd->cmdidx, cmd->resp_type, cmd->cmdarg); - debug("%s: cmd %d (hw state 0x%04x)\n", DRIVER_NAME, - cmd->cmdidx, mvebu_mmc_read(SDIO_HW_STATE)); + dev_dbg(dev, "cmd %d (hw state 0x%04x)\n", + cmd->cmdidx, mvebu_mmc_read(mmc, SDIO_HW_STATE)); /* * Hardware weirdness. The FIFO_EMPTY bit of the HW_STATE @@ -88,26 +97,26 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, * this bit comes to good sense (which eventually happens by * itself) then the new transfer simply fails with a timeout. */ - if (!(mvebu_mmc_read(SDIO_HW_STATE) & CMD_FIFO_EMPTY)) { + if (!(mvebu_mmc_read(mmc, SDIO_HW_STATE) & CMD_FIFO_EMPTY)) { ushort hw_state, count = 0; start = get_timer(0); do { - hw_state = mvebu_mmc_read(SDIO_HW_STATE); + hw_state = mvebu_mmc_read(mmc, SDIO_HW_STATE); if ((get_timer(0) - start) > TIMEOUT_DELAY) { printf("%s : FIFO_EMPTY bit missing\n", - DRIVER_NAME); + dev->name); break; } count++; } while (!(hw_state & CMD_FIFO_EMPTY)); - debug("%s *** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n", - DRIVER_NAME, hw_state, count, (get_timer(0) - (start))); + dev_dbg(dev, "*** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n", + hw_state, count, (get_timer(0) - (start))); } /* Clear status */ - mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); - mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); resptype = SDIO_CMD_INDEX(cmd->cmdidx); @@ -133,11 +142,10 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } if (data) { - int err = mvebu_mmc_setup_data(data); + int err = mvebu_mmc_setup_data(dev, data); if (err) { - debug("%s: command DATA error :%x\n", - DRIVER_NAME, err); + dev_dbg(dev, "command DATA error :%x\n", err); return err; } @@ -154,34 +162,33 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } /* Setting cmd arguments */ - mvebu_mmc_write(SDIO_ARG_LOW, cmd->cmdarg & 0xffff); - mvebu_mmc_write(SDIO_ARG_HI, cmd->cmdarg >> 16); + mvebu_mmc_write(mmc, SDIO_ARG_LOW, cmd->cmdarg & 0xffff); + mvebu_mmc_write(mmc, SDIO_ARG_HI, cmd->cmdarg >> 16); /* Setting Xfer mode */ - mvebu_mmc_write(SDIO_XFER_MODE, xfertype); + mvebu_mmc_write(mmc, SDIO_XFER_MODE, xfertype); /* Sending command */ - mvebu_mmc_write(SDIO_CMD, resptype); + mvebu_mmc_write(mmc, SDIO_CMD, resptype); start = get_timer(0); - while (!((mvebu_mmc_read(SDIO_NOR_INTR_STATUS)) & waittype)) { - if (mvebu_mmc_read(SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) { - debug("%s: error! cmdidx : %d, err reg: %04x\n", - DRIVER_NAME, cmd->cmdidx, - mvebu_mmc_read(SDIO_ERR_INTR_STATUS)); - if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & + while (!((mvebu_mmc_read(mmc, SDIO_NOR_INTR_STATUS)) & waittype)) { + if (mvebu_mmc_read(mmc, SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) { + dev_dbg(dev, "error! cmdidx : %d, err reg: %04x\n", + cmd->cmdidx, + mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS)); + if (mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS) & (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) { - debug("%s: command READ timed out\n", - DRIVER_NAME); + dev_dbg(dev, "command READ timed out\n"); return -ETIMEDOUT; } - debug("%s: command READ error\n", DRIVER_NAME); + dev_dbg(dev, "command READ error\n"); return -ECOMM; } if ((get_timer(0) - start) > TIMEOUT_DELAY) { - debug("%s: command timed out\n", DRIVER_NAME); + dev_dbg(dev, "command timed out\n"); return -ETIMEDOUT; } } @@ -191,8 +198,7 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, uint response[8]; for (resp_indx = 0; resp_indx < 8; resp_indx++) - response[resp_indx] - = mvebu_mmc_read(SDIO_RSP(resp_indx)); + response[resp_indx] = mvebu_mmc_read(mmc, SDIO_RSP(resp_indx)); cmd->response[0] = ((response[0] & 0x03ff) << 22) | ((response[1] & 0xffff) << 6) | @@ -209,8 +215,7 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, uint response[3]; for (resp_indx = 0; resp_indx < 3; resp_indx++) - response[resp_indx] - = mvebu_mmc_read(SDIO_RSP(resp_indx)); + response[resp_indx] = mvebu_mmc_read(mmc, SDIO_RSP(resp_indx)); cmd->response[0] = ((response[2] & 0x003f) << (8 - 8)) | ((response[1] & 0xffff) << (14 - 8)) | @@ -225,64 +230,71 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, cmd->response[3] = 0; } - debug("%s: resp[0x%x] ", DRIVER_NAME, cmd->resp_type); + dev_dbg(dev, "resp[0x%x] ", cmd->resp_type); debug("[0x%x] ", cmd->response[0]); debug("[0x%x] ", cmd->response[1]); debug("[0x%x] ", cmd->response[2]); debug("[0x%x] ", cmd->response[3]); debug("\n"); - if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & + if (mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS) & (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) return -ETIMEDOUT; return 0; } -static void mvebu_mmc_power_up(void) +static void mvebu_mmc_power_up(struct udevice *dev) { - debug("%s: power up\n", DRIVER_NAME); + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; + + dev_dbg(dev, "power up\n"); /* disable interrupts */ - mvebu_mmc_write(SDIO_NOR_INTR_EN, 0); - mvebu_mmc_write(SDIO_ERR_INTR_EN, 0); + mvebu_mmc_write(mmc, SDIO_NOR_INTR_EN, 0); + mvebu_mmc_write(mmc, SDIO_ERR_INTR_EN, 0); /* SW reset */ - mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW); + mvebu_mmc_write(mmc, SDIO_SW_RESET, SDIO_SW_RESET_NOW); - mvebu_mmc_write(SDIO_XFER_MODE, 0); + mvebu_mmc_write(mmc, SDIO_XFER_MODE, 0); /* enable status */ - mvebu_mmc_write(SDIO_NOR_STATUS_EN, SDIO_POLL_MASK); - mvebu_mmc_write(SDIO_ERR_STATUS_EN, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_NOR_STATUS_EN, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_ERR_STATUS_EN, SDIO_POLL_MASK); /* enable interrupts status */ - mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); - mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK); } -static void mvebu_mmc_set_clk(unsigned int clock) +static void mvebu_mmc_set_clk(struct udevice *dev, unsigned int clock) { unsigned int m; + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; if (clock == 0) { - debug("%s: clock off\n", DRIVER_NAME); - mvebu_mmc_write(SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK); - mvebu_mmc_write(SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX); + dev_dbg(dev, "clock off\n"); + mvebu_mmc_write(mmc, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK); + mvebu_mmc_write(mmc, SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX); } else { m = MVEBU_MMC_BASE_FAST_CLOCK/(2*clock) - 1; if (m > MVEBU_MMC_BASE_DIV_MAX) m = MVEBU_MMC_BASE_DIV_MAX; - mvebu_mmc_write(SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX); - debug("%s: clock (%d) div : %d\n", DRIVER_NAME, clock, m); + mvebu_mmc_write(mmc, SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX); + dev_dbg(dev, "clock (%d) div : %d\n", clock, m); } } -static void mvebu_mmc_set_bus(unsigned int bus) +static void mvebu_mmc_set_bus(struct udevice *dev, unsigned int bus) { + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; u32 ctrl_reg = 0; - ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL); + ctrl_reg = mvebu_mmc_read(mmc, SDIO_HOST_CTRL); ctrl_reg &= ~SDIO_HOST_CTRL_DATA_WIDTH_4_BITS; switch (bus) { @@ -306,23 +318,26 @@ static void mvebu_mmc_set_bus(unsigned int bus) ctrl_reg |= SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY; - debug("%s: ctrl 0x%04x: %s %s %s\n", DRIVER_NAME, ctrl_reg, - (ctrl_reg & SDIO_HOST_CTRL_PUSH_PULL_EN) ? - "push-pull" : "open-drain", - (ctrl_reg & SDIO_HOST_CTRL_DATA_WIDTH_4_BITS) ? - "4bit-width" : "1bit-width", - (ctrl_reg & SDIO_HOST_CTRL_HI_SPEED_EN) ? - "high-speed" : ""); + dev_dbg(dev, "ctrl 0x%04x: %s %s %s\n", ctrl_reg, + (ctrl_reg & SDIO_HOST_CTRL_PUSH_PULL_EN) ? + "push-pull" : "open-drain", + (ctrl_reg & SDIO_HOST_CTRL_DATA_WIDTH_4_BITS) ? + "4bit-width" : "1bit-width", + (ctrl_reg & SDIO_HOST_CTRL_HI_SPEED_EN) ? + "high-speed" : ""); - mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg); + mvebu_mmc_write(mmc, SDIO_HOST_CTRL, ctrl_reg); } -static int mvebu_mmc_set_ios(struct mmc *mmc) +static int mvebu_mmc_set_ios(struct udevice *dev) { - debug("%s: bus[%d] clock[%d]\n", DRIVER_NAME, - mmc->bus_width, mmc->clock); - mvebu_mmc_set_bus(mmc->bus_width); - mvebu_mmc_set_clk(mmc->clock); + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; + + dev_dbg(dev, "bus[%d] clock[%d]\n", + mmc->bus_width, mmc->clock); + mvebu_mmc_set_bus(dev, mmc->bus_width); + mvebu_mmc_set_clk(dev, mmc->clock); return 0; } @@ -330,13 +345,13 @@ static int mvebu_mmc_set_ios(struct mmc *mmc) /* * Set window register. */ -static void mvebu_window_setup(void) +static void mvebu_window_setup(const struct mmc *mmc) { int i; for (i = 0; i < 4; i++) { - mvebu_mmc_write(WINDOW_CTRL(i), 0); - mvebu_mmc_write(WINDOW_BASE(i), 0); + mvebu_mmc_write(mmc, WINDOW_CTRL(i), 0); + mvebu_mmc_write(mmc, WINDOW_BASE(i), 0); } for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { u32 size, base, attrib; @@ -364,79 +379,119 @@ static void mvebu_window_setup(void) size = gd->bd->bi_dram[i].size; base = gd->bd->bi_dram[i].start; if (size && attrib) { - mvebu_mmc_write(WINDOW_CTRL(i), + mvebu_mmc_write(mmc, WINDOW_CTRL(i), MVCPU_WIN_CTRL_DATA(size, MVEBU_TARGET_DRAM, attrib, MVCPU_WIN_ENABLE)); } else { - mvebu_mmc_write(WINDOW_CTRL(i), MVCPU_WIN_DISABLE); + mvebu_mmc_write(mmc, WINDOW_CTRL(i), MVCPU_WIN_DISABLE); } - mvebu_mmc_write(WINDOW_BASE(i), base); + mvebu_mmc_write(mmc, WINDOW_BASE(i), base); } } -static int mvebu_mmc_initialize(struct mmc *mmc) +static int mvebu_mmc_initialize(struct udevice *dev) { - debug("%s: mvebu_mmc_initialize\n", DRIVER_NAME); + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc *mmc = &pdata->mmc; + + dev_dbg(dev, "%s\n", __func__); /* * Setting host parameters * Initial Host Ctrl : Timeout : max , Normal Speed mode, * 4-bit data mode, Big Endian, SD memory Card, Push_pull CMD Line */ - mvebu_mmc_write(SDIO_HOST_CTRL, + mvebu_mmc_write(mmc, SDIO_HOST_CTRL, SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX) | SDIO_HOST_CTRL_DATA_WIDTH_4_BITS | SDIO_HOST_CTRL_BIG_ENDIAN | SDIO_HOST_CTRL_PUSH_PULL_EN | SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY); - mvebu_mmc_write(SDIO_CLK_CTRL, 0); + mvebu_mmc_write(mmc, SDIO_CLK_CTRL, 0); /* enable status */ - mvebu_mmc_write(SDIO_NOR_STATUS_EN, SDIO_POLL_MASK); - mvebu_mmc_write(SDIO_ERR_STATUS_EN, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_NOR_STATUS_EN, SDIO_POLL_MASK); + mvebu_mmc_write(mmc, SDIO_ERR_STATUS_EN, SDIO_POLL_MASK); /* disable interrupts */ - mvebu_mmc_write(SDIO_NOR_INTR_EN, 0); - mvebu_mmc_write(SDIO_ERR_INTR_EN, 0); + mvebu_mmc_write(mmc, SDIO_NOR_INTR_EN, 0); + mvebu_mmc_write(mmc, SDIO_ERR_INTR_EN, 0); - mvebu_window_setup(); + mvebu_window_setup(mmc); /* SW reset */ - mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW); + mvebu_mmc_write(mmc, SDIO_SW_RESET, SDIO_SW_RESET_NOW); return 0; } -static const struct mmc_ops mvebu_mmc_ops = { - .send_cmd = mvebu_mmc_send_cmd, - .set_ios = mvebu_mmc_set_ios, - .init = mvebu_mmc_initialize, -}; - -static struct mmc_config mvebu_mmc_cfg = { - .name = DRIVER_NAME, - .ops = &mvebu_mmc_ops, - .f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX, - .f_max = MVEBU_MMC_CLOCKRATE_MAX, - .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, - .host_caps = MMC_MODE_4BIT | MMC_MODE_HS | - MMC_MODE_HS_52MHz, - .part_type = PART_TYPE_DOS, - .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, -}; - -int mvebu_mmc_init(struct bd_info *bis) +static int mvebu_mmc_of_to_plat(struct udevice *dev) { - struct mmc *mmc; + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + fdt_addr_t addr; - mvebu_mmc_power_up(); + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; - mmc = mmc_create(&mvebu_mmc_cfg, bis); - if (mmc == NULL) - return -1; + pdata->iobase = (void *)addr; return 0; } + +static int mvebu_mmc_probe(struct udevice *dev) +{ + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct mmc *mmc = &pdata->mmc; + struct mmc_config *cfg = &pdata->cfg; + + cfg->name = dev->name; + cfg->f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX; + cfg->f_max = MVEBU_MMC_CLOCKRATE_MAX; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; + cfg->part_type = PART_TYPE_DOS; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + mmc->cfg = cfg; + mmc->priv = pdata; + mmc->dev = dev; + upriv->mmc = mmc; + + mvebu_mmc_power_up(dev); + mvebu_mmc_initialize(dev); + + return 0; +} + +static const struct dm_mmc_ops mvebu_dm_mmc_ops = { + .send_cmd = mvebu_mmc_send_cmd, + .set_ios = mvebu_mmc_set_ios, +}; + +static int mvebu_mmc_bind(struct udevice *dev) +{ + struct mvebu_mmc_plat *pdata = dev_get_plat(dev); + + return mmc_bind(dev, &pdata->mmc, &pdata->cfg); +} + +static const struct udevice_id mvebu_mmc_match[] = { + { .compatible = "marvell,orion-sdio" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(mvebu_mmc) = { + .name = "mvebu_mmc", + .id = UCLASS_MMC, + .of_match = mvebu_mmc_match, + .ops = &mvebu_dm_mmc_ops, + .probe = mvebu_mmc_probe, + .bind = mvebu_mmc_bind, + .of_to_plat = mvebu_mmc_of_to_plat, + .plat_auto = sizeof(struct mvebu_mmc_plat), +}; diff --git a/include/mvebu_mmc.h b/include/mvebu_mmc.h index a35e5a12ce..e75c3fa328 100644 --- a/include/mvebu_mmc.h +++ b/include/mvebu_mmc.h @@ -258,17 +258,10 @@ /* Hardware reset */ #define MMC_CAP_HW_RESET (1 << 31) -struct mvebu_mmc_cfg { - u32 mvebu_mmc_base; - u32 mvebu_mmc_clk; - u8 max_bus_width; +struct mvebu_mmc_plat { + void *iobase; struct mmc_config cfg; + struct mmc mmc; }; -/* - * Functions prototypes - */ - -int mvebu_mmc_init(struct bd_info *bis); - #endif /* __MVEBU_MMC_H__ */ From b5293df17a2c9239e92c8024484cd3ad3ed55f00 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Tue, 30 Mar 2021 10:19:42 +0200 Subject: [PATCH 17/17] configs: sheevaplug: enable driver-model based MMC The non-dm MMC driver has been converted to the driver model. The sheevaplug was using the non-dm driver and this commit enables the new driver. Signed-off-by: Harm Berntsen Reviewed-by: Stefan Roese CC: Prafulla Wadaskar CC: Stefan Roese CC: Tom Rini --- configs/sheevaplug_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/sheevaplug_defconfig b/configs/sheevaplug_defconfig index 34da356b8e..65d8dff7ff 100644 --- a/configs/sheevaplug_defconfig +++ b/configs/sheevaplug_defconfig @@ -40,6 +40,8 @@ CONFIG_ENV_IS_IN_NAND=y CONFIG_NETCONSOLE=y CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_DM_MMC=y +CONFIG_MVEBU_MMC=y CONFIG_MTD=y CONFIG_MTD_RAW_NAND=y CONFIG_MVGBE=y