* [PATCH v4 1/4] ARM: novena: Add Kosagi Novena board
2023-02-02 7:57 [PATCH v4 0/5] Add support for the Kosagi Novena board John Watts
@ 2023-02-02 7:57 ` John Watts
2023-02-02 7:57 ` [PATCH v4 2/4] ARM: novena: Setup RAM using static configuration John Watts
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: John Watts @ 2023-02-02 7:57 UTC (permalink / raw)
To: barebox; +Cc: John Watts
The Kosagi Novena is an open source laptop released in 2014.
This patch adds the initial project skeleton for running the PBL
and debugging over the UART2 port (labeled DEBUG on the board.)
Signed-off-by: John Watts <contact@jookia.org>
---
arch/arm/boards/Makefile | 1 +
arch/arm/boards/novena/Makefile | 4 ++
arch/arm/boards/novena/board.c | 24 +++++++
| 6 ++
arch/arm/boards/novena/lowlevel.c | 68 +++++++++++++++++++
arch/arm/configs/imx_v7_defconfig | 1 +
arch/arm/dts/Makefile | 1 +
arch/arm/dts/imx6q-novena.dts | 4 ++
arch/arm/mach-imx/Kconfig | 7 ++
images/Makefile.imx | 2 +
10 files changed, 118 insertions(+)
create mode 100644 arch/arm/boards/novena/Makefile
create mode 100644 arch/arm/boards/novena/board.c
create mode 100644 arch/arm/boards/novena/flash-header-novena.imxcfg
create mode 100644 arch/arm/boards/novena/lowlevel.c
create mode 100644 arch/arm/dts/imx6q-novena.dts
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index f47aea6602..50088886eb 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MACH_BEAGLEBONE) += beaglebone/
obj-$(CONFIG_MACH_CANON_A1100) += canon-a1100/
obj-$(CONFIG_MACH_CM_FX6) += cm-fx6/
obj-$(CONFIG_MACH_NITROGEN6) += boundarydevices-nitrogen6/
+obj-$(CONFIG_MACH_NOVENA) += novena/
obj-$(CONFIG_MACH_CCMX51) += ccxmx51/
obj-$(CONFIG_MACH_CCMX53) += ccxmx53/
obj-$(CONFIG_MACH_CFA10036) += crystalfontz-cfa10036/
diff --git a/arch/arm/boards/novena/Makefile b/arch/arm/boards/novena/Makefile
new file mode 100644
index 0000000000..3111392bf9
--- /dev/null
+++ b/arch/arm/boards/novena/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-y += board.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/novena/board.c b/arch/arm/boards/novena/board.c
new file mode 100644
index 0000000000..e41ea10f8d
--- /dev/null
+++ b/arch/arm/boards/novena/board.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 John Watts <contact@jookia.org>
+
+#include <common.h>
+#include <deep-probe.h>
+
+static int novena_probe(struct device *dev)
+{
+ return 0;
+}
+
+static const struct of_device_id novena_of_match[] = {
+ { .compatible = "kosagi,imx6q-novena", },
+ { /* sentinel */ }
+};
+
+static struct driver novena_board_driver = {
+ .name = "board-novena",
+ .probe = novena_probe,
+ .of_compatible = novena_of_match,
+};
+coredevice_platform_driver(novena_board_driver);
+
+BAREBOX_DEEP_PROBE_ENABLE(novena_of_match);
--git a/arch/arm/boards/novena/flash-header-novena.imxcfg b/arch/arm/boards/novena/flash-header-novena.imxcfg
new file mode 100644
index 0000000000..0612542c19
--- /dev/null
+++ b/arch/arm/boards/novena/flash-header-novena.imxcfg
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+loadaddr 0x00907000
+soc imx6
+max_load_size 0x11000
+ivtofs 0x400
diff --git a/arch/arm/boards/novena/lowlevel.c b/arch/arm/boards/novena/lowlevel.c
new file mode 100644
index 0000000000..5782e598c7
--- /dev/null
+++ b/arch/arm/boards/novena/lowlevel.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2023 John Watts <contact@jookia.org>
+
+#include <asm/barebox-arm.h>
+#include <common.h>
+#include <debug_ll.h>
+#include <mach/esdctl.h>
+#include <mach/generic.h>
+#include <mach/imx6.h>
+#include <mach/iomux-mx6.h>
+#include <mach/xload.h>
+#include <soc/fsl/fsl_udc.h>
+
+#define STACK_TOP (MX6_OCRAM_BASE_ADDR + MX6_OCRAM_MAX_SIZE)
+
+extern char __dtb_z_imx6q_novena_start[];
+
+static bool running_from_ram(void)
+{
+ return (get_pc() >= MX6_MMDC_PORT01_BASE_ADDR);
+}
+
+static void setup_uart(void)
+{
+ void __iomem *iomuxbase = IOMEM(MX6_IOMUXC_BASE_ADDR);
+ void __iomem *uart2base = IOMEM(MX6_UART2_BASE_ADDR);
+
+ /* NOTE: RX is needed for TX to work on this board */
+ imx_setup_pad(iomuxbase, MX6Q_PAD_EIM_D26__UART2_RXD);
+ imx_setup_pad(iomuxbase, MX6Q_PAD_EIM_D27__UART2_TXD);
+
+ imx6_uart_setup(uart2base);
+ pbl_set_putc(imx_uart_putc, uart2base);
+
+ pr_debug(">");
+}
+
+static void load_barebox(void)
+{
+ enum bootsource bootsrc;
+ int bootinstance;
+
+ imx6_get_boot_source(&bootsrc, &bootinstance);
+
+ if (bootsrc == BOOTSOURCE_SERIAL)
+ imx6_barebox_start_usb(IOMEM(MX6_MMDC_PORT01_BASE_ADDR));
+ else if (bootsrc == BOOTSOURCE_MMC)
+ imx6_esdhc_start_image(bootinstance);
+
+ pr_err("Unsupported boot source %i instance %i\n",
+ bootsrc, bootinstance);
+ hang();
+}
+
+ENTRY_FUNCTION_WITHSTACK(start_imx6q_novena, STACK_TOP, r0, r1, r2)
+{
+ imx6_cpu_lowlevel_init();
+ relocate_to_current_adr();
+ setup_c();
+
+ imx6_ungate_all_peripherals();
+ setup_uart();
+
+ if (!running_from_ram())
+ load_barebox();
+ else
+ imx6q_barebox_entry(__dtb_z_imx6q_novena_start);
+}
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 6110a52e48..f8deca324a 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -25,6 +25,7 @@ CONFIG_MACH_SABRELITE=y
CONFIG_MACH_SABRESD=y
CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB=y
CONFIG_MACH_NITROGEN6=y
+CONFIG_MACH_NOVENA=y
CONFIG_MACH_SOLIDRUN_MICROSOM=y
CONFIG_MACH_TECHNEXION_PICO_HOBBIT=y
CONFIG_MACH_TECHNEXION_WANDBOARD=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 26c4a8ab99..a01ee19f68 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -46,6 +46,7 @@ lwl-$(CONFIG_MACH_MYIRTECH_X335X) += am335x-myirtech-myd.dtb.o
lwl-$(CONFIG_MACH_NETGEAR_RN104) += armada-370-rn104-bb.dtb.o
lwl-$(CONFIG_MACH_NETGEAR_RN2120) += armada-xp-rn2120-bb.dtb.o
lwl-$(CONFIG_MACH_NITROGEN6) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o imx6qp-nitrogen6_max.dtb.o
+lwl-$(CONFIG_MACH_NOVENA) += imx6q-novena.dtb.o
lwl-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o
lwl-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o
lwl-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o
diff --git a/arch/arm/dts/imx6q-novena.dts b/arch/arm/dts/imx6q-novena.dts
new file mode 100644
index 0000000000..12bade849c
--- /dev/null
+++ b/arch/arm/dts/imx6q-novena.dts
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR X11
+// SPDX-FileCopyrightText: 2023 John Watts <contact@jookia.org>
+
+#include <arm/imx6q-novena.dts>
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 774c4cacb7..912eef8290 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -434,6 +434,13 @@ config MACH_NITROGEN6
bool "BoundaryDevices Nitrogen6 boards"
select ARCH_IMX6
+config MACH_NOVENA
+ bool "Kosagi Novena board"
+ select ARCH_IMX6
+ select ARM_USE_COMPRESSED_DTB
+ select MCI_IMX_ESDHC_PBL
+ select USB_GADGET_DRIVER_ARC_PBL
+
config MACH_SOLIDRUN_MICROSOM
bool "SolidRun MicroSOM based devices"
select ARCH_IMX6
diff --git a/images/Makefile.imx b/images/Makefile.imx
index e9f4ba64e4..65914212bf 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -258,6 +258,8 @@ $(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6dl_nitrogen6x_2g, bo
$(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6qp_nitrogen6_max, boundarydevices-nitrogen6/flash-header-nitrogen6qp-max, boundarydevices-imx6qp-nitrogen6_max)
+$(call build_imx_habv4img, CONFIG_MACH_NOVENA, start_imx6q_novena, novena/flash-header-novena, imx6q-novena)
+
$(call build_imx_habv4img, CONFIG_MACH_TX6X, start_imx6dl_tx6x_512m, karo-tx6x/flash-header-tx6dl-512m, karo-imx6dl-tx6x-512m)
$(call build_imx_habv4img, CONFIG_MACH_TX6X, start_imx6dl_tx6x_1g, karo-tx6x/flash-header-tx6dl-1g, karo-imx6dl-tx6x-1g)
--
2.39.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 2/4] ARM: novena: Setup RAM using static configuration
2023-02-02 7:57 [PATCH v4 0/5] Add support for the Kosagi Novena board John Watts
2023-02-02 7:57 ` [PATCH v4 1/4] ARM: novena: Add " John Watts
@ 2023-02-02 7:57 ` John Watts
2023-02-02 7:57 ` [PATCH v4 3/4] ARM: novena: Read Ethernet MAC address from EEPROM John Watts
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: John Watts @ 2023-02-02 7:57 UTC (permalink / raw)
To: barebox; +Cc: John Watts
The Novena laptops were shipped with a 4GB stick that can be set up
using this DDR3 configuration.
This isn't ideal as the stick is swappable, but it will work for
most people.
The DDR registers are copied from /board/kosagi/novena/novena_spl.c
from the Novena U-Boot fork (tag novena-r2) with two changes:
- Bank interleaving is disabled: The Novena U-Boot code disables it
unconditionally during execution anyway
- Page size is set to 1KB: I'm not sure the hardware supports x16 DIMMs
Mainline U-Boot has similar code, but the timing differences don't work
on my board so I'm unable to test or port that code over.
Signed-off-by: John Watts <contact@jookia.org>
---
arch/arm/boards/novena/ddr_regs.h | 119 ++++++++++++++++++++++++++++++
arch/arm/boards/novena/lowlevel.c | 14 +++-
2 files changed, 131 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/boards/novena/ddr_regs.h
diff --git a/arch/arm/boards/novena/ddr_regs.h b/arch/arm/boards/novena/ddr_regs.h
new file mode 100644
index 0000000000..5f18d5e0e4
--- /dev/null
+++ b/arch/arm/boards/novena/ddr_regs.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2014 Marek Vasut <marex@denx.de> */
+
+#ifndef NOVENA_DDR_REGS_H
+#define NOVENA_DDR_REGS_H
+
+/* MEMORY CONTROLLER CONFIGURATION */
+
+static struct mx6dq_iomux_ddr_regs novena_ddr_regs = {
+ /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+ .dram_sdclk_0 = 0x00020038,
+ .dram_sdclk_1 = 0x00020038,
+ .dram_cas = 0x00000038,
+ .dram_ras = 0x00000038,
+ .dram_reset = 0x00000038,
+ /* SDCKE[0:1]: 100k pull-up */
+ .dram_sdcke0 = 0x00003000,
+ .dram_sdcke1 = 0x00003000,
+ /* SDBA2: pull-up disabled */
+ .dram_sdba2 = 0x00000000,
+ /* SDODT[0:1]: 100k pull-up, 40 ohm */
+ .dram_sdodt0 = 0x00000038,
+ .dram_sdodt1 = 0x00000038,
+ /* SDQS[0:7]: Differential input, 40 ohm */
+ .dram_sdqs0 = 0x00000038,
+ .dram_sdqs1 = 0x00000038,
+ .dram_sdqs2 = 0x00000038,
+ .dram_sdqs3 = 0x00000038,
+ .dram_sdqs4 = 0x00000038,
+ .dram_sdqs5 = 0x00000038,
+ .dram_sdqs6 = 0x00000038,
+ .dram_sdqs7 = 0x00000038,
+
+ /* DQM[0:7]: Differential input, 40 ohm */
+ .dram_dqm0 = 0x00000038,
+ .dram_dqm1 = 0x00000038,
+ .dram_dqm2 = 0x00000038,
+ .dram_dqm3 = 0x00000038,
+ .dram_dqm4 = 0x00000038,
+ .dram_dqm5 = 0x00000038,
+ .dram_dqm6 = 0x00000038,
+ .dram_dqm7 = 0x00000038,
+};
+
+static struct mx6dq_iomux_grp_regs novena_grp_regs = {
+ /* DDR3 */
+ .grp_ddr_type = 0x000c0000,
+ .grp_ddrmode_ctl = 0x00020000,
+ /* Disable DDR pullups */
+ .grp_ddrpke = 0x00000000,
+ /* ADDR[00:16], SDBA[0:1]: 40 ohm */
+ .grp_addds = 0x00000038,
+ /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+ .grp_ctlds = 0x00000038,
+ /* DATA[00:63]: Differential input, 40 ohm */
+ .grp_ddrmode = 0x00020000,
+ .grp_b0ds = 0x00000038,
+ .grp_b1ds = 0x00000038,
+ .grp_b2ds = 0x00000038,
+ .grp_b3ds = 0x00000038,
+ .grp_b4ds = 0x00000038,
+ .grp_b5ds = 0x00000038,
+ .grp_b6ds = 0x00000038,
+ .grp_b7ds = 0x00000038,
+};
+
+/* MEMORY STICK CONFIGURATION */
+
+static struct mx6_mmdc_calibration novena_mmdc_calib = {
+ /* write leveling calibration determine */
+ .p0_mpwldectrl0 = 0x00420048,
+ .p0_mpwldectrl1 = 0x006f0059,
+ .p1_mpwldectrl0 = 0x005a0104,
+ .p1_mpwldectrl1 = 0x01070113,
+ /* Read DQS Gating calibration */
+ .p0_mpdgctrl0 = 0x437c040b,
+ .p0_mpdgctrl1 = 0x0413040e,
+ .p1_mpdgctrl0 = 0x444f0446,
+ .p1_mpdgctrl1 = 0x044d0422,
+ /* Read Calibration: DQS delay relative to DQ read access */
+ .p0_mprddlctl = 0x4c424249,
+ .p1_mprddlctl = 0x4e48414f,
+ /* Write Calibration: DQ/DM delay relative to DQS write access */
+ .p0_mpwrdlctl = 0x42414641,
+ .p1_mpwrdlctl = 0x46374b43,
+};
+
+static struct mx6_ddr_sysinfo novena_ddr_info = {
+ /* Width of data bus: 0=16, 1=32, 2=64 */
+ .dsize = 2,
+ /* Config for full 4GB range so that get_mem_size() works */
+ .cs_density = 32, /* 32Gb per CS */
+ /* Single chip select */
+ .ncs = 1,
+ .cs1_mirror = 0,
+ .rtt_wr = 1, /* RTT_Wr = RZQ/4 */
+ .rtt_nom = 2, /* RTT_Nom = RZQ/2 */
+ .walat = 3, /* Write additional latency */
+ .ralat = 7, /* Read additional latency */
+ .mif3_mode = 3, /* Command prediction working mode */
+ .bi_on = 0, /* Bank interleaving disabled */
+ .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
+ .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
+};
+
+static struct mx6_ddr3_cfg novena_ddr_cfg = {
+ .mem_speed = 1600,
+ .density = 4,
+ .width = 64,
+ .banks = 8,
+ .rowaddr = 16,
+ .coladdr = 10,
+ .pagesz = 1,
+ .trcd = 1300,
+ .trcmin = 4900,
+ .trasmin = 3590,
+};
+
+#endif
diff --git a/arch/arm/boards/novena/lowlevel.c b/arch/arm/boards/novena/lowlevel.c
index 5782e598c7..c49c6aab41 100644
--- a/arch/arm/boards/novena/lowlevel.c
+++ b/arch/arm/boards/novena/lowlevel.c
@@ -7,9 +7,11 @@
#include <mach/esdctl.h>
#include <mach/generic.h>
#include <mach/imx6.h>
+#include <mach/imx6-mmdc.h>
#include <mach/iomux-mx6.h>
#include <mach/xload.h>
#include <soc/fsl/fsl_udc.h>
+#include "ddr_regs.h"
#define STACK_TOP (MX6_OCRAM_BASE_ADDR + MX6_OCRAM_MAX_SIZE)
@@ -35,6 +37,12 @@ static void setup_uart(void)
pr_debug(">");
}
+static void setup_ram(void)
+{
+ mx6dq_dram_iocfg(64, &novena_ddr_regs, &novena_grp_regs);
+ mx6_dram_cfg(&novena_ddr_info, &novena_mmdc_calib, &novena_ddr_cfg);
+}
+
static void load_barebox(void)
{
enum bootsource bootsrc;
@@ -61,8 +69,10 @@ ENTRY_FUNCTION_WITHSTACK(start_imx6q_novena, STACK_TOP, r0, r1, r2)
imx6_ungate_all_peripherals();
setup_uart();
- if (!running_from_ram())
+ if (!running_from_ram()) {
+ setup_ram();
load_barebox();
- else
+ } else {
imx6q_barebox_entry(__dtb_z_imx6q_novena_start);
+ }
}
--
2.39.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 3/4] ARM: novena: Read Ethernet MAC address from EEPROM
2023-02-02 7:57 [PATCH v4 0/5] Add support for the Kosagi Novena board John Watts
2023-02-02 7:57 ` [PATCH v4 1/4] ARM: novena: Add " John Watts
2023-02-02 7:57 ` [PATCH v4 2/4] ARM: novena: Setup RAM using static configuration John Watts
@ 2023-02-02 7:57 ` John Watts
2023-02-02 7:57 ` [PATCH v4 4/4] ARM: novena: Use DDR3 information from SPD EEPROM John Watts
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: John Watts @ 2023-02-02 7:57 UTC (permalink / raw)
To: barebox; +Cc: John Watts
The Novena has an EEPROM used for storing information about the board,
including the Ethernet MAC address.
The reference for the EEPROM fields is the novena-eeprom source code.
Signed-off-by: John Watts <contact@jookia.org>
---
arch/arm/boards/novena/board.c | 85 ++++++++++++++++++++++++++++++++++
arch/arm/dts/imx6q-novena.dts | 14 ++++++
2 files changed, 99 insertions(+)
diff --git a/arch/arm/boards/novena/board.c b/arch/arm/boards/novena/board.c
index e41ea10f8d..b6c59aff44 100644
--- a/arch/arm/boards/novena/board.c
+++ b/arch/arm/boards/novena/board.c
@@ -3,9 +3,94 @@
#include <common.h>
#include <deep-probe.h>
+#include <fs.h>
+#include <libfile.h>
+#include <net.h>
+
+struct novena_eeprom {
+ uint8_t signature[6]; /* 'Novena' */
+ uint8_t version; /* 1 or 2, not checked */
+ uint8_t page_size; /* v2 only: EEPROM read/write page */
+ uint32_t serial; /* 32-bit serial number */
+ uint8_t mac[6]; /* Gigabit MAC address */
+ uint16_t features; /* features */
+ /* ... extra fields omitted ... */
+} __packed;
+
+static void power_on_audio_codec(void)
+{
+ int rc = of_devices_ensure_probed_by_name("regulator-audio-codec");
+
+ if (rc < 0)
+ pr_err("Unable to power on audio codec: %s\n", strerror(-rc));
+}
+
+static struct novena_eeprom *novena_read_eeprom(void)
+{
+ size_t read;
+ loff_t max = sizeof(struct novena_eeprom);
+ void *eeprom;
+ int rc;
+
+ /*
+ * When powered off the audio codec pulls down the EEPROM's I2C line.
+ * Power it on so we can actually read data.
+ */
+ power_on_audio_codec();
+
+ rc = of_device_ensure_probed_by_alias("eeprom0");
+ if (rc < 0) {
+ pr_err("Unable to probe eeprom0: %s\n", strerror(-rc));
+ return NULL;
+ }
+
+ rc = read_file_2("/dev/eeprom0", &read, &eeprom, max);
+
+ if (rc < 0 && rc != -EFBIG) {
+ pr_err("Unable to read Novena EEPROM: %s\n", strerror(-rc));
+ return NULL;
+ } else if (read != max) {
+ pr_err("Short read from Novena EEPROM?\n");
+ free(eeprom);
+ return NULL;
+ }
+
+ return eeprom;
+}
+
+static bool novena_check_eeprom(struct novena_eeprom *eeprom)
+{
+ char *sig = eeprom->signature;
+ size_t size = sizeof(eeprom->signature);
+
+ if (memcmp("Novena", sig, size) != 0) {
+ pr_err("Unknown Novena EEPROM signature\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void novena_set_mac(struct novena_eeprom *eeprom)
+{
+ struct device_node *dnode;
+
+ dnode = of_find_node_by_alias(of_get_root_node(), "ethernet0");
+ if (dnode)
+ of_eth_register_ethaddr(dnode, eeprom->mac);
+ else
+ pr_err("Unable to find ethernet node\n");
+}
static int novena_probe(struct device *dev)
{
+ struct novena_eeprom *eeprom = novena_read_eeprom();
+
+ if (eeprom && novena_check_eeprom(eeprom))
+ novena_set_mac(eeprom);
+
+ free(eeprom);
+
return 0;
}
diff --git a/arch/arm/dts/imx6q-novena.dts b/arch/arm/dts/imx6q-novena.dts
index 12bade849c..c614ed3cbb 100644
--- a/arch/arm/dts/imx6q-novena.dts
+++ b/arch/arm/dts/imx6q-novena.dts
@@ -2,3 +2,17 @@
// SPDX-FileCopyrightText: 2023 John Watts <contact@jookia.org>
#include <arm/imx6q-novena.dts>
+
+/ {
+ aliases {
+ eeprom0 = &eeprom;
+ };
+};
+
+&i2c3 {
+ eeprom: eeprom@56 {
+ compatible = "24c512";
+ reg = <0x56>;
+ pagesize = <128>;
+ };
+};
--
2.39.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 4/4] ARM: novena: Use DDR3 information from SPD EEPROM
2023-02-02 7:57 [PATCH v4 0/5] Add support for the Kosagi Novena board John Watts
` (2 preceding siblings ...)
2023-02-02 7:57 ` [PATCH v4 3/4] ARM: novena: Read Ethernet MAC address from EEPROM John Watts
@ 2023-02-02 7:57 ` John Watts
2023-02-02 9:19 ` [PATCH v4 0/5] Add support for the Kosagi Novena board Marco Felsch
2023-02-03 8:01 ` Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: John Watts @ 2023-02-02 7:57 UTC (permalink / raw)
To: barebox; +Cc: John Watts
The Novena supports swappable memory which means we must query the memory
for configuration details. This patch uses values stored in the SPD EEPROM
to configure the i.MX6 memory controller.
If the SPD can't be read, the default configuration for a 4GB stick is
used. This is the same type of stick that comes with the board.
Calibration for the installed stick is run unconditionally.
Verification that this works was done by comparing MMDC registers before and
after and carefully reading other people's source code.
Signed-off-by: John Watts <contact@jookia.org>
---
arch/arm/boards/novena/lowlevel.c | 94 +++++++++++++++++++++++++++++++
arch/arm/mach-imx/Kconfig | 2 +
2 files changed, 96 insertions(+)
diff --git a/arch/arm/boards/novena/lowlevel.c b/arch/arm/boards/novena/lowlevel.c
index c49c6aab41..178c874892 100644
--- a/arch/arm/boards/novena/lowlevel.c
+++ b/arch/arm/boards/novena/lowlevel.c
@@ -3,6 +3,8 @@
#include <asm/barebox-arm.h>
#include <common.h>
+#include <ddr_dimms.h>
+#include <ddr_spd.h>
#include <debug_ll.h>
#include <mach/esdctl.h>
#include <mach/generic.h>
@@ -10,6 +12,7 @@
#include <mach/imx6-mmdc.h>
#include <mach/iomux-mx6.h>
#include <mach/xload.h>
+#include <pbl/i2c.h>
#include <soc/fsl/fsl_udc.h>
#include "ddr_regs.h"
@@ -17,6 +20,92 @@
extern char __dtb_z_imx6q_novena_start[];
+static struct spd_eeprom spd_eeprom;
+static struct dimm_params dimm_params;
+
+static struct pbl_i2c *setup_spd_i2c(void)
+{
+ void __iomem *iomuxbase = IOMEM(MX6_IOMUXC_BASE_ADDR);
+ void __iomem *i2c1base = IOMEM(MX6_I2C1_BASE_ADDR);
+
+ imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT8__I2C1_SDA);
+ imx_setup_pad(iomuxbase, MX6Q_PAD_CSI0_DAT9__I2C1_SCL);
+
+ return imx6_i2c_early_init(i2c1base);
+}
+
+static struct spd_eeprom *read_spd(void)
+{
+ struct spd_eeprom *eeprom = &spd_eeprom;
+ struct pbl_i2c *i2c = setup_spd_i2c();
+ int rc;
+
+ rc = spd_read_eeprom(i2c, 0x50, eeprom, SPD_MEMTYPE_DDR3);
+ if (rc < 0) {
+ pr_err("Couldn't read SPD EEPROM: %i\n", rc);
+ return NULL;
+ }
+
+ rc = ddr3_spd_check(&eeprom->ddr3);
+ if (rc < 0) {
+ pr_err("Couldn't verify SPD data: %i\n", rc);
+ return NULL;
+ }
+
+ return eeprom;
+}
+
+static void setup_dimm_settings(struct dimm_params *params,
+ struct mx6_ddr_sysinfo *info,
+ struct mx6_ddr3_cfg *cfg)
+{
+ int capacity_gbit = params->capacity / 0x8000000;
+ int density_rank = capacity_gbit / params->n_ranks;
+
+ info->ncs = params->n_ranks;
+ info->cs_density = density_rank;
+ cfg->mem_speed = params->tckmin_x_ps;
+ cfg->density = density_rank / params->n_banks_per_sdram_device;
+ cfg->width = params->data_width;
+ cfg->banks = params->n_banks_per_sdram_device;
+ cfg->rowaddr = params->n_row_addr;
+ cfg->coladdr = params->n_col_addr;
+ cfg->trcd = params->trcd_ps / 10;
+ cfg->trcmin = params->trc_ps / 10;
+ cfg->trasmin = params->tras_ps / 10;
+ cfg->SRT = params->extended_op_srt;
+
+ if (params->device_width >= 16)
+ cfg->pagesz = 2;
+}
+
+static void read_dimm_settings(void)
+{
+ struct spd_eeprom *eeprom = read_spd();
+ struct dimm_params *params = &dimm_params;
+ int rc;
+
+ if (!eeprom) {
+ pr_err("Couldn't read SPD EEPROM, using default settings\n");
+ return;
+ }
+
+ rc = ddr3_compute_dimm_parameters(&eeprom->ddr3, params);
+ if (rc < 0) {
+ pr_err("Couldn't compute DIMM params: %i\n", rc);
+ return;
+ }
+
+ pr_info("Found DIMM: %s\n", params->mpart);
+
+ if (params->primary_sdram_width != 64) {
+ pr_err("ERROR: DIMM stick memory width is not 64 bits\n");
+ hang();
+ }
+
+ setup_dimm_settings(params, &novena_ddr_info, &novena_ddr_cfg);
+}
+
static bool running_from_ram(void)
{
return (get_pc() >= MX6_MMDC_PORT01_BASE_ADDR);
@@ -39,8 +128,13 @@ static void setup_uart(void)
static void setup_ram(void)
{
+ read_dimm_settings();
+
mx6dq_dram_iocfg(64, &novena_ddr_regs, &novena_grp_regs);
mx6_dram_cfg(&novena_ddr_info, &novena_mmdc_calib, &novena_ddr_cfg);
+
+ mmdc_do_write_level_calibration();
+ mmdc_do_dqs_calibration();
}
static void load_barebox(void)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 912eef8290..dce5d9e1bb 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -438,6 +438,8 @@ config MACH_NOVENA
bool "Kosagi Novena board"
select ARCH_IMX6
select ARM_USE_COMPRESSED_DTB
+ select DDR_SPD
+ select I2C_IMX_EARLY
select MCI_IMX_ESDHC_PBL
select USB_GADGET_DRIVER_ARC_PBL
--
2.39.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 0/5] Add support for the Kosagi Novena board
2023-02-02 7:57 [PATCH v4 0/5] Add support for the Kosagi Novena board John Watts
` (3 preceding siblings ...)
2023-02-02 7:57 ` [PATCH v4 4/4] ARM: novena: Use DDR3 information from SPD EEPROM John Watts
@ 2023-02-02 9:19 ` Marco Felsch
2023-02-03 8:01 ` Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Marco Felsch @ 2023-02-02 9:19 UTC (permalink / raw)
To: John Watts; +Cc: barebox
Hi John,
On 23-02-02, John Watts wrote:
> This patch series introduces support for the Novena board.
> This support is basic but enough to boot Barebox.
>
> The EEPROM code here is included in anticipation for reading the features
> flag in the future when more board features are supported.
Reviewed-by: Marco Felsch <m.felsch@pengutronix.de>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v4 0/5] Add support for the Kosagi Novena board
2023-02-02 7:57 [PATCH v4 0/5] Add support for the Kosagi Novena board John Watts
` (4 preceding siblings ...)
2023-02-02 9:19 ` [PATCH v4 0/5] Add support for the Kosagi Novena board Marco Felsch
@ 2023-02-03 8:01 ` Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2023-02-03 8:01 UTC (permalink / raw)
To: John Watts; +Cc: barebox
On Thu, Feb 02, 2023 at 06:57:37PM +1100, John Watts wrote:
> This patch series introduces support for the Novena board.
> This support is basic but enough to boot Barebox.
>
> The EEPROM code here is included in anticipation for reading the features
> flag in the future when more board features are supported.
>
> Changes v3 -> v4:
> - Compressed device tree is now used
> - Code style fixes
> - Reworked DDR3 error checking to be more readable
>
> Changes v2 -> v3:
> - EEPROM data is freed correctly
> - Add email to copyright headers
> - Switched license from GPL2 to GPL2+
> - Dropped get_runtime_offset for device tree
> - Removed "okay" status from EEPROM in device tree
> - Moved novena_try_eeprom code in to novena_probe
> - Other small code re-organizations
> - Moved OCRAM address to its own separate patch
> - Moved udelay fix to its own patch
>
> Changes v1 -> v2:
> - The board uses the driver model now
> - Memory density is now calculated correctly
>
> John Watts (4):
> ARM: novena: Add Kosagi Novena board
> ARM: novena: Setup RAM using static configuration
> ARM: novena: Read Ethernet MAC address from EEPROM
> ARM: novena: Use DDR3 information from SPD EEPROM
Applied, thanks
Sascha
>
> arch/arm/boards/Makefile | 1 +
> arch/arm/boards/novena/Makefile | 4 +
> arch/arm/boards/novena/board.c | 109 +++++++++++
> arch/arm/boards/novena/ddr_regs.h | 119 ++++++++++++
> .../boards/novena/flash-header-novena.imxcfg | 6 +
> arch/arm/boards/novena/lowlevel.c | 172 ++++++++++++++++++
> arch/arm/configs/imx_v7_defconfig | 1 +
> arch/arm/dts/Makefile | 1 +
> arch/arm/dts/imx6q-novena.dts | 18 ++
> arch/arm/mach-imx/Kconfig | 9 +
> images/Makefile.imx | 2 +
> 11 files changed, 442 insertions(+)
> create mode 100644 arch/arm/boards/novena/Makefile
> create mode 100644 arch/arm/boards/novena/board.c
> create mode 100644 arch/arm/boards/novena/ddr_regs.h
> create mode 100644 arch/arm/boards/novena/flash-header-novena.imxcfg
> create mode 100644 arch/arm/boards/novena/lowlevel.c
> create mode 100644 arch/arm/dts/imx6q-novena.dts
>
> --
> 2.39.1
>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 7+ messages in thread