All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx
@ 2018-05-24  8:41 Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 02/11] sysreset: Add get_status method Mario Six
                   ` (9 more replies)
  0 siblings, 10 replies; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:41 UTC (permalink / raw)
  To: u-boot

Add a RAM driver for the MPC83xx architecture.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Converted some #ifdefs to if (IS_ENABLED(...))
* Added driver files to MAINTAINERS

v1 -> v2:
No changes

---
 MAINTAINERS                                |   2 +
 arch/powerpc/cpu/mpc83xx/spd_sdram.c       |   4 +
 drivers/ram/Kconfig                        |   8 +
 drivers/ram/Makefile                       |   1 +
 drivers/ram/mpc83xx_sdram.c                | 969 +++++++++++++++++++++++++++++
 include/dt-bindings/memory/mpc83xx-sdram.h | 151 +++++
 include/mpc83xx.h                          |   6 +
 7 files changed, 1141 insertions(+)
 create mode 100644 drivers/ram/mpc83xx_sdram.c
 create mode 100644 include/dt-bindings/memory/mpc83xx-sdram.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5670917b41b..139f7af26ac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -468,6 +468,8 @@ POWERPC MPC83XX
 M:	Mario Six <mario.six@gdsys.cc>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-mpc83xx.git
+F:	drivers/ram/mpc83xx_sdram.c
+F:	include/dt-bindings/memory/mpc83xx-sdram.h
 F:	arch/powerpc/cpu/mpc83xx/
 F:	arch/powerpc/include/asm/arch-mpc83xx/

diff --git a/arch/powerpc/cpu/mpc83xx/spd_sdram.c b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
index bbc8ef03c7b..328a018eb6f 100644
--- a/arch/powerpc/cpu/mpc83xx/spd_sdram.c
+++ b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
@@ -10,6 +10,8 @@
  * Xianghua Xiao (X.Xiao at motorola.com)
  */

+#ifndef CONFIG_MPC83XX_SDRAM
+
 #include <common.h>
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -924,3 +926,5 @@ void ddr_enable_ecc(unsigned int dram_size)
 	__asm__ __volatile__ ("isync");
 }
 #endif	/* CONFIG_DDR_ECC */
+
+#endif /* !CONFIG_MPC83XX_SDRAM */
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index 496e2b793bd..18532e71be9 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -34,4 +34,12 @@ config STM32_SDRAM
 	  support external memories like sdram, psram & nand.
 	  This driver is for the sdram memory interface with the FMC.

+config MPC83XX_SDRAM
+	bool "Enable MPC83XX SDRAM support"
+	depends on RAM
+	help
+	  Enable support for the internal DDR Memory Controller of the MPC83xx
+	  family of SoCs. Both static configurations, as well as configuring
+	  the RAM through the use of SPD is supported via device tree settings.
+
 source "drivers/ram/stm32mp1/Kconfig"
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 3820d03aa41..4ad3604d163 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -5,6 +5,7 @@
 # SPDX-License-Identifier:      GPL-2.0+
 #
 obj-$(CONFIG_RAM) += ram-uclass.o
+obj-$(CONFIG_MPC83XX_SDRAM) += mpc83xx_sdram.o
 obj-$(CONFIG_SANDBOX) += sandbox_ram.o
 obj-$(CONFIG_STM32MP1_DDR) += stm32mp1/
 obj-$(CONFIG_STM32_SDRAM) += stm32_sdram.o
diff --git a/drivers/ram/mpc83xx_sdram.c b/drivers/ram/mpc83xx_sdram.c
new file mode 100644
index 00000000000..9d31d28ce0e
--- /dev/null
+++ b/drivers/ram/mpc83xx_sdram.c
@@ -0,0 +1,969 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <dt-bindings/memory/mpc83xx-sdram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CSCONFIG_ENABLE			0x80000000
+
+#define BANK_BITS_2		0x00000000
+#define BANK_BITS_3		0x00004000
+
+#define ROW_BITS_12		0x00000000
+#define ROW_BITS_13		0x00000100
+#define ROW_BITS_14		0x00000200
+
+#define COL_BITS_8		0x00000000
+#define COL_BITS_9		0x00000001
+#define COL_BITS_10		0x00000002
+#define COL_BITS_11		0x00000003
+
+#define TIMING_CFG3_EXT_REFREC_SHIFT	16
+
+#define TIMING_CFG0_RWT_SHIFT		30
+#define TIMING_CFG0_WRT_SHIFT		28
+#define TIMING_CFG0_RRT_SHIFT		26
+#define TIMING_CFG0_WWT_SHIFT		24
+#define TIMING_CFG0_ACT_PD_EXIT_SHIFT	20
+#define TIMING_CFG0_PRE_PD_EXIT_SHIFT	16
+#define TIMING_CFG0_ODT_PD_EXIT_SHIFT	8
+#define TIMING_CFG0_MRS_CYC_SHIFT	0
+
+#define TIMING_CFG1_PRETOACT_SHIFT	28
+#define TIMING_CFG1_ACTTOPRE_SHIFT	24
+#define TIMING_CFG1_ACTTORW_SHIFT	20
+#define TIMING_CFG1_CASLAT_SHIFT	16
+#define TIMING_CFG1_REFREC_SHIFT	12
+#define TIMING_CFG1_WRREC_SHIFT		8
+#define TIMING_CFG1_ACTTOACT_SHIFT	4
+#define TIMING_CFG1_WRTORD_SHIFT	0
+
+#define TIMING_CFG2_CPO_SHIFT		23
+#define TIMING_CFG2_WR_DATA_DELAY_SHIFT	10
+#define TIMING_CFG2_ADD_LAT_SHIFT	28
+#define TIMING_CFG2_WR_LAT_DELAY_SHIFT	19
+#define TIMING_CFG2_RD_TO_PRE_SHIFT	13
+#define TIMING_CFG2_CKE_PLS_SHIFT	6
+#define TIMING_CFG2_FOUR_ACT_SHIFT	0
+
+#define SDRAM_CFG_SREN_SHIFT		(31 - 1)
+#define SDRAM_CFG_ECC_EN_SHIFT		(31 - 2)
+#define SDRAM_CFG_RD_EN_SHIFT		(31 - 3)
+#define SDRAM_CFG_SDRAM_TYPE_SHIFT	(31 - 7)
+#define SDRAM_CFG_DYN_PWR_SHIFT		(31 - 10)
+#define SDRAM_CFG_DBW_SHIFT		(31 - 12)
+#define SDRAM_CFG_NCAP_SHIFT		(31 - 14)
+#define SDRAM_CFG_2T_EN_SHIFT		(31 - 16)
+#define SDRAM_CFG_BA_INTLV_CTL_SHIFT	(31 - 23)
+#define SDRAM_CFG_PCHB8_SHIFT		(31 - 27)
+#define SDRAM_CFG_HSE_SHIFT		(31 - 28)
+#define SDRAM_CFG_BI_SHIFT		(31 - 31)
+
+#define SDRAM_CFG2_FRC_SR_SHIFT	(31 - 0)
+#define SDRAM_CFG2_DLL_RST_DIS	(31 - 2)
+#define SDRAM_CFG2_DQS_CFG	(31 - 5)
+#define SDRAM_CFG2_ODT_CFG	(31 - 10)
+#define SDRAM_CFG2_NUM_PR	(31 - 19)
+
+#define SDRAM_MODE_ESD_SHIFT		16
+#define SDRAM_MODE_SD_SHIFT		0
+
+#define SDRAM_MODE2_ESD2_SHIFT		(31 - 15)
+#define SDRAM_MODE2_ESD3_SHIFT		(31 - 31)
+
+#define SDRAM_INTERVAL_REFINT_SHIFT	16
+#define SDRAM_INTERVAL_BSTOPRE_SHIFT	0
+
+#define SDRAM_CFG_MEM_EN              0x80000000
+
+int dram_init(void)
+{
+	struct udevice *ram_ctrl;
+	int ret;
+
+	/* Current assumption: There is only one RAM controller */
+	ret = uclass_first_device_err(UCLASS_RAM, &ram_ctrl);
+
+	if (ret) {
+		debug("uclass_first_device_err failed: %d\n", ret);
+		return ret;
+	}
+
+	/* Set gd->ram_size? */
+
+	return 0;
+}
+
+phys_size_t get_effective_memsize(void)
+{
+	if (!IS_ENABLED(CONFIG_VERY_BIG_RAM))
+		return gd->ram_size;
+
+	/* limit stack to what we can reasonable map */
+	return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ?
+		CONFIG_MAX_MEM_MAPPED : gd->ram_size);
+}
+
+struct mpc83xx_sdram_priv {
+	ulong total_size;
+};
+
+int mpc83xx_sdram_static_init(ofnode node, u32 cs, u32 mapaddr, u32 size)
+{
+	immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	u32 msize = size;
+	u32 msize_log2 = __ilog2(msize);
+	u32 auto_precharge, odt_rd_cfg, odt_wr_cfg, bank_bits, row_bits,
+	    col_bits;
+	u32 bank_bits_mask, row_bits_mask, col_bits_mask;
+
+	/* Configure the DDR local access window */
+	out_be32(&im->sysconf.ddrlaw[cs].bar, mapaddr & 0xfffff000);
+	out_be32(&im->sysconf.ddrlaw[cs].ar, LBLAWAR_EN | (msize_log2 - 1));
+
+	out_be32(&im->ddr.csbnds[cs].csbnds, (msize - 1) >> 24);
+
+	auto_precharge = ofnode_read_u32_default(node, "auto_precharge", 0);
+	switch (auto_precharge) {
+	case AUTO_PRECHARGE_ENABLE:
+	case AUTO_PRECHARGE_DISABLE:
+		break;
+	default:
+		debug("auto_precharge value invalid.\n");
+		return -EINVAL;
+	}
+
+	odt_rd_cfg = ofnode_read_u32_default(node, "odt_rd_cfg", 0);
+	switch (odt_rd_cfg) {
+	case ODT_RD_ONLY_OTHER_DIMM:
+		if (!IS_ENABLED(CONFIG_MPC8360) &&
+		    !IS_ENABLED(CONFIG_MPC837x)) {
+			debug("odt_rd_cfg value invalid.\n");
+			return -EINVAL;
+		}
+		/* fall through */
+	case ODT_RD_NEVER:
+	case ODT_RD_ONLY_CURRENT:
+	case ODT_RD_ONLY_OTHER_CS:
+		if (!IS_ENABLED(CONFIG_MPC830x) &&
+		    !IS_ENABLED(CONFIG_MPC831x) &&
+		    !IS_ENABLED(CONFIG_MPC8360) &&
+		    !IS_ENABLED(CONFIG_MPC837x)) {
+			debug("odt_rd_cfg value invalid.\n");
+			return -EINVAL;
+		}
+		/* fall through */
+	/* MPC832x only knows this value */
+	case ODT_RD_ALL:
+		break;
+	default:
+		debug("odt_rd_cfg value invalid.\n");
+		return -EINVAL;
+	}
+
+	odt_wr_cfg = ofnode_read_u32_default(node, "odt_wr_cfg", 0);
+	switch (odt_wr_cfg) {
+	case ODT_WR_ONLY_OTHER_DIMM:
+		if (!IS_ENABLED(CONFIG_MPC8360) &&
+		    !IS_ENABLED(CONFIG_MPC837x)) {
+			debug("odt_wr_cfg value invalid.\n");
+			return -EINVAL;
+		}
+		/* fall through */
+	case ODT_WR_NEVER:
+	case ODT_WR_ONLY_CURRENT:
+	case ODT_WR_ONLY_OTHER_CS:
+		if (!IS_ENABLED(CONFIG_MPC830x) &&
+		    !IS_ENABLED(CONFIG_MPC831x) &&
+		    !IS_ENABLED(CONFIG_MPC8360) &&
+		    !IS_ENABLED(CONFIG_MPC837x)) {
+			debug("odt_wr_cfg value invalid.\n");
+			return -EINVAL;
+		}
+		/* fall through */
+	/* MPC832x only knows this value */
+	case ODT_WR_ALL:
+		break;
+	default:
+		debug("odt_wr_cfg value invalid.\n");
+		return -EINVAL;
+	}
+
+	bank_bits = ofnode_read_u32_default(node, "bank_bits", 0);
+	switch (bank_bits) {
+	case 2:
+		bank_bits_mask = BANK_BITS_2;
+		break;
+	case 3:
+		bank_bits_mask = BANK_BITS_3;
+		break;
+	default:
+		debug("bank_bits value invalid.\n");
+		return -EINVAL;
+	}
+
+	row_bits = ofnode_read_u32_default(node, "row_bits", 0);
+	switch (row_bits) {
+	case 12:
+		row_bits_mask = ROW_BITS_12;
+		break;
+	case 13:
+		row_bits_mask = ROW_BITS_13;
+		break;
+	case 14:
+		row_bits_mask = ROW_BITS_14;
+		break;
+	default:
+		debug("row_bits value invalid.\n");
+		return -EINVAL;
+	}
+
+	col_bits = ofnode_read_u32_default(node, "col_bits", 0);
+	switch (col_bits) {
+	case 8:
+		col_bits_mask = COL_BITS_8;
+		break;
+	case 9:
+		col_bits_mask = COL_BITS_9;
+		break;
+	case 10:
+		col_bits_mask = COL_BITS_10;
+		break;
+	case 11:
+		col_bits_mask = COL_BITS_11;
+		break;
+	default:
+		debug("col_bits value invalid.\n");
+		return -EINVAL;
+	}
+
+	/* Write CS config value */
+	out_be32(&im->ddr.cs_config[cs], CSCONFIG_ENABLE | auto_precharge |
+					 odt_rd_cfg | odt_wr_cfg |
+					 bank_bits_mask | row_bits_mask |
+					 col_bits_mask);
+	return 0;
+}
+
+int mpc83xx_sdram_spd_init(ofnode node, u32 cs, u32 mapaddr, u32 size)
+{
+	return 0;
+}
+
+static int mpc83xx_sdram_ofdata_to_platdata(struct udevice *dev)
+{
+	return 0;
+}
+
+static int mpc83xx_sdram_probe(struct udevice *dev)
+{
+	struct mpc83xx_sdram_priv *priv = dev_get_priv(dev);
+	immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	int res = 0;
+	ofnode subnode;
+	u32 dso, pz_override, nz_override, odt_term, ddr_type, mvref_sel, m_odr;
+	u32 ddrcdr;
+	u32 clock_adjust;
+	u32 ext_refresh_rec, ext_refresh_rec_mask;
+	u32 read_to_write, write_to_read, read_to_read, write_to_write,
+	    active_powerdown_exit, precharge_powerdown_exit,
+	    odt_powerdown_exit, mode_reg_set_cycle;
+	u32 timing_cfg_0;
+	u32 precharge_to_activate, activate_to_precharge,
+	    activate_to_readwrite, mcas_latency, refresh_recovery,
+	    last_data_to_precharge, activate_to_activate,
+	    last_write_data_to_read;
+	u32 timing_cfg_1;
+	u32 additive_latency, mcas_to_preamble_override, write_latency,
+	    read_to_precharge, write_cmd_to_write_data,
+	    minimum_cke_pulse_width, four_activates_window;
+	u32 timing_cfg_2;
+	u32 self_refresh, ecc, registered_dram, sdram_type,
+	    dynamic_power_management, databus_width, nc_auto_precharge,
+	    timing_2t, bank_interleaving_ctrl, precharge_bit_8, half_strength,
+	    bypass_initialization;
+	u32 sdram_cfg;
+	u32 force_self_refresh, dll_reset, dqs_config, odt_config,
+	    posted_refreshes;
+	u32 sdram_cfg2;
+	u32 refresh_interval, precharge_interval, sdmode, esdmode, esdmode2,
+	    esdmode3;
+	u32 sdram_interval;
+	u32 sdram_mode;
+	u32 sdram_mode2;
+
+	priv->total_size = 0;
+
+	/* Disable both banks initially (might be re-enabled in loop below) */
+	out_be32(&im->ddr.cs_config[0], 0);
+	out_be32(&im->ddr.cs_config[1], 0);
+
+	dso = dev_read_u32_default(dev, "driver_software_override", 0);
+	if (dso > 1) {
+		debug("driver_software_override value invalid.\n");
+		return -EINVAL;
+	}
+
+	pz_override = dev_read_u32_default(dev, "p_impedance_override", 0);
+
+	switch (pz_override) {
+	case DSO_P_IMPEDANCE_HIGHEST_Z:
+	case DSO_P_IMPEDANCE_MUCH_HIGHER_Z:
+	case DSO_P_IMPEDANCE_HIGHER_Z:
+	case DSO_P_IMPEDANCE_NOMINAL:
+	case DSO_P_IMPEDANCE_LOWER_Z:
+		break;
+	default:
+		debug("p_impedance_override value invalid.\n");
+		return -EINVAL;
+	}
+
+	nz_override = dev_read_u32_default(dev, "n_impedance_override", 0);
+
+	switch (nz_override) {
+	case DSO_N_IMPEDANCE_HIGHEST_Z:
+	case DSO_N_IMPEDANCE_MUCH_HIGHER_Z:
+	case DSO_N_IMPEDANCE_HIGHER_Z:
+	case DSO_N_IMPEDANCE_NOMINAL:
+	case DSO_N_IMPEDANCE_LOWER_Z:
+		break;
+	default:
+		debug("n_impedance_override value invalid.\n");
+		return -EINVAL;
+	}
+
+	odt_term = dev_read_u32_default(dev, "odt_termination_value", 0);
+	if (odt_term > 1) {
+		debug("odt_termination_value value invalid.\n");
+		return -EINVAL;
+	}
+
+	ddr_type = dev_read_u32_default(dev, "ddr_type", 0);
+	if (ddr_type > 1) {
+		debug("ddr_type value invalid.\n");
+		return -EINVAL;
+	}
+
+	mvref_sel = dev_read_u32_default(dev, "mvref_sel", 0);
+	if (mvref_sel > 1) {
+		debug("mvref_sel value invalid.\n");
+		return -EINVAL;
+	}
+
+	m_odr = dev_read_u32_default(dev, "m_odr", 0);
+	if (mvref_sel > 1) {
+		debug("m_odr value invalid.\n");
+		return -EINVAL;
+	}
+
+	ddrcdr = dso << (31 - 1) |
+		 pz_override << (31 - 5) |
+		 nz_override << (31 - 9) |
+		 odt_term << (31 - 12) |
+		 ddr_type << (31 - 13) |
+		 mvref_sel << (31 - 29) |
+		 m_odr << (31 - 30) | 1;
+
+	/* Configure the DDR control driver register */
+	out_be32(&im->sysconf.ddrcdr, ddrcdr);
+
+	dev_for_each_subnode(subnode, dev) {
+		u32 val[3];
+		u32 cs, addr, size;
+
+		/* CS, map address, size -> three values */
+		ofnode_read_u32_array(subnode, "reg", val, 3);
+
+		cs = val[0];
+		addr = val[1];
+		size = val[2];
+
+		if (cs > 1) {
+			debug("chip select value invalid.\n");
+			return -EINVAL;
+		}
+
+		/* TODO: Sanity check for size. */
+
+		if (ofnode_read_bool(subnode, "read-spd"))
+			res = mpc83xx_sdram_spd_init(subnode, cs, addr, size);
+		else
+			res = mpc83xx_sdram_static_init(subnode, cs, addr,
+							size);
+		if (res)
+			return res;
+	};
+
+	/* TODO: This should only occur for static configuration */
+
+	clock_adjust = dev_read_u32_default(dev, "clock_adjust", 0);
+	switch (clock_adjust) {
+	case CLOCK_ADJUST_025:
+	case CLOCK_ADJUST_05:
+	case CLOCK_ADJUST_075:
+	case CLOCK_ADJUST_1:
+		break;
+	default:
+		debug("clock_adjust value invalid.\n");
+		return -EINVAL;
+	}
+
+	/* Configure the DDR SDRAM Clock Control register */
+	out_be32(&im->ddr.sdram_clk_cntl, clock_adjust);
+
+	ext_refresh_rec = dev_read_u32_default(dev, "ext_refresh_rec", 0);
+	switch (ext_refresh_rec) {
+	case 0:
+		ext_refresh_rec_mask = 0 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 16:
+		ext_refresh_rec_mask = 1 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 32:
+		ext_refresh_rec_mask = 2 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 48:
+		ext_refresh_rec_mask = 3 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 64:
+		ext_refresh_rec_mask = 4 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 80:
+		ext_refresh_rec_mask = 5 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 96:
+		ext_refresh_rec_mask = 6 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	case 112:
+		ext_refresh_rec_mask = 7 << TIMING_CFG3_EXT_REFREC_SHIFT;
+		break;
+	default:
+		debug("ext_refresh_rec value invalid.\n");
+		return -EINVAL;
+	}
+
+	/* Configure the DDR SDRAM Timing Configuration 3 register */
+	out_be32(&im->ddr.timing_cfg_3, ext_refresh_rec_mask);
+
+	read_to_write = dev_read_u32_default(dev, "read_to_write", 0);
+	if (read_to_write > 3) {
+		debug("read_to_write value invalid.\n");
+		return -EINVAL;
+	}
+
+	write_to_read = dev_read_u32_default(dev, "write_to_read", 0);
+	if (write_to_read > 3) {
+		debug("write_to_read value invalid.\n");
+		return -EINVAL;
+	}
+
+	read_to_read = dev_read_u32_default(dev, "read_to_read", 0);
+	if (read_to_read > 3) {
+		debug("read_to_read value invalid.\n");
+		return -EINVAL;
+	}
+
+	write_to_write = dev_read_u32_default(dev, "write_to_write", 0);
+	if (write_to_write > 3) {
+		debug("write_to_write value invalid.\n");
+		return -EINVAL;
+	}
+
+	active_powerdown_exit =
+		dev_read_u32_default(dev, "active_powerdown_exit", 0);
+	if (active_powerdown_exit > 7) {
+		debug("active_powerdown_exit value invalid.\n");
+		return -EINVAL;
+	}
+
+	precharge_powerdown_exit =
+		dev_read_u32_default(dev, "precharge_powerdown_exit", 0);
+	if (precharge_powerdown_exit > 7) {
+		debug("precharge_powerdown_exit value invalid.\n");
+		return -EINVAL;
+	}
+
+	odt_powerdown_exit = dev_read_u32_default(dev, "odt_powerdown_exit", 0);
+	if (odt_powerdown_exit > 15) {
+		debug("odt_powerdown_exit value invalid.\n");
+		return -EINVAL;
+	}
+
+	mode_reg_set_cycle = dev_read_u32_default(dev, "mode_reg_set_cycle", 0);
+	if (mode_reg_set_cycle > 15) {
+		debug("mode_reg_set_cycle value invalid.\n");
+		return -EINVAL;
+	}
+
+	timing_cfg_0 = read_to_write << TIMING_CFG0_RWT_SHIFT |
+		       write_to_read << TIMING_CFG0_WRT_SHIFT |
+		       read_to_read << TIMING_CFG0_RRT_SHIFT |
+		       write_to_write << TIMING_CFG0_WWT_SHIFT |
+		       active_powerdown_exit << TIMING_CFG0_ACT_PD_EXIT_SHIFT |
+		       precharge_powerdown_exit << TIMING_CFG0_PRE_PD_EXIT_SHIFT |
+		       odt_powerdown_exit << TIMING_CFG0_ODT_PD_EXIT_SHIFT |
+		       mode_reg_set_cycle << TIMING_CFG0_MRS_CYC_SHIFT;
+
+	out_be32(&im->ddr.timing_cfg_0, timing_cfg_0);
+
+	precharge_to_activate =
+		dev_read_u32_default(dev, "precharge_to_activate", 0);
+	if (precharge_to_activate > 7 || precharge_to_activate == 0) {
+		debug("precharge_to_activate value invalid.\n");
+		return -EINVAL;
+	}
+
+	activate_to_precharge =
+		dev_read_u32_default(dev, "activate_to_precharge", 0);
+	if (activate_to_precharge > 15 || activate_to_precharge == 0) {
+		debug("activate_to_precharge value invalid.\n");
+		return -EINVAL;
+	}
+
+	activate_to_readwrite =
+		dev_read_u32_default(dev, "activate_to_readwrite", 0);
+	if (activate_to_readwrite > 7 || activate_to_readwrite == 0) {
+		debug("activate_to_readwrite value invalid.\n");
+		return -EINVAL;
+	}
+
+	/* TODO: MPC8308 only supports caslat >= 3 clocks */
+	mcas_latency = dev_read_u32_default(dev, "mcas_latency", 0);
+	switch (mcas_latency) {
+	case CASLAT_20:
+	case CASLAT_25:
+	case CASLAT_30:
+	case CASLAT_35:
+	case CASLAT_40:
+	case CASLAT_45:
+	case CASLAT_50:
+		break;
+	default:
+		debug("ext_refresh_rec value invalid.\n");
+		return -EINVAL;
+	}
+
+	refresh_recovery = dev_read_u32_default(dev, "refresh_recovery", 0);
+	if (refresh_recovery > 23 || refresh_recovery < 8) {
+		debug("refresh_recovery value invalid.\n");
+		return -EINVAL;
+	}
+
+	last_data_to_precharge =
+		dev_read_u32_default(dev, "last_data_to_precharge", 0);
+	if (last_data_to_precharge > 7 || last_data_to_precharge == 0) {
+		debug("last_data_to_precharge value invalid.\n");
+		return -EINVAL;
+	}
+
+	activate_to_activate =
+		dev_read_u32_default(dev, "activate_to_activate", 0);
+	if (activate_to_activate > 7 || activate_to_activate == 0) {
+		debug("activate_to_activate value invalid.\n");
+		return -EINVAL;
+	}
+
+	last_write_data_to_read =
+		dev_read_u32_default(dev, "last_write_data_to_read", 0);
+	if (last_write_data_to_read > 7 || last_write_data_to_read == 0) {
+		debug("last_write_data_to_read value invalid.\n");
+		return -EINVAL;
+	}
+
+	timing_cfg_1 = precharge_to_activate << TIMING_CFG1_PRETOACT_SHIFT |
+		       activate_to_precharge << TIMING_CFG1_ACTTOPRE_SHIFT |
+		       activate_to_readwrite << TIMING_CFG1_ACTTORW_SHIFT |
+		       mcas_latency << TIMING_CFG1_CASLAT_SHIFT |
+		       (refresh_recovery - 8) << TIMING_CFG1_REFREC_SHIFT |
+		       last_data_to_precharge << TIMING_CFG1_WRREC_SHIFT |
+		       activate_to_activate << TIMING_CFG1_ACTTOACT_SHIFT |
+		       last_write_data_to_read << TIMING_CFG1_WRTORD_SHIFT;
+
+	/* Configure the DDR SDRAM Timing Configuration 1 register */
+	out_be32(&im->ddr.timing_cfg_1, timing_cfg_1);
+
+	additive_latency = dev_read_u32_default(dev, "additive_latency", 0);
+	if (additive_latency > 5) {
+		debug("additive_latency value invalid.\n");
+		return -EINVAL;
+	}
+
+	mcas_to_preamble_override =
+		dev_read_u32_default(dev, "mcas_to_preamble_override", 0);
+	switch (mcas_to_preamble_override) {
+	case READ_LAT_PLUS_1:
+	case READ_LAT:
+	case READ_LAT_PLUS_1_4:
+	case READ_LAT_PLUS_1_2:
+	case READ_LAT_PLUS_3_4:
+	case READ_LAT_PLUS_5_4:
+	case READ_LAT_PLUS_3_2:
+	case READ_LAT_PLUS_7_4:
+	case READ_LAT_PLUS_2:
+	case READ_LAT_PLUS_9_4:
+	case READ_LAT_PLUS_5_2:
+	case READ_LAT_PLUS_11_4:
+	case READ_LAT_PLUS_3:
+	case READ_LAT_PLUS_13_4:
+	case READ_LAT_PLUS_7_2:
+	case READ_LAT_PLUS_15_4:
+	case READ_LAT_PLUS_4:
+	case READ_LAT_PLUS_17_4:
+	case READ_LAT_PLUS_9_2:
+	case READ_LAT_PLUS_19_4:
+		break;
+	default:
+		debug("mcas_to_preamble_override value invalid.\n");
+		return -EINVAL;
+	}
+
+	write_latency = dev_read_u32_default(dev, "write_latency", 0);
+	if (write_latency > 7 || write_latency == 0) {
+		debug("write_latency value invalid.\n");
+		return -EINVAL;
+	}
+
+	read_to_precharge = dev_read_u32_default(dev, "read_to_precharge", 0);
+	if (read_to_precharge > 4 || read_to_precharge == 0) {
+		debug("read_to_precharge value invalid.\n");
+		return -EINVAL;
+	}
+
+	write_cmd_to_write_data =
+		dev_read_u32_default(dev, "write_cmd_to_write_data", 0);
+	switch (write_cmd_to_write_data) {
+	case CLOCK_DELAY_0:
+	case CLOCK_DELAY_1_4:
+	case CLOCK_DELAY_1_2:
+	case CLOCK_DELAY_3_4:
+	case CLOCK_DELAY_1:
+	case CLOCK_DELAY_5_4:
+	case CLOCK_DELAY_3_2:
+		break;
+	default:
+		debug("write_cmd_to_write_data value invalid.\n");
+		return -EINVAL;
+	}
+
+	minimum_cke_pulse_width =
+		dev_read_u32_default(dev, "minimum_cke_pulse_width", 0);
+	if (minimum_cke_pulse_width > 4 || minimum_cke_pulse_width == 0) {
+		debug("minimum_cke_pulse_width value invalid.\n");
+		return -EINVAL;
+	}
+
+	four_activates_window =
+		dev_read_u32_default(dev, "four_activates_window", 0);
+	if (four_activates_window > 20 || four_activates_window == 0) {
+		debug("four_activates_window value invalid.\n");
+		return -EINVAL;
+	}
+
+	timing_cfg_2 = additive_latency << TIMING_CFG2_ADD_LAT_SHIFT |
+		       mcas_to_preamble_override << TIMING_CFG2_CPO_SHIFT |
+		       write_latency << TIMING_CFG2_WR_LAT_DELAY_SHIFT |
+		       read_to_precharge << TIMING_CFG2_RD_TO_PRE_SHIFT |
+		       write_cmd_to_write_data << TIMING_CFG2_WR_DATA_DELAY_SHIFT |
+		       minimum_cke_pulse_width << TIMING_CFG2_CKE_PLS_SHIFT |
+		       four_activates_window << TIMING_CFG2_FOUR_ACT_SHIFT;
+
+	out_be32(&im->ddr.timing_cfg_2, timing_cfg_2);
+
+	self_refresh = dev_read_u32_default(dev, "self_refresh", 0);
+	switch (self_refresh) {
+	case SREN_DISABLE:
+	case SREN_ENABLE:
+		break;
+	default:
+		debug("self_refresh value invalid.\n");
+		return -EINVAL;
+	}
+
+	ecc = dev_read_u32_default(dev, "ecc", 0);
+	switch (ecc) {
+	case ECC_DISABLE:
+	case ECC_ENABLE:
+		break;
+	default:
+		debug("ecc value invalid.\n");
+		return -EINVAL;
+	}
+
+	registered_dram = dev_read_u32_default(dev, "registered_dram", 0);
+	switch (registered_dram) {
+	case RD_DISABLE:
+	case RD_ENABLE:
+		break;
+	default:
+		debug("registered_dram value invalid.\n");
+		return -EINVAL;
+	}
+
+	sdram_type = dev_read_u32_default(dev, "sdram_type", 0);
+	switch (sdram_type) {
+	case TYPE_DDR1:
+	case TYPE_DDR2:
+		break;
+	default:
+		debug("sdram_type value invalid.\n");
+		return -EINVAL;
+	}
+
+	dynamic_power_management =
+		dev_read_u32_default(dev, "dynamic_power_management", 0);
+	switch (dynamic_power_management) {
+	case DYN_PWR_DISABLE:
+	case DYN_PWR_ENABLE:
+		break;
+	default:
+		debug("dynamic_power_management value invalid.\n");
+		return -EINVAL;
+	}
+
+	databus_width = dev_read_u32_default(dev, "databus_width", 0);
+	switch (databus_width) {
+	case DATA_BUS_WIDTH_16:
+	case DATA_BUS_WIDTH_32:
+		break;
+	default:
+		debug("databus_width value invalid.\n");
+		return -EINVAL;
+	}
+
+	nc_auto_precharge = dev_read_u32_default(dev, "nc_auto_precharge", 0);
+	switch (nc_auto_precharge) {
+	case NCAP_DISABLE:
+	case NCAP_ENABLE:
+		break;
+	default:
+		debug("nc_auto_precharge value invalid.\n");
+		return -EINVAL;
+	}
+
+	timing_2t = dev_read_u32_default(dev, "timing_2t", 0);
+	switch (timing_2t) {
+	case TIMING_1T:
+	case TIMING_2T:
+		break;
+	default:
+		debug("timing_2t value invalid.\n");
+		return -EINVAL;
+	}
+
+	bank_interleaving_ctrl =
+		dev_read_u32_default(dev, "bank_interleaving_ctrl", 0);
+	switch (bank_interleaving_ctrl) {
+	case INTERLEAVE_NONE:
+	case INTERLEAVE_1_AND_2:
+		break;
+	default:
+		debug("bank_interleaving_ctrl value invalid.\n");
+		return -EINVAL;
+	}
+
+	precharge_bit_8 = dev_read_u32_default(dev, "precharge_bit_8", 0);
+	switch (precharge_bit_8) {
+	case PRECHARGE_MA_10:
+	case PRECHARGE_MA_8:
+		break;
+	default:
+		debug("precharge_bit_8 value invalid.\n");
+		return -EINVAL;
+	}
+
+	half_strength = dev_read_u32_default(dev, "half_strength", 0);
+	switch (half_strength) {
+	case STRENGTH_FULL:
+	case STRENGTH_HALF:
+		break;
+	default:
+		debug("half_strength value invalid.\n");
+		return -EINVAL;
+	}
+
+	bypass_initialization =
+		dev_read_u32_default(dev, "bypass_initialization", 0);
+	switch (bypass_initialization) {
+	case INITIALIZATION_DONT_BYPASS:
+	case INITIALIZATION_BYPASS:
+		break;
+	default:
+		debug("bypass_initialization value invalid.\n");
+		return -EINVAL;
+	}
+
+	sdram_cfg = self_refresh << SDRAM_CFG_SREN_SHIFT |
+		    ecc << SDRAM_CFG_ECC_EN_SHIFT |
+		    registered_dram << SDRAM_CFG_RD_EN_SHIFT |
+		    sdram_type << SDRAM_CFG_SDRAM_TYPE_SHIFT |
+		    dynamic_power_management << SDRAM_CFG_DYN_PWR_SHIFT |
+		    databus_width << SDRAM_CFG_DBW_SHIFT |
+		    nc_auto_precharge << SDRAM_CFG_NCAP_SHIFT |
+		    timing_2t << SDRAM_CFG_2T_EN_SHIFT |
+		    bank_interleaving_ctrl << SDRAM_CFG_BA_INTLV_CTL_SHIFT |
+		    precharge_bit_8 << SDRAM_CFG_PCHB8_SHIFT |
+		    half_strength << SDRAM_CFG_HSE_SHIFT |
+		    bypass_initialization << SDRAM_CFG_BI_SHIFT;
+
+	out_be32(&im->ddr.sdram_cfg, sdram_cfg);
+
+	force_self_refresh = dev_read_u32_default(dev, "force_self_refresh", 0);
+	switch (force_self_refresh) {
+	case MODE_NORMAL:
+	case MODE_REFRESH:
+		break;
+	default:
+		debug("force_self_refresh value invalid.\n");
+		return -EINVAL;
+	}
+
+	dll_reset = dev_read_u32_default(dev, "dll_reset", 0);
+	switch (dll_reset) {
+	case DLL_RESET_ENABLE:
+	case DLL_RESET_DISABLE:
+		break;
+	default:
+		debug("dll_reset value invalid.\n");
+		return -EINVAL;
+	}
+
+	dqs_config = dev_read_u32_default(dev, "dqs_config", 0);
+	switch (dqs_config) {
+	case DQS_TRUE:
+		break;
+	default:
+		debug("dqs_config value invalid.\n");
+		return -EINVAL;
+	}
+
+	odt_config = dev_read_u32_default(dev, "odt_config", 0);
+	switch (odt_config) {
+	case ODT_ASSERT_NEVER:
+	case ODT_ASSERT_WRITES:
+	case ODT_ASSERT_READS:
+	case ODT_ASSERT_ALWAYS:
+		break;
+	default:
+		debug("odt_config value invalid.\n");
+		return -EINVAL;
+	}
+
+	posted_refreshes = dev_read_u32_default(dev, "posted_refreshes", 0);
+	if (posted_refreshes > 8 || posted_refreshes == 0) {
+		debug("posted_refreshes value invalid.\n");
+		return -EINVAL;
+	}
+
+	sdram_cfg2 = force_self_refresh << SDRAM_CFG2_FRC_SR_SHIFT |
+		     dll_reset << SDRAM_CFG2_DLL_RST_DIS |
+		     dqs_config << SDRAM_CFG2_DQS_CFG |
+		     odt_config << SDRAM_CFG2_ODT_CFG |
+		     posted_refreshes << SDRAM_CFG2_NUM_PR;
+
+	out_be32(&im->ddr.sdram_cfg2, sdram_cfg2);
+
+	sdmode = dev_read_u32_default(dev, "sdmode", 0);
+	if (sdmode > 0xFFFF) {
+		debug("sdmode value invalid.\n");
+		return -EINVAL;
+	}
+
+	esdmode = dev_read_u32_default(dev, "esdmode", 0);
+	if (esdmode > 0xFFFF) {
+		debug("esdmode value invalid.\n");
+		return -EINVAL;
+	}
+
+	sdram_mode = sdmode << SDRAM_MODE_SD_SHIFT |
+		     esdmode << SDRAM_MODE_ESD_SHIFT;
+
+	out_be32(&im->ddr.sdram_mode, sdram_mode);
+
+	esdmode2 = dev_read_u32_default(dev, "esdmode2", 0);
+	if (esdmode2 > 0xFFFF) {
+		debug("esdmode2 value invalid.\n");
+		return -EINVAL;
+	}
+
+	esdmode3 = dev_read_u32_default(dev, "esdmode3", 0);
+	if (esdmode3 > 0xFFFF) {
+		debug("esdmode3 value invalid.\n");
+		return -EINVAL;
+	}
+
+	sdram_mode2 = esdmode2 << SDRAM_MODE2_ESD2_SHIFT |
+		      esdmode3 << SDRAM_MODE2_ESD3_SHIFT;
+
+	out_be32(&im->ddr.sdram_mode2, sdram_mode2);
+
+	refresh_interval = dev_read_u32_default(dev, "refresh_interval", 0);
+	if (refresh_interval > 0xFFFF) {
+		debug("refresh_interval value invalid.\n");
+		return -EINVAL;
+	}
+
+	precharge_interval = dev_read_u32_default(dev, "precharge_interval", 0);
+	if (precharge_interval > 0x3FFF) {
+		debug("precharge_interval value invalid.\n");
+		return -EINVAL;
+	}
+
+	sdram_interval = refresh_interval << SDRAM_INTERVAL_REFINT_SHIFT |
+			 precharge_interval << SDRAM_INTERVAL_BSTOPRE_SHIFT;
+
+	out_be32(&im->ddr.sdram_interval, sdram_interval);
+	sync();
+
+	/* Enable DDR controller */
+	setbits_be32(&im->ddr.sdram_cfg, SDRAM_CFG_MEM_EN);
+	sync();
+
+	dev_for_each_subnode(subnode, dev) {
+		u32 val[3];
+		u32 addr, size;
+
+		/* CS, map address, size -> three values */
+		ofnode_read_u32_array(subnode, "reg", val, 3);
+
+		addr = val[1];
+		size = val[2];
+
+		priv->total_size += get_ram_size((long int *)addr, size);
+	};
+
+	gd->ram_size = priv->total_size;
+
+	return 0;
+}
+
+static int mpc83xx_sdram_get_info(struct udevice *dev, struct ram_info *info)
+{
+	return 0;
+}
+
+static struct ram_ops mpc83xx_sdram_ops = {
+	.get_info = mpc83xx_sdram_get_info,
+};
+
+static const struct udevice_id mpc83xx_sdram_ids[] = {
+	{ .compatible = "fsl,mpc83xx-mem-controller" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mpc83xx_sdram) = {
+	.name = "mpc83xx_sdram",
+	.id = UCLASS_RAM,
+	.of_match = mpc83xx_sdram_ids,
+	.ops = &mpc83xx_sdram_ops,
+	.ofdata_to_platdata = mpc83xx_sdram_ofdata_to_platdata,
+	.probe = mpc83xx_sdram_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc83xx_sdram_priv),
+};
diff --git a/include/dt-bindings/memory/mpc83xx-sdram.h b/include/dt-bindings/memory/mpc83xx-sdram.h
new file mode 100644
index 00000000000..074f594bd31
--- /dev/null
+++ b/include/dt-bindings/memory/mpc83xx-sdram.h
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#ifndef DT_BINDINGS_MPC83XX_SDRAM_H
+#define DT_BINDINGS_MPC83XX_SDRAM_H
+
+#define DSO_DISABLE	0
+#define DSO_ENABLE	1
+
+#define DSO_P_IMPEDANCE_HIGHEST_Z	0x0
+#define DSO_P_IMPEDANCE_MUCH_HIGHER_Z	0x8
+#define DSO_P_IMPEDANCE_HIGHER_Z	0xC
+#define DSO_P_IMPEDANCE_NOMINAL		0xE
+#define DSO_P_IMPEDANCE_LOWER_Z		0xF
+
+#define DSO_N_IMPEDANCE_HIGHEST_Z	0x0
+#define DSO_N_IMPEDANCE_MUCH_HIGHER_Z	0x8
+#define DSO_N_IMPEDANCE_HIGHER_Z	0xC
+#define DSO_N_IMPEDANCE_NOMINAL		0xE
+#define DSO_N_IMPEDANCE_LOWER_Z		0xF
+
+#define ODT_TERMINATION_75_OHM		0
+#define ODT_TERMINATION_150_OHM		1
+
+#define DDR_TYPE_DDR2_1_8_VOLT		0
+#define DDR_TYPE_DDR1_2_5_VOLT		1
+
+#define MVREF_SEL_EXTERNAL		0
+#define MVREF_SEL_INTERNAL_GVDD		1
+
+#define M_ODR_ENABLE			0
+#define M_ODR_DISABLE			1
+
+/* CS config register */
+
+#define AUTO_PRECHARGE_ENABLE	0x00800000
+#define AUTO_PRECHARGE_DISABLE	0x00000000
+
+#define ODT_RD_NEVER		0x00000000
+#define ODT_RD_ONLY_CURRENT	0x00100000
+#define ODT_RD_ONLY_OTHER_CS	0x00200000
+#define ODT_RD_ONLY_OTHER_DIMM	0x00300000
+#define ODT_RD_ALL		0x00400000
+#define ODT_WR_NEVER		0x00000000
+#define ODT_WR_ONLY_CURRENT	0x00010000
+#define ODT_WR_ONLY_OTHER_CS	0x00020000
+#define ODT_WR_ONLY_OTHER_DIMM	0x00030000
+#define ODT_WR_ALL		0x00040000
+
+/* DDR SDRAM Clock Control register */
+
+#define CLOCK_ADJUST_025	0x01000000
+#define CLOCK_ADJUST_05		0x02000000
+#define CLOCK_ADJUST_075	0x03000000
+#define CLOCK_ADJUST_1		0x04000000
+
+#define CASLAT_20		0x3	/* CAS latency = 2.0 */
+#define CASLAT_25		0x4	/* CAS latency = 2.5 */
+#define CASLAT_30		0x5	/* CAS latency = 3.0 */
+#define CASLAT_35		0x6	/* CAS latency = 3.5 */
+#define CASLAT_40		0x7	/* CAS latency = 4.0 */
+#define CASLAT_45		0x8	/* CAS latency = 4.5 */
+#define CASLAT_50		0x9	/* CAS latency = 5.0 */
+
+#define READ_LAT_PLUS_1		0x0
+#define READ_LAT		0x2
+#define READ_LAT_PLUS_1_4	0x3
+#define READ_LAT_PLUS_1_2	0x4
+#define READ_LAT_PLUS_3_4	0x5
+/* #define READ_LAT_PLUS_1		0x6 */
+#define READ_LAT_PLUS_5_4	0x7
+#define READ_LAT_PLUS_3_2	0x8
+#define READ_LAT_PLUS_7_4	0x9
+#define READ_LAT_PLUS_2		0xA
+#define READ_LAT_PLUS_9_4	0xB
+#define READ_LAT_PLUS_5_2	0xC
+#define READ_LAT_PLUS_11_4	0xD
+#define READ_LAT_PLUS_3		0xE
+#define READ_LAT_PLUS_13_4	0xF
+#define READ_LAT_PLUS_7_2	0x10
+#define READ_LAT_PLUS_15_4	0x11
+#define READ_LAT_PLUS_4		0x12
+#define READ_LAT_PLUS_17_4	0x13
+#define READ_LAT_PLUS_9_2	0x14
+#define READ_LAT_PLUS_19_4	0x15
+
+#define CLOCK_DELAY_0		0x0
+#define CLOCK_DELAY_1_4		0x1
+#define CLOCK_DELAY_1_2		0x2
+#define CLOCK_DELAY_3_4		0x3
+#define CLOCK_DELAY_1		0x4
+#define CLOCK_DELAY_5_4		0x5
+#define CLOCK_DELAY_3_2		0x6
+
+/* DDR SDRAM Control Configuration */
+
+#define SREN_DISABLE	0x0
+#define SREN_ENABLE	0x1
+
+#define ECC_DISABLE	0x0
+#define ECC_ENABLE	0x1
+
+#define RD_DISABLE	0x0
+#define RD_ENABLE	0x1
+
+#define TYPE_DDR1	0x2
+#define TYPE_DDR2	0x3
+
+#define DYN_PWR_DISABLE		0x0
+#define DYN_PWR_ENABLE		0x1
+
+#define DATA_BUS_WIDTH_16	0x1
+#define DATA_BUS_WIDTH_32	0x2
+
+#define NCAP_DISABLE	0x0
+#define NCAP_ENABLE	0x1
+
+#define TIMING_1T	0x0
+#define TIMING_2T	0x1
+
+#define INTERLEAVE_NONE		0x0
+#define INTERLEAVE_1_AND_2	0x1
+
+#define PRECHARGE_MA_10		0x0
+#define PRECHARGE_MA_8		0x1
+
+#define STRENGTH_FULL		0x0
+#define STRENGTH_HALF		0x1
+
+#define INITIALIZATION_DONT_BYPASS	0x0
+#define INITIALIZATION_BYPASS		0x1
+
+/* DDR SDRAM Control Configuration 2 */
+
+#define MODE_NORMAL	0x0
+#define MODE_REFRESH	0x1
+
+#define DLL_RESET_ENABLE	0x0
+#define DLL_RESET_DISABLE	0x1
+
+#define DQS_TRUE	0x0
+
+#define ODT_ASSERT_NEVER	0x0
+#define ODT_ASSERT_WRITES	0x1
+#define ODT_ASSERT_READS	0x2
+#define ODT_ASSERT_ALWAYS	0x3
+
+#endif
diff --git a/include/mpc83xx.h b/include/mpc83xx.h
index e1e50ab6b50..a4c5bd38376 100644
--- a/include/mpc83xx.h
+++ b/include/mpc83xx.h
@@ -1110,6 +1110,8 @@
 #define CSBNDS_EA			0x000000FF
 #define CSBNDS_EA_SHIFT			24

+#ifndef CONFIG_MPC83XX_SDRAM
+
 /*
  * CSn_CONFIG - Chip Select Configuration Register
  */
@@ -1407,6 +1409,8 @@
 #define ECC_ERROR_MAN_SBEC		(0xff000000 >> 24)
 #define ECC_ERROR_MAN_SBEC_SHIFT	0

+#endif /* !CONFIG_MPC83XX_SDRAM */
+
 /*
  * CONFIG_ADDRESS - PCI Config Address Register
  */
@@ -1510,6 +1514,7 @@
  */
 #define PMCCR1_POWER_OFF		0x00000020

+#ifndef CONFIG_RAM
 /*
  * DDRCDR - DDR Control Driver Register
  */
@@ -1531,6 +1536,7 @@
 #define DDRCDR_DDR_CFG		0x00040000
 #define DDRCDR_M_ODR		0x00000002
 #define DDRCDR_Q_DRN		0x00000001
+#endif /* !CONFIG_RAM */

 /*
  * PCIE Bridge Register
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 02/11] sysreset: Add get_status method
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status Mario Six
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

It's useful to have the reset status of the SoC printed out during reset
(e.g. to learn whether the reset was caused by software or a watchdog).

As a first step to implement this, add a get_status method to the
sysreset class, which enables the caller to get printable information
about the reset status (akin to get_desc in the CPU uclass).

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
No changes

v1 -> v2:
New in v2

---
 drivers/sysreset/sysreset-uclass.c | 10 ++++++++++
 include/sysreset.h                 | 17 +++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c
index 7e06c3c90a7..de0c0aadbd9 100644
--- a/drivers/sysreset/sysreset-uclass.c
+++ b/drivers/sysreset/sysreset-uclass.c
@@ -24,6 +24,16 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type)
 	return ops->request(dev, type);
 }

+int sysreset_get_status(struct udevice *dev, char *buf, int size)
+{
+	struct sysreset_ops *ops = sysreset_get_ops(dev);
+
+	if (!ops->get_status)
+		return -ENOSYS;
+
+	return ops->get_status(dev, buf, size);
+}
+
 int sysreset_walk(enum sysreset_t type)
 {
 	struct udevice *dev;
diff --git a/include/sysreset.h b/include/sysreset.h
index 81318bdbf5d..a5c0b74a473 100644
--- a/include/sysreset.h
+++ b/include/sysreset.h
@@ -28,6 +28,14 @@ struct sysreset_ops {
 	 *		(in which case this method will not actually return)
 	 */
 	int (*request)(struct udevice *dev, enum sysreset_t type);
+	/**
+	 * get_status() - get printable reset status information
+	 *
+	 * @buf:	Buffer to receive the textual reset information
+	 * @size:	Size of the passed buffer
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*get_status)(struct udevice *dev, char *buf, int size);
 };

 #define sysreset_get_ops(dev)        ((struct sysreset_ops *)(dev)->driver->ops)
@@ -41,6 +49,15 @@ struct sysreset_ops {
 int sysreset_request(struct udevice *dev, enum sysreset_t type);

 /**
+ * get_status() - get printable reset status information
+ *
+ * @buf:	Buffer to receive the textual reset information
+ * @size:	Size of the passed buffer
+ * @return 0 if OK, -ve on error
+ */
+int sysreset_get_status(struct udevice *dev, char *buf, int size);
+
+/**
  * sysreset_walk() - cause a system reset
  *
  * This works through the available sysreset devices until it finds one that can
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 02/11] sysreset: Add get_status method Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-25  2:41   ` Simon Glass
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 04/11] board_f: Add reset status printing Mario Six
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Add some tests for sysreset_get_status.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
New in v3.

---
 drivers/sysreset/sysreset_sandbox.c | 16 ++++++++++++++++
 test/dm/sysreset.c                  | 19 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
index f12c4e84198..e03b5c122fe 100644
--- a/drivers/sysreset/sysreset_sandbox.c
+++ b/drivers/sysreset/sysreset_sandbox.c
@@ -29,6 +29,13 @@ static int sandbox_warm_sysreset_request(struct udevice *dev,
 	return -EINPROGRESS;
 }

+int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size)
+{
+	strncpy(buf, "Reset Status: WARM", size);
+
+	return 0;
+}
+
 static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
 {
 	struct sandbox_state *state = state_get_current();
@@ -60,8 +67,16 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
 	return -EINPROGRESS;
 }

+int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size)
+{
+	strncpy(buf, "Reset Status: COLD", size);
+
+	return 0;
+}
+
 static struct sysreset_ops sandbox_sysreset_ops = {
 	.request	= sandbox_sysreset_request,
+	.get_status	= sandbox_sysreset_get_status,
 };

 static const struct udevice_id sandbox_sysreset_ids[] = {
@@ -78,6 +93,7 @@ U_BOOT_DRIVER(sysreset_sandbox) = {

 static struct sysreset_ops sandbox_warm_sysreset_ops = {
 	.request	= sandbox_warm_sysreset_request,
+	.get_status	= sandbox_warm_sysreset_get_status,
 };

 static const struct udevice_id sandbox_warm_sysreset_ids[] = {
diff --git a/test/dm/sysreset.c b/test/dm/sysreset.c
index 33a8bfb33c4..218cc239cc6 100644
--- a/test/dm/sysreset.c
+++ b/test/dm/sysreset.c
@@ -45,6 +45,25 @@ static int dm_test_sysreset_base(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_sysreset_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);

+static int dm_test_sysreset_get_status(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	char msg[64];
+
+	/* Device 1 is the warm sysreset device */
+	ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev));
+	ut_assertok(sysreset_get_status(dev, msg, sizeof(msg)));
+	ut_asserteq_str("Reset Status: WARM", msg);
+
+	/* Device 2 is the cold sysreset device */
+	ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev));
+	ut_assertok(sysreset_get_status(dev, msg, sizeof(msg)));
+	ut_asserteq_str("Reset Status: COLD", msg);
+
+	return 0;
+}
+DM_TEST(dm_test_sysreset_get_status, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test that we can walk through the sysreset devices */
 static int dm_test_sysreset_walk(struct unit_test_state *uts)
 {
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 04/11] board_f: Add reset status printing
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 02/11] sysreset: Add get_status method Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 05/11] mpc83xx: Add sysreset driver Mario Six
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

To print the reset status during boot, add a method print_resetinfo to
board_f, which is called in init_sequence_f[], that gets the reset
information from the sysreset driver (assuming there is only one seems
reasonable), and prints it.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Improved behavior and error handling

v1 -> v2:
New in v2

---
 common/board_f.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/common/board_f.c b/common/board_f.c
index fa667c764bc..d24513d6d18 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -24,6 +24,7 @@
 #include <relocate.h>
 #include <spi.h>
 #include <status_led.h>
+#include <sysreset.h>
 #include <timer.h>
 #include <trace.h>
 #include <video.h>
@@ -140,6 +141,30 @@ static int display_text_info(void)
 	return 0;
 }

+#ifdef CONFIG_SYSRESET
+static int print_resetinfo(void)
+{
+	struct udevice *dev;
+	char status[256];
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_SYSRESET, &dev);
+	if (ret) {
+		debug("%s: No sysreset device found (error: %d)\n",
+		      __func__, ret);
+		/* Not all boards have sysreset drivers available during early
+		 * boot, so don't fail if one can't be found.
+		 */
+		return 0;
+	}
+
+	if (!sysreset_get_status(dev, status, sizeof(status)))
+		printf("%s", status);
+
+	return 0;
+}
+#endif
+
 static int announce_dram_init(void)
 {
 	puts("DRAM:  ");
@@ -788,6 +813,9 @@ static const init_fnc_t init_sequence_f[] = {
 #if defined(CONFIG_PPC) || defined(CONFIG_SH) || defined(CONFIG_X86)
 	checkcpu,
 #endif
+#if defined(CONFIG_SYSRESET)
+	print_resetinfo,
+#endif
 #if defined(CONFIG_DISPLAY_CPUINFO)
 	print_cpuinfo,		/* display cpu info (and speed) */
 #endif
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 05/11] mpc83xx: Add sysreset driver
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (2 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 04/11] board_f: Add reset status printing Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver Mario Six
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Add a sysreset driver for the MPC83xx platform.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Added driver file to MAINTAINERS

v1 -> v2:
New in v2

---
 MAINTAINERS                         |   1 +
 arch/powerpc/cpu/mpc83xx/cpu.c      |   3 +-
 drivers/sysreset/Kconfig            |   5 ++
 drivers/sysreset/Makefile           |   9 +-
 drivers/sysreset/sysreset_mpc83xx.c | 159 ++++++++++++++++++++++++++++++++++++
 5 files changed, 172 insertions(+), 5 deletions(-)
 create mode 100644 drivers/sysreset/sysreset_mpc83xx.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 139f7af26ac..b43e4bc179d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -470,6 +470,7 @@ S:	Maintained
 T:	git git://git.denx.de/u-boot-mpc83xx.git
 F:	drivers/ram/mpc83xx_sdram.c
 F:	include/dt-bindings/memory/mpc83xx-sdram.h
+F:	drivers/sysreset/sysreset_mpc83xx.c
 F:	arch/powerpc/cpu/mpc83xx/
 F:	arch/powerpc/include/asm/arch-mpc83xx/

diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
index 82370b54301..e1d2f2f07cb 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu.c
@@ -115,6 +115,7 @@ int checkcpu(void)
 	return 0;
 }

+#ifndef CONFIG_SYSRESET
 int
 do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
@@ -169,7 +170,7 @@ do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])

 	return 1;
 }
-
+#endif

 /*
  * Get timebase clock frequency (like cpu_clk in Hz)
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index a6d48e8a662..fd89e5f474c 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -37,4 +37,9 @@ config SYSRESET_WATCHDOG
 	help
 	  Reboot support for generic watchdog reset.

+config SYSRESET_MCP83XX
+	bool "Enable support MPC83xx SoC family reboot driver"
+	help
+	  Reboot support for NXP MPC83xx SoCs.
+
 endmenu
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index 0da58a1cf6a..50a7aef9fd7 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -3,11 +3,12 @@
 # (C) Copyright 2016 Cadence Design Systems Inc.

 obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
+obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
+obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
+obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
+obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
+obj-$(CONFIG_SYSRESET_MCP83XX) += sysreset_mpc83xx.o
 obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
 obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o
 obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
-obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
-obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
-obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
 obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
-obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
diff --git a/drivers/sysreset/sysreset_mpc83xx.c b/drivers/sysreset/sysreset_mpc83xx.c
new file mode 100644
index 00000000000..e61777e95f5
--- /dev/null
+++ b/drivers/sysreset/sysreset_mpc83xx.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sysreset.h>
+
+static void __do_reset(void)
+{
+	ulong msr;
+
+	immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+
+	puts("Resetting the board.\n");
+
+	/* Interrupts and MMU off */
+	msr = mfmsr();
+	msr &= ~(MSR_EE | MSR_IR | MSR_DR);
+	mtmsr(msr);
+
+	/* enable Reset Control Reg */
+	out_be32(&immap->reset.rpr, 0x52535445);
+	sync();
+	isync();
+
+	/* confirm Reset Control Reg is enabled */
+
+	while (!(in_be32(&immap->reset.rcer) & RCER_CRE))
+		;
+
+	udelay(200);
+
+	/* perform reset, only one bit */
+	out_be32(&immap->reset.rcr, RCR_SWHR);
+}
+
+int mpc83xx_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	switch (type) {
+	case SYSRESET_WARM:
+	case SYSRESET_COLD:
+		__do_reset();
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	return -EINPROGRESS;
+}
+
+#if defined(CONFIG_DISPLAY_AER_FULL)
+static int print_83xx_arb_event(int force)
+{
+	int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT)
+		    >> AEATR_EVENT_SHIFT;
+	int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID)
+		      >> AEATR_MSTR_ID_SHIFT;
+	int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST)
+		   >> AEATR_TBST_SHIFT;
+	int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE)
+		    >> AEATR_TSIZE_SHIFT;
+	int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE)
+		    >> AEATR_TTYPE_SHIFT;
+
+	if (!force && !gd->arch.arbiter_event_address)
+		return 0;
+
+	puts("Arbiter Event Status:\n");
+	printf("       Event Address: 0x%08lX\n",
+	       gd->arch.arbiter_event_address);
+	printf("       Event Type:    0x%1x  = %s\n", etype, event[etype]);
+	printf("       Master ID:     0x%02x = %s\n", mstr_id, master[mstr_id]);
+	printf("       Transfer Size: 0x%1x  = %d bytes\n", (tbst << 3) | tsize,
+	       tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize);
+	printf("       Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]);
+
+	return gd->arch.arbiter_event_address;
+}
+
+#elif defined(CONFIG_DISPLAY_AER_BRIEF)
+
+static int print_83xx_arb_event(int force, char *buf, int size)
+{
+	int res;
+
+	if (!force && !gd->arch.arbiter_event_address)
+		return 0;
+
+	res = snprintf(buf, size,
+		       "Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
+		       gd->arch.arbiter_event_attributes,
+		       gd->arch.arbiter_event_address);
+
+	return res;
+}
+#endif /* CONFIG_DISPLAY_AER_xxxx */
+
+int mpc83xx_sysreset_get_status(struct udevice *dev, char *buf, int size)
+{
+	int res;
+	static const struct {
+		ulong mask;
+		char *desc;
+	} bits[] = {
+		{
+		RSR_SWSR, "Software Soft"}, {
+		RSR_SWHR, "Software Hard"}, {
+		RSR_JSRS, "JTAG Soft"}, {
+		RSR_CSHR, "Check Stop"}, {
+		RSR_SWRS, "Software Watchdog"}, {
+		RSR_BMRS, "Bus Monitor"}, {
+		RSR_SRS,  "External/Internal Soft"}, {
+		RSR_HRS,  "External/Internal Hard"}
+	};
+	static int n = ARRAY_SIZE(bits);
+	ulong rsr = gd->arch.reset_status;
+	int i;
+	char *sep;
+
+	res = snprintf(buf, size, "Reset Status:");
+	if (!res)
+		return -EIO;
+
+	buf += res;
+	size -= res;
+
+	sep = " ";
+	for (i = 0; i < n; i++)
+		if (rsr & bits[i].mask) {
+			res = snprintf(buf, size, "%s%s%s", sep, bits[i].desc, (i == n - 1) ? "\n" : "");
+			buf += res;
+			size -= res;
+			sep = ", ";
+		}
+
+/* TODO(mario.six@gdsys.cc): Move this into a dedicated arbiter driver */
+#if defined(CONFIG_DISPLAY_AER_FULL) || defined(CONFIG_DISPLAY_AER_BRIEF)
+	res = print_83xx_arb_event(rsr & RSR_BMRS, buf, size);
+	buf += res;
+	size -= res;
+#endif
+	snprintf(buf, size, "\n");
+
+	return 0;
+}
+
+static struct sysreset_ops mpc83xx_sysreset = {
+	.request	= mpc83xx_sysreset_request,
+	.get_status	= mpc83xx_sysreset_get_status,
+};
+
+U_BOOT_DRIVER(sysreset_mpc83xx) = {
+	.name	= "mpc83xx_sysreset",
+	.id	= UCLASS_SYSRESET,
+	.ops	= &mpc83xx_sysreset,
+};
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (3 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 05/11] mpc83xx: Add sysreset driver Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-25  2:42   ` Simon Glass
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver Mario Six
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Add a clock driver for the MPC83xx architecture.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Added driver files to MAINTAINERS

v1 -> v2:
* Added binding of sysreset driver

---
 MAINTAINERS                           |   3 +
 arch/powerpc/cpu/mpc83xx/speed.c      |   4 +
 arch/powerpc/include/asm/config.h     |   2 +-
 drivers/clk/Kconfig                   |   6 +
 drivers/clk/Makefile                  |   1 +
 drivers/clk/mpc83xx_clk.c             | 426 ++++++++++++++++++++++++++++++++++
 drivers/clk/mpc83xx_clk.h             | 121 ++++++++++
 include/dt-bindings/clk/mpc83xx-clk.h |  33 +++
 8 files changed, 595 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mpc83xx_clk.c
 create mode 100644 drivers/clk/mpc83xx_clk.h
 create mode 100644 include/dt-bindings/clk/mpc83xx-clk.h

diff --git a/MAINTAINERS b/MAINTAINERS
index b43e4bc179d..ab0f6a0a5d0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -471,6 +471,9 @@ T:	git git://git.denx.de/u-boot-mpc83xx.git
 F:	drivers/ram/mpc83xx_sdram.c
 F:	include/dt-bindings/memory/mpc83xx-sdram.h
 F:	drivers/sysreset/sysreset_mpc83xx.c
+F:	drivers/clk/mpc83xx_clk.c
+F:	drivers/clk/mpc83xx_clk.h
+F:	include/dt-bindings/clk/mpc83xx-clk.h
 F:	arch/powerpc/cpu/mpc83xx/
 F:	arch/powerpc/include/asm/arch-mpc83xx/

diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
index f0945281cd2..39bc1c53406 100644
--- a/arch/powerpc/cpu/mpc83xx/speed.c
+++ b/arch/powerpc/cpu/mpc83xx/speed.c
@@ -6,6 +6,8 @@
  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
  */

+#ifndef CONFIG_CLK_MPC83XX
+
 #include <common.h>
 #include <mpc83xx.h>
 #include <command.h>
@@ -590,3 +592,5 @@ U_BOOT_CMD(clocks, 1, 0, do_clocks,
 	"print clock configuration",
 	"    clocks"
 );
+
+#endif
diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
index 284cfe21ab0..7bc8f5006ec 100644
--- a/arch/powerpc/include/asm/config.h
+++ b/arch/powerpc/include/asm/config.h
@@ -78,7 +78,7 @@
 /* All PPC boards must swap IDE bytes */
 #define CONFIG_IDE_SWAP_IO

-#if defined(CONFIG_DM_SERIAL)
+#if defined(CONFIG_DM_SERIAL) && !defined(CONFIG_CLK_MPC83XX)
 /*
  * TODO: Convert this to a clock driver exists that can give us the UART
  * clock here.
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index edb4ca58ea5..e6ebff0a9d4 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -98,4 +98,10 @@ config ICS8N3QV01
 	  Crystal Oscillator). The output frequency can be programmed via an
 	  I2C interface.

+config CLK_MPC83XX
+	bool "Enable MPC83xx clock driver"
+	depends on CLK
+	help
+	  Support for the clock driver of the MPC83xx series of SoCs.
+
 endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 58139b13a89..58f497d3a15 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
 obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
+obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
 obj-$(CONFIG_CLK_RENESAS) += renesas/
 obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
 obj-$(CONFIG_CLK_STM32MP1) += clk_stm32mp1.o
diff --git a/drivers/clk/mpc83xx_clk.c b/drivers/clk/mpc83xx_clk.c
new file mode 100644
index 00000000000..80be597332d
--- /dev/null
+++ b/drivers/clk/mpc83xx_clk.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dt-bindings/clk/mpc83xx-clk.h>
+
+#include "mpc83xx_clk.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static u32 *speed;
+
+struct mpc83xx_clk_priv {
+	u32 *speed;
+};
+
+static const char * const names[] = {
+	[MPC83XX_CLK_CORE] = "Core",
+	[MPC83XX_CLK_CSB] = "Coherent System Bus",
+	[MPC83XX_CLK_QE] = "QE",
+	[MPC83XX_CLK_BRG] = "BRG",
+	[MPC83XX_CLK_LBIU] = "Local Bus Controller",
+	[MPC83XX_CLK_LCLK] = "Local Bus",
+	[MPC83XX_CLK_MEM] = "DDR",
+	[MPC83XX_CLK_MEM_SEC] = "DDR Secondary",
+	[MPC83XX_CLK_ENC] = "SEC",
+	[MPC83XX_CLK_I2C1] = "I2C1",
+	[MPC83XX_CLK_I2C2] = "I2C2",
+	[MPC83XX_CLK_TDM] = "TDM",
+	[MPC83XX_CLK_SDHC] = "SDHC",
+	[MPC83XX_CLK_TSEC1] = "TSEC1",
+	[MPC83XX_CLK_TSEC2] = "TSEC2",
+	[MPC83XX_CLK_USBDR] = "USB DR",
+	[MPC83XX_CLK_USBMPH] = "USB MPH",
+	[MPC83XX_CLK_PCIEXP1] = "PCIEXP1",
+	[MPC83XX_CLK_PCIEXP2] = "PCIEXP2",
+	[MPC83XX_CLK_SATA] = "SATA",
+	[MPC83XX_CLK_DMAC] = "DMAC",
+	[MPC83XX_CLK_PCI] = "PCI",
+};
+
+struct clk_mode {
+	u8 low;
+	u8 high;
+	int type;
+};
+
+const struct clk_mode modes[] = {
+	[MPC83XX_CLK_CORE] = {0, 0, TYPE_SPECIAL},
+	[MPC83XX_CLK_CSB] = {0, 0, TYPE_SPECIAL},
+	[MPC83XX_CLK_QE] = {0, 0, TYPE_SPECIAL},
+	[MPC83XX_CLK_BRG] = {0, 0, TYPE_SPECIAL},
+	[MPC83XX_CLK_MEM] = {1, 1, TYPE_SPMR_DIRECT_MULTIPLY },
+	[MPC83XX_CLK_LBIU] = {0, 0, TYPE_SPMR_DIRECT_MULTIPLY },
+	[MPC83XX_CLK_LCLK] = {0, 0, TYPE_SPECIAL},
+	[MPC83XX_CLK_MEM_SEC] = {0, 0, TYPE_SPMR_DIRECT_MULTIPLY }, /* The same as LBIU */
+#ifndef CONFIG_MPC8313
+	[MPC83XX_CLK_TSEC1] = {0, 1, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_TSEC2] = {2, 3, TYPE_SCCR_STANDARD },
+#else
+	[MPC83XX_CLK_TSEC1] = {0, 1, TYPE_SCCR_STANDARD }, /* FIXME: This has separate enable/disable bit! */
+	[MPC83XX_CLK_TSEC2] = {0, 1, TYPE_SCCR_STANDARD }, /* FIXME: This has separate enable/disable bit! */
+#endif
+	[MPC83XX_CLK_SDHC] = {4, 5, TYPE_SCCR_STANDARD },
+#ifdef CONFIG_MPC834x
+	[MPC83XX_CLK_ENC] = {6, 7, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_I2C1] = {2, 3, TYPE_SCCR_STANDARD }, /* I2C and TSEC2 are the same register */
+#else
+	[MPC83XX_CLK_ENC] = {6, 7, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_I2C1] = {6, 7, TYPE_SCCR_STANDARD }, /* I2C and ENC are the same register */
+#endif
+	[MPC83XX_CLK_I2C2] = {0, 0, TYPE_SPECIAL },
+	[MPC83XX_CLK_PCIEXP1] = {10, 11, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_PCIEXP2] = {12, 13, TYPE_SCCR_STANDARD },
+#if defined(CONFIG_MPC8313) || defined(CONFIG_MPC834x)
+	[MPC83XX_CLK_USBDR] = {10, 11, TYPE_SCCR_STANDARD },
+#else
+	[MPC83XX_CLK_USBDR] = {8, 9, TYPE_SCCR_STANDARD },
+#endif
+	[MPC83XX_CLK_USBMPH] = {8, 9, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_PCI] = {15, 15, TYPE_SCCR_ONOFF },
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC8309)
+	[MPC83XX_CLK_DMAC] = {26, 27, TYPE_SCCR_STANDARD },
+#endif
+/* FIXME: All SATA controllers must have the same clock ratio */
+#ifdef CONFIG_MPC83XX_SATA_SUPPORT
+#ifdef CONFIG_MPC8379
+	[MPC83XX_CLK_SATA] = {24, 25, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_SATA] = {26, 27, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_SATA] = {28, 29, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_SATA] = {30, 31, TYPE_SCCR_STANDARD },
+#else
+	[MPC83XX_CLK_SATA] = {18, 19, TYPE_SCCR_STANDARD },
+	[MPC83XX_CLK_SATA] = {20, 21, TYPE_SCCR_STANDARD },
+#endif
+#endif
+	[MPC83XX_CLK_TDM] = {26, 27, TYPE_SCCR_STANDARD },
+};
+
+int get_clocks(void)
+{
+	return 0;
+}
+
+inline bool is_clk_valid(int id)
+{
+	switch (id) {
+	case MPC83XX_CLK_MEM:
+#if defined(CONFIG_MPC8360)
+	case MPC83XX_CLK_MEM_SEC:
+#endif
+#ifndef CONFIG_MPC830x
+	case MPC83XX_CLK_ENC:
+#endif
+	case MPC83XX_CLK_I2C1:
+#ifdef CONFIG_MPC8315
+	case MPC83XX_CLK_TDM:
+#endif
+#ifdef CONFIG_MPC83XX_SDHC_SUPPORT
+	case MPC83XX_CLK_SDHC:
+#endif
+#ifdef CONFIG_MPC83XX_TSEC1_SUPPORT
+	case MPC83XX_CLK_TSEC1:
+#endif
+#ifdef CONFIG_MPC83XX_TSEC2_SUPPORT
+	case MPC83XX_CLK_TSEC2:
+#endif
+#if !defined(CONFIG_MPC8360)
+	case MPC83XX_CLK_USBDR:
+#endif
+#ifdef CONFIG_MPC834x
+	case MPC83XX_CLK_USBMPH:
+#endif
+#ifdef CONFIG_MPC83XX_PCIE1_SUPPORT
+	case MPC83XX_CLK_PCIEXP1:
+#endif
+#ifdef CONFIG_MPC83XX_PCIE2_SUPPORT
+	case MPC83XX_CLK_PCIEXP2:
+#endif
+#ifdef CONFIG_MPC83XX_SATA_SUPPORT
+	case MPC83XX_CLK_SATA:
+#endif
+#ifdef CONFIG_MPC830x
+	case MPC83XX_CLK_DMAC:
+#endif
+#ifdef CONFIG_MPC83XX_PCI_SUPPORT
+	case MPC83XX_CLK_PCI:
+#endif
+	case MPC83XX_CLK_CSB:
+#ifdef CONFIG_MPC83XX_SECOND_I2C_SUPPORT
+	case MPC83XX_CLK_I2C2:
+#endif
+#if defined(CONFIG_MPC83XX_QUICC_ENGINE) && !defined(CONFIG_MPC8309)
+	case MPC83XX_CLK_QE:
+	case MPC83XX_CLK_BRG:
+#endif
+	case MPC83XX_CLK_LCLK:
+	case MPC83XX_CLK_LBIU:
+	case MPC83XX_CLK_CORE:
+		return true;
+	}
+
+	return false;
+}
+
+static int mpc83xx_clk_request(struct clk *clock)
+{
+	/* Reject requests of clocks that are not available */
+	if (is_clk_valid(clock->id))
+		return 0;
+	else
+		return -ENODEV;
+}
+
+static inline void init_clks(u32 *speed)
+{
+	int i;
+	immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+	u32 csb_clk = get_csb_clk(im);
+
+	for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
+		struct clk_mode mode = modes[i];
+		ulong mask;
+
+		if (mode.type == TYPE_INVALID)
+			continue;
+
+		if (mode.type == TYPE_SCCR_STANDARD) {
+			mask = GENMASK(31 - mode.low, 31 - mode.high);
+
+			switch (sccr_field(im, mask, 31 - mode.high)) {
+			case 0:
+				speed[i] = 0;
+				break;
+			case 1:
+				speed[i] = csb_clk;
+				break;
+			case 2:
+				speed[i] = csb_clk / 2;
+				break;
+			case 3:
+				speed[i] = csb_clk / 3;
+				break;
+			default:
+				speed[i] = 0;
+			}
+
+			continue;
+		}
+
+		if (mode.type == TYPE_SPMR_DIRECT_MULTIPLY) {
+			mask = GENMASK(31 - mode.low, 31 - mode.high);
+
+			speed[i] = csb_clk * (1 + sccr_field(im, mask, 31 - mode.high));
+			continue;
+		}
+
+		if (i == MPC83XX_CLK_CSB || i == MPC83XX_CLK_I2C2) {
+			speed[i] = csb_clk; /* i2c-2 clk is equal to csb clk */
+			continue;
+		}
+
+		if (i == MPC83XX_CLK_QE || i == MPC83XX_CLK_BRG) {
+			u32 pci_sync_in = get_pci_sync_in(im);
+			u32 qepmf = spmr_field(im, SPMR_CEPMF, SPMR_CEPMF_SHIFT);
+			u32 qepdf = spmr_field(im, SPMR_CEPDF, SPMR_CEPDF_SHIFT);
+			u32 qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
+
+			if (i == MPC83XX_CLK_QE)
+				speed[i] = qe_clk;
+			else
+				speed[i] = qe_clk / 2;
+
+			continue;
+		}
+
+		if (i == MPC83XX_CLK_LCLK || i == MPC83XX_CLK_LBIU) {
+			u32 lbiu_clk = csb_clk *
+				(1 + spmr_field(im, SPMR_LBIUCM, SPMR_LBIUCM_SHIFT));
+			u32 clkdiv = lcrr_field(im, LCRR_CLKDIV, LCRR_CLKDIV_SHIFT);
+
+			if (i == MPC83XX_CLK_LBIU)
+				speed[i] = lbiu_clk;
+
+			switch (clkdiv) {
+			case 2:
+			case 4:
+			case 8:
+				speed[i] = lbiu_clk / clkdiv;
+				break;
+			default:
+				/* unknown lcrr */
+				speed[i] = 0;
+			}
+
+			continue;
+		}
+
+		if (i == MPC83XX_CLK_CORE) {
+			u8 corepll = spmr_field(im, SPMR_COREPLL, SPMR_COREPLL_SHIFT);
+			u32 corecnf_tab_index = ((corepll & 0x1F) << 2) |
+						((corepll & 0x60) >> 5);
+
+			if (corecnf_tab_index > (ARRAY_SIZE(corecnf_tab))) {
+				/* corecnf_tab_index is too high, possibly wrong value */
+				speed[i] = 0;
+			}
+
+			switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
+			case _byp:
+			case _x1:
+			case _1x:
+				speed[i] = csb_clk;
+				break;
+			case _1_5x:
+				speed[i] = (3 * csb_clk) / 2;
+				break;
+			case _2x:
+				speed[i] = 2 * csb_clk;
+				break;
+			case _2_5x:
+				speed[i] = (5 * csb_clk) / 2;
+				break;
+			case _3x:
+				speed[i] = 3 * csb_clk;
+				break;
+			default:
+				/* unknown core to csb ratio */
+				speed[i] = 0;
+			}
+
+			continue;
+		}
+	}
+}
+
+static ulong mpc83xx_clk_get_rate(struct clk *clk)
+{
+	struct mpc83xx_clk_priv *priv = dev_get_priv(clk->dev);
+
+	return priv->speed[clk->id];
+}
+
+int get_serial_clock(void)
+{
+	return speed[MPC83XX_CLK_CSB];
+}
+
+const struct clk_ops mpc83xx_clk_ops = {
+	.request = mpc83xx_clk_request,
+	.get_rate = mpc83xx_clk_get_rate,
+};
+
+static const struct udevice_id mpc83xx_clk_match[] = {
+	{ .compatible = "fsl,mpc83xx-clk", },
+	{ /* sentinel */ }
+};
+
+static int mpc83xx_clk_probe(struct udevice *dev)
+{
+	struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
+
+	speed = malloc((MPC83XX_CLK_COUNT + 1) * sizeof(u32));
+	priv->speed = speed;
+	init_clks(priv->speed);
+
+	gd->arch.csb_clk = speed[MPC83XX_CLK_CSB];
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+	defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+	gd->arch.tsec1_clk = speed[MPC83XX_CLK_TSEC1];
+	gd->arch.tsec2_clk = speed[MPC83XX_CLK_TSEC2];
+	gd->arch.usbdr_clk = speed[MPC83XX_CLK_USBDR];
+#elif defined(CONFIG_MPC8309)
+	gd->arch.usbdr_clk = speed[MPC83XX_CLK_USBDR];
+#endif
+#if defined(CONFIG_MPC834x)
+	gd->arch.usbmph_clk = speed[MPC83XX_CLK_USBMPH];
+#endif
+#if defined(CONFIG_MPC8315)
+	gd->arch.tdm_clk = speed[MPC83XX_CLK_TDM];
+#endif
+#if defined(CONFIG_FSL_ESDHC)
+	gd->arch.sdhc_clk = speed[MPC83XX_CLK_SDHC];
+#endif
+	gd->arch.core_clk = speed[MPC83XX_CLK_CORE];
+	gd->arch.i2c1_clk = speed[MPC83XX_CLK_I2C1];
+#if !defined(CONFIG_MPC832x)
+	gd->arch.i2c2_clk = speed[MPC83XX_CLK_I2C2];
+#endif
+#if !defined(CONFIG_MPC8309)
+	gd->arch.enc_clk = speed[MPC83XX_CLK_ENC];
+#endif
+	gd->arch.lbiu_clk = speed[MPC83XX_CLK_LBIU];
+	gd->arch.lclk_clk = speed[MPC83XX_CLK_LCLK];
+	gd->mem_clk = speed[MPC83XX_CLK_MEM];
+#if defined(CONFIG_MPC8360)
+	gd->arch.mem_sec_clk = speed[MPC83XX_CLK_MEM_SEC];
+#endif
+#if defined(CONFIG_QE)
+	gd->arch.qe_clk = speed[MPC83XX_CLK_QE];
+	gd->arch.brg_clk = speed[MPC83XX_CLK_BRG];
+#endif
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+	defined(CONFIG_MPC837x)
+	gd->arch.pciexp1_clk = speed[MPC83XX_CLK_PCIEXP1];
+	gd->arch.pciexp2_clk = speed[MPC83XX_CLK_PCIEXP2];
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+	gd->arch.sata_clk = speed[MPC83XX_CLK_SATA];
+#endif
+	gd->pci_clk = speed[MPC83XX_CLK_PCI];
+	gd->cpu_clk = speed[MPC83XX_CLK_CORE];
+	gd->bus_clk = speed[MPC83XX_CLK_CSB];
+
+	return 0;
+}
+
+static int mpc83xx_clk_bind(struct udevice *dev)
+{
+	int ret;
+	struct udevice *sys_child;
+
+	ret = device_bind_driver(dev, "mpc83xx_sysreset", "sysreset",
+				 &sys_child);
+	if (ret)
+		debug("Warning: No sysreset driver: ret=%d\n", ret);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(mpc83xx_clk) = {
+	.name = "mpc83xx_clk",
+	.id = UCLASS_CLK,
+	.of_match = mpc83xx_clk_match,
+	.ops = &mpc83xx_clk_ops,
+	.probe = mpc83xx_clk_probe,
+	.priv_auto_alloc_size	= sizeof(struct mpc83xx_clk_priv),
+	.bind = mpc83xx_clk_bind,
+};
+
+static int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int i;
+	char buf[32];
+
+	for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
+		if (!is_clk_valid(i))
+			continue;
+
+		printf("%s = %s MHz\n", names[i], strmhz(buf, speed[i]));
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	clocks,	1,	1,	do_clocks,
+	"display values of SoC's clocks",
+	""
+);
diff --git a/drivers/clk/mpc83xx_clk.h b/drivers/clk/mpc83xx_clk.h
new file mode 100644
index 00000000000..296f1333e5e
--- /dev/null
+++ b/drivers/clk/mpc83xx_clk.h
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ */
+
+enum {
+	_unk,
+	_off,
+	_byp,
+	_x8,
+	_x4,
+	_x2,
+	_x1,
+	_1x,
+	_1_5x,
+	_2x,
+	_2_5x,
+	_3x
+};
+
+struct corecnf {
+	int core_csb_ratio;
+	int vco_divider;
+};
+
+static struct corecnf corecnf_tab[] = {
+	{_byp, _byp},		/* 0x00 */
+	{_byp, _byp},		/* 0x01 */
+	{_byp, _byp},		/* 0x02 */
+	{_byp, _byp},		/* 0x03 */
+	{_byp, _byp},		/* 0x04 */
+	{_byp, _byp},		/* 0x05 */
+	{_byp, _byp},		/* 0x06 */
+	{_byp, _byp},		/* 0x07 */
+	{_1x, _x2},		/* 0x08 */
+	{_1x, _x4},		/* 0x09 */
+	{_1x, _x8},		/* 0x0A */
+	{_1x, _x8},		/* 0x0B */
+	{_1_5x, _x2},		/* 0x0C */
+	{_1_5x, _x4},		/* 0x0D */
+	{_1_5x, _x8},		/* 0x0E */
+	{_1_5x, _x8},		/* 0x0F */
+	{_2x, _x2},		/* 0x10 */
+	{_2x, _x4},		/* 0x11 */
+	{_2x, _x8},		/* 0x12 */
+	{_2x, _x8},		/* 0x13 */
+	{_2_5x, _x2},		/* 0x14 */
+	{_2_5x, _x4},		/* 0x15 */
+	{_2_5x, _x8},		/* 0x16 */
+	{_2_5x, _x8},		/* 0x17 */
+	{_3x, _x2},		/* 0x18 */
+	{_3x, _x4},		/* 0x19 */
+	{_3x, _x8},		/* 0x1A */
+	{_3x, _x8},		/* 0x1B */
+};
+
+enum reg_type {
+	REG_SCCR,
+	REG_SPMR,
+};
+
+enum mode_type {
+	TYPE_INVALID = 0,
+	TYPE_SCCR_STANDARD,
+	TYPE_SCCR_ONOFF,
+	TYPE_SPMR_DIRECT_MULTIPLY,
+	TYPE_SPECIAL,
+};
+
+static inline u32 get_spmr(immap_t *im)
+{
+	u32 res = in_be32(&im->clk.spmr);
+
+	return res;
+}
+
+static inline u32 get_sccr(immap_t *im)
+{
+	u32 res = in_be32(&im->clk.sccr);
+
+	return res;
+}
+
+static inline u32 get_lcrr(immap_t *im)
+{
+	u32 res = in_be32(&im->im_lbc.lcrr);
+
+	return res;
+}
+
+static inline u32 get_pci_sync_in(immap_t *im)
+{
+	u8 clkin_div;
+
+	clkin_div = (get_spmr(im) & SPMR_CKID) >> SPMR_CKID_SHIFT;
+	return CONFIG_SYS_CLK_FREQ / (1 + clkin_div);
+}
+
+static inline u32 get_csb_clk(immap_t *im)
+{
+	u8 spmf;
+
+	spmf = (get_spmr(im) & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
+	return CONFIG_SYS_CLK_FREQ * spmf;
+}
+
+static inline uint spmr_field(immap_t *im, u32 mask, uint shift)
+{
+	return (get_spmr(im) & mask) >> shift;
+}
+
+static inline uint sccr_field(immap_t *im, u32 mask, uint shift)
+{
+	return (get_sccr(im) & mask) >> shift;
+}
+
+static inline uint lcrr_field(immap_t *im, u32 mask, uint shift)
+{
+	return (get_lcrr(im) & mask) >> shift;
+}
diff --git a/include/dt-bindings/clk/mpc83xx-clk.h b/include/dt-bindings/clk/mpc83xx-clk.h
new file mode 100644
index 00000000000..2d0879cd137
--- /dev/null
+++ b/include/dt-bindings/clk/mpc83xx-clk.h
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#ifndef DT_BINDINGS_MPC83XX_CLK_H
+#define DT_BINDINGS_MPC83XX_CLK_H
+#define MPC83XX_CLK_CORE	0
+#define MPC83XX_CLK_CSB		1
+#define MPC83XX_CLK_QE		2
+#define MPC83XX_CLK_BRG		3
+#define MPC83XX_CLK_LBIU	4
+#define MPC83XX_CLK_LCLK	5
+#define MPC83XX_CLK_MEM		6
+#define MPC83XX_CLK_MEM_SEC	7
+#define MPC83XX_CLK_ENC		8
+#define MPC83XX_CLK_I2C1	9
+#define MPC83XX_CLK_I2C2	10
+#define MPC83XX_CLK_TDM		11
+#define MPC83XX_CLK_SDHC	12
+#define MPC83XX_CLK_TSEC1	13
+#define MPC83XX_CLK_TSEC2	14
+#define MPC83XX_CLK_USBDR	15
+#define MPC83XX_CLK_USBMPH	16
+#define MPC83XX_CLK_PCIEXP1	17
+#define MPC83XX_CLK_PCIEXP2	18
+#define MPC83XX_CLK_SATA	19
+#define MPC83XX_CLK_DMAC	20
+#define MPC83XX_CLK_PCI		21
+/* Count */
+#define MPC83XX_CLK_COUNT	22
+#endif /* DT_BINDINGS_MPC83XX_CLK_H */
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (4 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-25  2:42   ` Simon Glass
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 08/11] common: board_f: Sort includes Mario Six
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Add a timer driver for the MPC83xx architecture.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Got rid of the static variables
* Added driver files to MAINTAINERS

v1 -> v2:
* Removed now-superfluous comments
* Removed usage of uclass_{first,next}_device_compat
* Switched to usage of new board uclass (instead of devinfo)

---
 MAINTAINERS                    |   1 +
 arch/powerpc/cpu/mpc83xx/cpu.c |   4 +-
 arch/powerpc/lib/Makefile      |   4 +
 arch/powerpc/lib/interrupts.c  |   5 +-
 drivers/timer/Kconfig          |   7 ++
 drivers/timer/Makefile         |   1 +
 drivers/timer/mpc83xx_timer.c  | 182 +++++++++++++++++++++++++++++++++++++++++
 7 files changed, 201 insertions(+), 3 deletions(-)
 create mode 100644 drivers/timer/mpc83xx_timer.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ab0f6a0a5d0..f03cfcc73b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -474,6 +474,7 @@ F:	drivers/sysreset/sysreset_mpc83xx.c
 F:	drivers/clk/mpc83xx_clk.c
 F:	drivers/clk/mpc83xx_clk.h
 F:	include/dt-bindings/clk/mpc83xx-clk.h
+F:	drivers/timer/mpc83xx_timer.c
 F:	arch/powerpc/cpu/mpc83xx/
 F:	arch/powerpc/include/asm/arch-mpc83xx/

diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
index e1d2f2f07cb..ffb42415feb 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu.c
@@ -175,12 +175,12 @@ do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 /*
  * Get timebase clock frequency (like cpu_clk in Hz)
  */
-
+#ifndef CONFIG_TIMER
 unsigned long get_tbclk(void)
 {
 	return (gd->bus_clk + 3L) / 4L;
 }
-
+#endif

 #if defined(CONFIG_WATCHDOG)
 void watchdog_reset (void)
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index c3acefaea7e..8ac49bdd060 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -17,13 +17,17 @@ endif

 ifdef MINIMAL
 obj-y += cache.o time.o
+ifndef CONFIG_TIMER
 obj-y += ticks.o
+endif
 else

 obj-y	+= ppcstring.o

 obj-y	+= ppccache.o
+ifndef CONFIG_TIMER
 obj-y	+= ticks.o
+endif
 obj-y	+= reloc.o

 obj-$(CONFIG_BAT_RW) += bat_rw.o
diff --git a/arch/powerpc/lib/interrupts.c b/arch/powerpc/lib/interrupts.c
index f63e5cf799b..19682cfcfad 100644
--- a/arch/powerpc/lib/interrupts.c
+++ b/arch/powerpc/lib/interrupts.c
@@ -14,6 +14,7 @@
 #include <status_led.h>
 #endif

+#ifndef CONFIG_MPC83XX_TIMER
 #ifdef CONFIG_SHOW_ACTIVITY
 void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity")));

@@ -44,7 +45,7 @@ static __inline__ void set_dec (unsigned long val)
 	if (val)
 		asm volatile ("mtdec %0"::"r" (val));
 }
-
+#endif /* !CONFIG_MPC83XX_TIMER */

 void enable_interrupts (void)
 {
@@ -60,6 +61,7 @@ int disable_interrupts (void)
 	return ((msr & MSR_EE) != 0);
 }

+#ifndef CONFIG_MPC83XX_TIMER
 int interrupt_init (void)
 {
 	/* call cpu specific function from $(CPU)/interrupts.c */
@@ -102,3 +104,4 @@ ulong get_timer (ulong base)
 {
 	return (timestamp - base);
 }
+#endif /* !CONFIG_MPC83XX_TIMER */
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 8a31397553d..c7909bd6e52 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -133,4 +133,11 @@ config STM32_TIMER
 	  Select this to enable support for the timer found on
 	  STM32 devices.

+config MPC83XX_TIMER
+        bool "MPC83xx timer support"
+	depends on TIMER
+	help
+	  Select this to enable support for the timer found on
+	  devices based on the MPC83xx family of SoCs.
+
 endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index ee2fcb1fa71..75360d81de3 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
 obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
 obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
 obj-$(CONFIG_STM32_TIMER)	+= stm32_timer.o
+obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c
new file mode 100644
index 00000000000..148fb2550ca
--- /dev/null
+++ b/drivers/timer/mpc83xx_timer.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <clk.h>
+#include <timer.h>
+#include <watchdog.h>
+#include <board.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mpc83xx_timer_priv {
+	uint decrementer_count; /* count value for 1e6/HZ microseconds */
+	ulong timestamp;
+};
+
+static inline unsigned long get_dec(void)
+{
+	unsigned long val;
+
+	asm volatile ("mfdec %0" : "=r" (val) : );
+
+	return val;
+}
+
+static inline void set_dec(unsigned long val)
+{
+	if (val)
+		asm volatile ("mtdec %0"::"r" (val));
+}
+
+/* TODO(mario.six at gdsys.cc): This should really be done by timer_init, and the
+ * interrupt init should go into a interrupt driver.
+ */
+int interrupt_init(void)
+{
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+	struct udevice *csb;
+	struct udevice *board;
+	struct udevice *timer = gd->timer;
+	struct mpc83xx_timer_priv *timer_priv = dev_get_priv(timer);
+	struct clk clock;
+	int ret;
+
+	if (get_board(&board)) {
+		debug("%s: board device could not be fetched.\n", __func__);
+		return -ENOENT;
+	}
+
+	ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, board,
+					   "csb", &csb);
+	if (ret) {
+		debug("%s: Could not retrieve CSB device (error: %d)",
+		      __func__, ret);
+		return ret;
+	}
+
+	ret = clk_get_by_index(csb, 0, &clock);
+	if (ret) {
+		debug("%s: Could not retrieve clock (error: %d)",
+		      __func__, ret);
+		return ret;
+	}
+
+	timer_priv->decrementer_count = (clk_get_rate(&clock) / 4)
+					/ CONFIG_SYS_HZ;
+	/* Enable e300 time base */
+	setbits_be32(&immr->sysconf.spcr, 0x00400000);
+
+	set_dec(timer_priv->decrementer_count);
+
+	set_msr(get_msr() | MSR_EE);
+
+	return 0;
+}
+
+void timer_interrupt(struct pt_regs *regs)
+{
+	struct udevice *timer = gd->timer;
+	struct mpc83xx_timer_priv *priv = dev_get_priv(timer);
+
+	/* Restore Decrementer Count */
+	set_dec(priv->decrementer_count);
+
+	priv->timestamp++;
+
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
+	if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+		WATCHDOG_RESET();
+#endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
+
+#ifdef CONFIG_LED_STATUS
+	status_led_tick(priv->timestamp);
+#endif /* CONFIG_LED_STATUS */
+
+#ifdef CONFIG_SHOW_ACTIVITY
+	board_show_activity(priv->timestamp);
+#endif /* CONFIG_SHOW_ACTIVITY */
+}
+
+ulong get_timer(ulong base)
+{
+	struct udevice *timer = gd->timer;
+	struct mpc83xx_timer_priv *priv = dev_get_priv(timer);
+
+	return (priv->timestamp - base);
+}
+
+static inline u32 mftbu(void)
+{
+	u32 rval;
+
+	asm volatile("mftbu %0" : "=r" (rval));
+	return rval;
+}
+
+static inline u32 mftb(void)
+{
+	u32 rval;
+
+	asm volatile("mftb %0" : "=r" (rval));
+	return rval;
+}
+
+void wait_ticks(ulong ticks)
+{
+	ulong end = get_ticks() + ticks;
+
+	while (end > get_ticks())
+		WATCHDOG_RESET();
+}
+
+static int mpc83xx_timer_get_count(struct udevice *dev, u64 *count)
+{
+	u32 tbu, tbl;
+
+	do {
+		tbu = mftbu();
+		tbl = mftb();
+	} while (tbu != mftbu());
+
+	*count = (tbu * 0x10000ULL) + tbl;
+
+	return 0;
+}
+
+static int mpc83xx_timer_probe(struct udevice *dev)
+{
+	struct timer_dev_priv *uc_priv = dev->uclass_priv;
+	struct clk clock;
+
+	interrupt_init();
+
+	clk_get_by_index(dev, 0, &clock);
+
+	uc_priv->clock_rate = (clk_get_rate(&clock) + 3L) / 4L;
+
+	return 0;
+}
+
+static const struct timer_ops mpc83xx_timer_ops = {
+	.get_count = mpc83xx_timer_get_count,
+};
+
+static const struct udevice_id mpc83xx_timer_ids[] = {
+	{ .compatible = "fsl,mpc83xx-timer" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mpc83xx_timer) = {
+	.name	= "mpc83xx_timer",
+	.id	= UCLASS_TIMER,
+	.of_match = mpc83xx_timer_ids,
+	.probe = mpc83xx_timer_probe,
+	.ops	= &mpc83xx_timer_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+	.priv_auto_alloc_size = sizeof(struct mpc83xx_timer_priv),
+};
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 08/11] common: board_f: Sort includes
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (5 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active Mario Six
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Includes should be sorted.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
No changes

v1 -> v2:
New in v2

---
 common/board_f.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/board_f.c b/common/board_f.c
index d24513d6d18..a716eeb8990 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -11,8 +11,8 @@

 #include <common.h>
 #include <console.h>
-#include <environment.h>
 #include <dm.h>
+#include <environment.h>
 #include <fdtdec.h>
 #include <fs.h>
 #include <i2c.h>
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (6 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 08/11] common: board_f: Sort includes Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-25  2:42   ` Simon Glass
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver Mario Six
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 11/11] misc: Add MPC83xx serdes driver Mario Six
  9 siblings, 1 reply; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

When the DM CPU drivers are active, printing information about a CPU
should be delegated to a matching driver.

Hence, add a static print_cpuinfo that implements this delegation when
DM CPU drivers are active.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
No changes

v1 -> v2:
New in v2

---
 common/board_f.c | 16 ++++++++++++++++
 include/init.h   |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/common/board_f.c b/common/board_f.c
index a716eeb8990..327c7d83e2c 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -11,6 +11,7 @@

 #include <common.h>
 #include <console.h>
+#include <cpu.h>
 #include <dm.h>
 #include <environment.h>
 #include <fdtdec.h>
@@ -165,6 +166,21 @@ static int print_resetinfo(void)
 }
 #endif

+#if defined(CONFIG_DISPLAY_CPUINFO) && defined(CONFIG_CPU)
+static int print_cpuinfo(void)
+{
+	struct udevice *dev;
+	char desc[512];
+
+	uclass_first_device_err(UCLASS_CPU, &dev);
+
+	cpu_get_desc(dev, desc, sizeof(desc));
+	printf("%s", desc);
+
+	return 0;
+}
+#endif
+
 static int announce_dram_init(void)
 {
 	puts("DRAM:  ");
diff --git a/include/init.h b/include/init.h
index f114a889631..38c9680c7a7 100644
--- a/include/init.h
+++ b/include/init.h
@@ -107,7 +107,9 @@ int arch_reserve_stacks(void);
  */
 int init_cache_f_r(void);

+#ifndef CONFIG_CPU
 int print_cpuinfo(void);
+#endif
 int timer_init(void);
 int reserve_mmu(void);
 int misc_init_f(void);
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (7 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-25  2:42   ` Simon Glass
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 11/11] misc: Add MPC83xx serdes driver Mario Six
  9 siblings, 1 reply; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Add a CPU driver for the MPC83xx architecture.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Added driver files to MAINTAINERS

v1 -> v2:
* Removed cpu_print_info
* Fixed CPU info printing
* Removed usage of uclass_{first,next}_device_compat
* Removed printing of reset status

---
 MAINTAINERS                          |   2 +
 arch/powerpc/cpu/mpc83xx/cpu.c       |   2 +
 arch/powerpc/cpu/mpc83xx/cpu_init.c  |   2 +
 arch/powerpc/include/asm/processor.h |   2 +
 drivers/cpu/Kconfig                  |   7 +
 drivers/cpu/Makefile                 |   1 +
 drivers/cpu/mpc83xx_cpu.c            | 265 +++++++++++++++++++++++++++++++++++
 drivers/cpu/mpc83xx_cpu.h            | 172 +++++++++++++++++++++++
 include/cpu.h                        |   1 +
 9 files changed, 454 insertions(+)
 create mode 100644 drivers/cpu/mpc83xx_cpu.c
 create mode 100644 drivers/cpu/mpc83xx_cpu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f03cfcc73b0..11965be1402 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -475,6 +475,8 @@ F:	drivers/clk/mpc83xx_clk.c
 F:	drivers/clk/mpc83xx_clk.h
 F:	include/dt-bindings/clk/mpc83xx-clk.h
 F:	drivers/timer/mpc83xx_timer.c
+F:	drivers/cpu/mpc83xx_cpu.c
+F:	drivers/cpu/mpc83xx_cpu.h
 F:	arch/powerpc/cpu/mpc83xx/
 F:	arch/powerpc/include/asm/arch-mpc83xx/

diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
index ffb42415feb..b29f271e9bc 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu.c
@@ -25,6 +25,7 @@

 DECLARE_GLOBAL_DATA_PTR;

+#ifndef CONFIG_CPU_MPC83XX
 int checkcpu(void)
 {
 	volatile immap_t *immr;
@@ -114,6 +115,7 @@ int checkcpu(void)

 	return 0;
 }
+#endif

 #ifndef CONFIG_SYSRESET
 int
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
index fcac9f63a81..1555205e069 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -464,6 +464,7 @@ static int print_83xx_arb_event(int force)
 }
 #endif /* CONFIG_DISPLAY_AER_xxxx */

+#ifndef CONFIG_CPU_MPC83XX
 /*
  * Figure out the cause of the reset
  */
@@ -505,3 +506,4 @@ int prt_83xx_rsr(void)

 	return 0;
 }
+#endif
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 6fbe8c46b31..f97ce48cc27 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -1325,7 +1325,9 @@ void ll_puts(const char *);
 /* In misc.c */
 void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);

+#ifndef CONFIG_CPU_MPC83XX
 int prt_83xx_rsr(void);
+#endif

 #endif /* ndef ASSEMBLY*/

diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
index 0d1424d38e9..d4052005e24 100644
--- a/drivers/cpu/Kconfig
+++ b/drivers/cpu/Kconfig
@@ -6,3 +6,10 @@ config CPU
 	  multiple CPUs, then normally have to be set up in U-Boot so that
 	  they can work correctly in the OS. This provides a framework for
 	  finding out information about available CPUs and making changes.
+
+config CPU_MPC83XX
+	bool "Enable MPC83xx CPU driver"
+	depends on CPU
+	select CLK_MPC83XX
+	help
+	  Support CPU cores for SoCs of the MPC83xx series.
diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
index db515f6f177..29d7da42fad 100644
--- a/drivers/cpu/Makefile
+++ b/drivers/cpu/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_CPU) += cpu-uclass.o

 obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
+obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c
new file mode 100644
index 00000000000..550a7ad89f1
--- /dev/null
+++ b/drivers/cpu/mpc83xx_cpu.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <cpu.h>
+#include <clk.h>
+#include <asm/immap_83xx.h>
+
+#include "mpc83xx_cpu.h"
+
+struct mpc83xx_cpu_priv {
+	struct mpc83xx_cpu_info info;
+};
+
+int checkcpu(void)
+{
+	struct udevice *cpu;
+
+	for (uclass_first_device(UCLASS_CPU, &cpu);
+	     cpu;
+	     uclass_next_device(&cpu)) {
+	}
+
+	return 0;
+}
+
+static inline u32 get_spridr(void)
+{
+	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+	return in_be32(&immr->sysconf.spridr);
+}
+
+static inline void determine_family(struct udevice *dev)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+
+	switch ((get_spridr() & 0xFFFE0000) >> 16) {
+	case 0x80B:
+		priv->info.family = FAMILY_831X;
+		break;
+	case 0x806:
+		priv->info.family = FAMILY_832X;
+		break;
+	case 0x803:
+		priv->info.family = FAMILY_834X;
+		break;
+	case 0x804:
+		priv->info.family = FAMILY_836X;
+		break;
+	case 0x80C:
+		priv->info.family = FAMILY_837X;
+		break;
+	default:
+		priv->info.family = FAMILY_UNKNOWN;
+	}
+}
+
+static inline void determine_type(struct udevice *dev)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+
+	switch ((get_spridr() & 0xFFFE0000) >> 16) {
+	case 0x8100:
+		priv->info.type = TYPE_8308;
+		break;
+	case 0x8110:
+		priv->info.type = TYPE_8309;
+		break;
+	case 0x80B2:
+		priv->info.type = TYPE_8311;
+		break;
+	case 0x80B0:
+		priv->info.type = TYPE_8313;
+		break;
+	case 0x80B6:
+		priv->info.type = TYPE_8314;
+		break;
+	case 0x80B4:
+		priv->info.type = TYPE_8315;
+		break;
+	case 0x8066:
+		priv->info.type = TYPE_8321;
+		break;
+	case 0x8062:
+		priv->info.type = TYPE_8323;
+		break;
+	case 0x8036:
+		priv->info.type = TYPE_8343;
+		break;
+	case 0x8032:
+		priv->info.type = TYPE_8347_TBGA;
+		break;
+	case 0x8034:
+		priv->info.type = TYPE_8347_PBGA;
+		break;
+	case 0x8030:
+		priv->info.type = TYPE_8349;
+		break;
+	case 0x804A:
+		priv->info.type = TYPE_8358_TBGA;
+		break;
+	case 0x804E:
+		priv->info.type = TYPE_8358_PBGA;
+		break;
+	case 0x8048:
+		priv->info.type = TYPE_8360;
+		break;
+	case 0x80C6:
+		priv->info.type = TYPE_8377;
+		break;
+	case 0x80C4:
+		priv->info.type = TYPE_8378;
+		break;
+	case 0x80C2:
+		priv->info.type = TYPE_8379;
+		break;
+	default:
+		priv->info.type = TYPE_UNKNOWN;
+	}
+}
+
+static inline void determine_e300_type(struct udevice *dev)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+	u32 pvr = get_pvr();
+
+	switch (pvr & 0xffff0000) {
+	case 0x80830000:
+		priv->info.e300_type = E300C1;
+		break;
+	case 0x80840000:
+		priv->info.e300_type = E300C2;
+		break;
+	case 0x80850000:
+		priv->info.e300_type = E300C3;
+		break;
+	case 0x80860000:
+		priv->info.e300_type = E300C4;
+		break;
+	default:
+		priv->info.e300_type = E300_UNKNOWN;
+	}
+}
+
+static inline void determine_revid_other(struct udevice *dev)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+	u32 spridr = get_spridr();
+
+	priv->info.revid.major = (spridr & 0x000000F0) >> 4;
+	priv->info.revid.minor = spridr & 0x0000000F;
+}
+
+static inline void determine_revid_mpc834x(struct udevice *dev)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+	u32 spridr = get_spridr();
+
+	priv->info.revid.major = (spridr & 0x0000FF00) >> 8;
+	priv->info.revid.minor = spridr & 0x000000FF;
+}
+
+static void determine_cpu_data(struct udevice *dev)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+	u32 spridr = get_spridr();
+
+	determine_family(dev);
+	determine_type(dev);
+	determine_e300_type(dev);
+
+	if (priv->info.family == FAMILY_834X)
+		determine_revid_mpc834x(dev);
+	else
+		determine_revid_other(dev);
+
+	if ((priv->info.family == FAMILY_834X ||
+	     priv->info.family == FAMILY_836X) && priv->info.revid.major >= 2)
+		priv->info.is_a_variant = true;
+
+	priv->info.is_e_processor = !(spridr & 0x00010000);
+}
+
+static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size)
+{
+	struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
+	struct clk core_clk;
+	struct clk csb_clk;
+	char core_freq[32];
+	char csb_freq[32];
+
+	clk_get_by_index(dev, 0, &core_clk);
+	clk_get_by_index(dev, 1, &csb_clk);
+
+	determine_cpu_data(dev);
+
+	snprintf(buf, size, "CPU:   %s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz\n",
+		 e300_names[priv->info.e300_type],
+		 cpu_type_names[priv->info.type],
+		 priv->info.is_e_processor ? "E" : "",
+		 priv->info.is_a_variant ? "A" : "",
+		 priv->info.revid.major,
+		 priv->info.revid.minor,
+		 strmhz(core_freq, clk_get_rate(&core_clk)),
+		 strmhz(csb_freq, clk_get_rate(&csb_clk)));
+
+	return 0;
+}
+
+static int mpc83xx_cpu_get_info(struct udevice *dev, struct cpu_info *info)
+{
+	struct clk clock;
+
+	clk_get_by_index(dev, 0, &clock);
+
+	info->cpu_freq = clk_get_rate(&clock);
+	info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
+
+	return 0;
+}
+
+static int mpc83xx_cpu_get_count(struct udevice *dev)
+{
+	/* TODO(mario.six at gdsys.cc): Replace this with real number of cores */
+	return 1;
+}
+
+static int mpc83xx_cpu_get_vendor(struct udevice *dev, char *buf, int size)
+{
+	snprintf(buf, size, "NXP");
+
+	return 0;
+}
+
+static const struct cpu_ops mpc83xx_cpu_ops = {
+	.get_desc = mpc83xx_cpu_get_desc,
+	.get_info = mpc83xx_cpu_get_info,
+	.get_count = mpc83xx_cpu_get_count,
+	.get_vendor = mpc83xx_cpu_get_vendor,
+};
+
+int mpc83xx_cpu_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct udevice_id mpc83xx_cpu_ids[] = {
+	{ .compatible = "fsl,mpc8308", },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mpc83xx_cpu) = {
+	.name = "mpc83xx_cpu",
+	.id = UCLASS_CPU,
+	.of_match = mpc83xx_cpu_ids,
+	.probe = mpc83xx_cpu_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc83xx_cpu_priv),
+	.ops = &mpc83xx_cpu_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/cpu/mpc83xx_cpu.h b/drivers/cpu/mpc83xx_cpu.h
new file mode 100644
index 00000000000..0f9926d1877
--- /dev/null
+++ b/drivers/cpu/mpc83xx_cpu.h
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
+ */
+
+#ifndef _MPC83XX_CPU_H_
+#define _MPC83XX_CPU_H_
+
+enum e300_type {
+	E300C1,
+	E300C2,
+	E300C3,
+	E300C4,
+	E300_UNKNOWN,
+};
+
+static const char * const e300_names[] = {
+	[E300C1] = "e300c1",
+	[E300C2] = "e300c2",
+	[E300C3] = "e300c3",
+	[E300C4] = "e300c4",
+	[E300_UNKNOWN] = "Unknown e300",
+};
+
+enum mpc83xx_cpu_family {
+	FAMILY_831X,
+	FAMILY_832X,
+	FAMILY_834X,
+	FAMILY_836X,
+	FAMILY_837X,
+	FAMILY_UNKNOWN,
+};
+
+enum mpc83xx_cpu_type {
+	TYPE_8308,
+	TYPE_8309,
+	TYPE_8311,
+	TYPE_8313,
+	TYPE_8314,
+	TYPE_8315,
+	TYPE_8321,
+	TYPE_8323,
+	TYPE_8343,
+	TYPE_8347_TBGA,
+	TYPE_8347_PBGA,
+	TYPE_8349,
+	TYPE_8358_TBGA,
+	TYPE_8358_PBGA,
+	TYPE_8360,
+	TYPE_8377,
+	TYPE_8378,
+	TYPE_8379,
+	TYPE_UNKNOWN,
+};
+
+static const char * const cpu_type_names[] = {
+	[TYPE_8308] = "8308",
+	[TYPE_8309] = "8309",
+	[TYPE_8311] = "8311",
+	[TYPE_8313] = "8313",
+	[TYPE_8314] = "8314",
+	[TYPE_8315] = "8315",
+	[TYPE_8321] = "8321",
+	[TYPE_8323] = "8323",
+	[TYPE_8343] = "8343",
+	[TYPE_8347_TBGA] = "8347_TBGA",
+	[TYPE_8347_PBGA] = "8347_PBGA",
+	[TYPE_8349] = "8349",
+	[TYPE_8358_TBGA] = "8358_TBGA",
+	[TYPE_8358_PBGA] = "8358_PBGA",
+	[TYPE_8360] = "8360",
+	[TYPE_8377] = "8377",
+	[TYPE_8378] = "8378",
+	[TYPE_8379] = "8379",
+	[TYPE_UNKNOWN] = "Unknown CPU",
+};
+
+struct mpc83xx_cpu_info {
+	enum e300_type e300_type;
+	enum mpc83xx_cpu_family family;
+	enum mpc83xx_cpu_type type;
+	bool is_e_processor;
+	bool is_a_variant;
+	struct {
+		uint major;
+		uint minor;
+	} revid;
+};
+
+static const char * const event[] = {
+	"Address Time Out",
+	"Data Time Out",
+	"Address Only Transfer Type",
+	"External Control Word Transfer Type",
+	"Reserved Transfer Type",
+	"Transfer Error",
+	"reserved",
+	"reserved"
+};
+
+static const char * const master[] = {
+	"e300 Core Data Transaction",
+	"reserved",
+	"e300 Core Instruction Fetch",
+	"reserved",
+	"TSEC1",
+	"TSEC2",
+	"USB MPH",
+	"USB DR",
+	"Encryption Core",
+	"I2C Boot Sequencer",
+	"JTAG",
+	"reserved",
+	"eSDHC",
+	"PCI1",
+	"PCI2",
+	"DMA",
+	"QUICC Engine 00",
+	"QUICC Engine 01",
+	"QUICC Engine 10",
+	"QUICC Engine 11",
+	"reserved",
+	"reserved",
+	"reserved",
+	"reserved",
+	"SATA1",
+	"SATA2",
+	"SATA3",
+	"SATA4",
+	"reserved",
+	"PCI Express 1",
+	"PCI Express 2",
+	"TDM-DMAC"
+};
+
+static const char * const transfer[] = {
+	"Address-only, Clean Block",
+	"Address-only, lwarx reservation set",
+	"Single-beat or Burst write",
+	"reserved",
+	"Address-only, Flush Block",
+	"reserved",
+	"Burst write",
+	"reserved",
+	"Address-only, sync",
+	"Address-only, tlbsync",
+	"Single-beat or Burst read",
+	"Single-beat or Burst read",
+	"Address-only, Kill Block",
+	"Address-only, icbi",
+	"Burst read",
+	"reserved",
+	"Address-only, eieio",
+	"reserved",
+	"Single-beat write",
+	"reserved",
+	"ecowx - Illegal single-beat write",
+	"reserved",
+	"reserved",
+	"reserved",
+	"Address-only, TLB Invalidate",
+	"reserved",
+	"Single-beat or Burst read",
+	"reserved",
+	"eciwx - Illegal single-beat read",
+	"reserved",
+	"Burst read",
+	"reserved"
+};
+
+#endif /* !_MPC83XX_CPU_H_ */
diff --git a/include/cpu.h b/include/cpu.h
index 5cc7c5abd72..e1de356b543 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -43,6 +43,7 @@ enum {
 struct cpu_info {
 	ulong cpu_freq;
 	ulong features;
+	void *specific_info;
 };

 struct cpu_ops {
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 11/11] misc: Add MPC83xx serdes driver
  2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
                   ` (8 preceding siblings ...)
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver Mario Six
@ 2018-05-24  8:42 ` Mario Six
  2018-05-25  2:42   ` Simon Glass
  9 siblings, 1 reply; 22+ messages in thread
From: Mario Six @ 2018-05-24  8:42 UTC (permalink / raw)
  To: u-boot

Add a driver to configure the SerDes (Serializer/Deserializer) lanes on
the MPC83xx architecture.

Signed-off-by: Mario Six <mario.six@gdsys.cc>

---

v2 -> v3:
* Added driver file to MAINTAINERS

v1 -> v2:
No changes

---
 MAINTAINERS                                   |   1 +
 arch/powerpc/cpu/mpc83xx/serdes.c             |   4 +
 arch/powerpc/include/asm/fsl_mpc83xx_serdes.h |   4 +
 drivers/misc/Kconfig                          |   7 +
 drivers/misc/Makefile                         |   1 +
 drivers/misc/mpc83xx_serdes.c                 | 228 ++++++++++++++++++++++++++
 6 files changed, 245 insertions(+)
 create mode 100644 drivers/misc/mpc83xx_serdes.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 11965be1402..d55632617ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -477,6 +477,7 @@ F:	include/dt-bindings/clk/mpc83xx-clk.h
 F:	drivers/timer/mpc83xx_timer.c
 F:	drivers/cpu/mpc83xx_cpu.c
 F:	drivers/cpu/mpc83xx_cpu.h
+F:	drivers/misc/mpc83xx_serdes.c
 F:	arch/powerpc/cpu/mpc83xx/
 F:	arch/powerpc/include/asm/arch-mpc83xx/

diff --git a/arch/powerpc/cpu/mpc83xx/serdes.c b/arch/powerpc/cpu/mpc83xx/serdes.c
index 982a4475f00..8242f952653 100644
--- a/arch/powerpc/cpu/mpc83xx/serdes.c
+++ b/arch/powerpc/cpu/mpc83xx/serdes.c
@@ -8,6 +8,8 @@
  * Author: Li Yang <leoli@freescale.com>
  */

+#ifndef CONFIG_MPC83XX_SERDES
+
 #include <config.h>
 #include <common.h>
 #include <asm/io.h>
@@ -148,3 +150,5 @@ void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd)
 	tmp |= FSL_SRDSRSTCTL_RST;
 	out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
 }
+
+#endif /* !CONFIG_MPC83XX_SERDES */
diff --git a/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h b/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h
index e51d060d6a7..a02b5992654 100644
--- a/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h
+++ b/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h
@@ -6,6 +6,8 @@
 #ifndef __FSL_MPC83XX_SERDES_H
 #define __FSL_MPC83XX_SERDES_H

+#ifndef CONFIG_MPC83XX_SERDES
+
 #include <config.h>

 #define FSL_SERDES_CLK_100		(0 << 28)
@@ -19,4 +21,6 @@

 extern void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd);

+#endif /* !CONFIG_MPC83XX_SERDES */
+
 #endif /* __FSL_MPC83XX_SERDES_H */
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index be900cf4d6e..4794f615093 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -268,4 +268,11 @@ config GDSYS_RXAUI_CTRL
 	depends on MISC
 	help
 	  Support gdsys FPGA's RXAUI control.
+
+config MPC83XX_SERDES
+	bool "Enable MPC83xx serdes driver"
+	depends on MISC
+	help
+	  Support for serdes found on MPC83xx SoCs.
+
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e362609d62a..f53f87a3639 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
 obj-$(CONFIG_STM32_RCC) += stm32_rcc.o
 obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
 obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
+obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
diff --git a/drivers/misc/mpc83xx_serdes.c b/drivers/misc/mpc83xx_serdes.c
new file mode 100644
index 00000000000..981128e300d
--- /dev/null
+++ b/drivers/misc/mpc83xx_serdes.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * base on the MPC83xx serdes initialization, which is
+ *
+ * Copyright 2007,2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 MontaVista Software, Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <misc.h>
+#include <mapmem.h>
+
+enum {
+	SRDSCR0_DPP_1V2    = 0x00008800,
+
+	SRDSCR0_TXEQA_MASK = 0x00007000,
+	SRDSCR0_TXEQA_SATA = 0x00001000,
+	SRDSCR0_TXEQE_MASK = 0x00000700,
+	SRDSCR0_TXEQE_SATA = 0x00000100,
+};
+
+enum {
+	SRDSCR1_PLLBW = 0x00000040
+};
+
+enum {
+	SRDSCR2_VDD_1V2    = 0x00800000,
+
+	SRDSCR2_SEIC_MASK  = 0x00001c1c,
+	SRDSCR2_SEIC_SATA  = 0x00001414,
+	SRDSCR2_SEIC_PEX   = 0x00001010,
+	SRDSCR2_SEIC_SGMII = 0x00000101,
+};
+
+enum {
+	SRDSCR3_KFR_SATA      = 0x10100000,
+	SRDSCR3_KPH_SATA      = 0x04040000,
+	SRDSCR3_SDFM_SATA_PEX = 0x01010000,
+	SRDSCR3_SDTXL_SATA    = 0x00000505,
+};
+
+enum {
+	SRDSCR4_PROT_SATA  = 0x00000808,
+	SRDSCR4_PROT_PEX   = 0x00000101,
+	SRDSCR4_PROT_SGMII = 0x00000505,
+
+	SRDSCR4_PLANE_X2   = 0x01000000,
+};
+
+enum {
+	SRDSRSTCTL_RST        = 0x80000000,
+	SRDSRSTCTL_SATA_RESET = 0xf,
+};
+
+enum {
+	SERDES_CLK_100 = (0 << 28),
+	SERDES_CLK_125 = (1 << 28),
+	SERDES_CLK_150 = (3 << 28),
+};
+
+struct mpc83xx_serdes_regs {
+	u32 srdscr0;
+	u32 srdscr1;
+	u32 srdscr2;
+	u32 srdscr3;
+	u32 srdscr4;
+	u8 fill0[12];
+	u32 srdsrstctl;
+};
+
+enum pex_type {
+	PEX_X1,
+	PEX_X2,
+};
+
+struct mpc83xx_serdes_priv {
+	struct mpc83xx_serdes_regs *regs;
+	u32 rfcks;
+};
+
+static const struct misc_ops mpc83xx_serdes_ops = {
+};
+
+void setup_sata(struct udevice *dev)
+{
+	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
+
+	/* Set and clear reset bits */
+	setbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_SATA_RESET);
+	udelay(1000);
+	clrbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_SATA_RESET);
+
+	/* Configure SRDSCR0 */
+	clrsetbits_be32(&priv->regs->srdscr0,
+			SRDSCR0_TXEQA_MASK | SRDSCR0_TXEQE_MASK,
+			SRDSCR0_TXEQA_SATA | SRDSCR0_TXEQE_SATA);
+
+	/* Configure SRDSCR1 */
+	clrbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
+
+	/* Configure SRDSCR2 */
+	clrsetbits_be32(&priv->regs->srdscr2,
+			SRDSCR2_SEIC_MASK,
+			SRDSCR2_SEIC_SATA);
+
+	/* Configure SRDSCR3 */
+	out_be32(&priv->regs->srdscr3,
+		 SRDSCR3_KFR_SATA | SRDSCR3_KPH_SATA |
+		 SRDSCR3_SDFM_SATA_PEX | SRDSCR3_SDTXL_SATA);
+
+	/* Configure SRDSCR4 */
+	out_be32(&priv->regs->srdscr4, priv->rfcks | SRDSCR4_PROT_SATA);
+}
+
+void setup_pex(struct udevice *dev, enum pex_type type)
+{
+	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
+
+	/* Configure SRDSCR1 */
+	setbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
+
+	/* Configure SRDSCR2 */
+	clrsetbits_be32(&priv->regs->srdscr2,
+			SRDSCR2_SEIC_MASK,
+			SRDSCR2_SEIC_PEX);
+
+	/* Configure SRDSCR3 */
+	out_be32(&priv->regs->srdscr3, SRDSCR3_SDFM_SATA_PEX);
+
+	/* Configure SRDSCR4 */
+	if (type == PEX_X2)
+		out_be32(&priv->regs->srdscr4,
+			 priv->rfcks | SRDSCR4_PROT_PEX | SRDSCR4_PLANE_X2);
+	else
+		out_be32(&priv->regs->srdscr4,
+			 priv->rfcks | SRDSCR4_PROT_PEX);
+}
+
+void setup_sgmii(struct udevice *dev)
+{
+	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
+
+	/* Configure SRDSCR1 */
+	clrbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
+
+	/* Configure SRDSCR2 */
+	clrsetbits_be32(&priv->regs->srdscr2,
+			SRDSCR2_SEIC_MASK,
+			SRDSCR2_SEIC_SGMII);
+
+	/* Configure SRDSCR3 */
+	out_be32(&priv->regs->srdscr3, 0);
+
+	/* Configure SRDSCR4 */
+	out_be32(&priv->regs->srdscr4, priv->rfcks | SRDSCR4_PROT_SGMII);
+}
+
+int mpc83xx_serdes_probe(struct udevice *dev)
+{
+	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
+	bool vdd;
+	const char *proto;
+
+	priv->regs = map_sysmem(dev_read_addr(dev),
+				sizeof(struct mpc83xx_serdes_regs));
+
+	vdd = dev_read_bool(dev, "vdd");
+
+	switch (dev_read_u32_default(dev, "serdes-clk", -1)) {
+	case 100:
+		priv->rfcks = SERDES_CLK_100;
+		break;
+	case 125:
+		priv->rfcks = SERDES_CLK_125;
+		break;
+	case 150:
+		priv->rfcks = SERDES_CLK_150;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* 1.0V corevdd */
+	if (vdd) {
+		/* DPPE/DPPA = 0 */
+		clrbits_be32(&priv->regs->srdscr0, SRDSCR0_DPP_1V2);
+
+		/* VDD = 0 */
+		clrbits_be32(&priv->regs->srdscr0, SRDSCR2_VDD_1V2);
+	}
+
+	proto = dev_read_string(dev, "proto");
+
+	/* protocol specific configuration */
+	if (!strcmp(proto, "sata"))
+		setup_sata(dev);
+	else if (!strcmp(proto, "pex"))
+		setup_pex(dev, PEX_X1);
+	else if (!strcmp(proto, "pex-x2"))
+		setup_pex(dev, PEX_X2);
+	else if (!strcmp(proto, "sgmii"))
+		setup_sgmii(dev);
+	else
+		return -EINVAL;
+
+	/* Do a software reset */
+	setbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_RST);
+
+	return 0;
+}
+
+static const struct udevice_id mpc83xx_serdes_ids[] = {
+	{ .compatible = "fsl,mpc83xx-serdes" },
+	{ }
+};
+
+U_BOOT_DRIVER(mpc83xx_serdes) = {
+	.name           = "mpc83xx_serdes",
+	.id             = UCLASS_MISC,
+	.ops		= &mpc83xx_serdes_ops,
+	.of_match       = mpc83xx_serdes_ids,
+	.probe          = mpc83xx_serdes_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc83xx_serdes_priv),
+};
--
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status Mario Six
@ 2018-05-25  2:41   ` Simon Glass
  2018-06-25  9:26     ` Mario Six
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Glass @ 2018-05-25  2:41 UTC (permalink / raw)
  To: u-boot

On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
> Add some tests for sysreset_get_status.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> New in v3.
>
> ---
>  drivers/sysreset/sysreset_sandbox.c | 16 ++++++++++++++++
>  test/dm/sysreset.c                  | 19 +++++++++++++++++++
>  2 files changed, 35 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
> index f12c4e84198..e03b5c122fe 100644
> --- a/drivers/sysreset/sysreset_sandbox.c
> +++ b/drivers/sysreset/sysreset_sandbox.c
> @@ -29,6 +29,13 @@ static int sandbox_warm_sysreset_request(struct udevice *dev,
>         return -EINPROGRESS;
>  }
>
> +int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size)
> +{
> +       strncpy(buf, "Reset Status: WARM", size);

strlcpy() might be better.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver Mario Six
@ 2018-05-25  2:42   ` Simon Glass
  2018-06-25  9:30     ` Mario Six
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Glass @ 2018-05-25  2:42 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
> Add a clock driver for the MPC83xx architecture.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> * Added driver files to MAINTAINERS
>
> v1 -> v2:
> * Added binding of sysreset driver
>
> ---
>  MAINTAINERS                           |   3 +
>  arch/powerpc/cpu/mpc83xx/speed.c      |   4 +
>  arch/powerpc/include/asm/config.h     |   2 +-
>  drivers/clk/Kconfig                   |   6 +
>  drivers/clk/Makefile                  |   1 +
>  drivers/clk/mpc83xx_clk.c             | 426 ++++++++++++++++++++++++++++++++++
>  drivers/clk/mpc83xx_clk.h             | 121 ++++++++++
>  include/dt-bindings/clk/mpc83xx-clk.h |  33 +++
>  8 files changed, 595 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/mpc83xx_clk.c
>  create mode 100644 drivers/clk/mpc83xx_clk.h
>  create mode 100644 include/dt-bindings/clk/mpc83xx-clk.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index b43e4bc179d..ab0f6a0a5d0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -471,6 +471,9 @@ T:  git git://git.denx.de/u-boot-mpc83xx.git
>  F:     drivers/ram/mpc83xx_sdram.c
>  F:     include/dt-bindings/memory/mpc83xx-sdram.h
>  F:     drivers/sysreset/sysreset_mpc83xx.c
> +F:     drivers/clk/mpc83xx_clk.c
> +F:     drivers/clk/mpc83xx_clk.h
> +F:     include/dt-bindings/clk/mpc83xx-clk.h
>  F:     arch/powerpc/cpu/mpc83xx/
>  F:     arch/powerpc/include/asm/arch-mpc83xx/
>
> diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
> index f0945281cd2..39bc1c53406 100644
> --- a/arch/powerpc/cpu/mpc83xx/speed.c
> +++ b/arch/powerpc/cpu/mpc83xx/speed.c
> @@ -6,6 +6,8 @@
>   * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
>   */
>
> +#ifndef CONFIG_CLK_MPC83XX
> +
>  #include <common.h>
>  #include <mpc83xx.h>
>  #include <command.h>
> @@ -590,3 +592,5 @@ U_BOOT_CMD(clocks, 1, 0, do_clocks,
>         "print clock configuration",
>         "    clocks"
>  );
> +
> +#endif
> diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
> index 284cfe21ab0..7bc8f5006ec 100644
> --- a/arch/powerpc/include/asm/config.h
> +++ b/arch/powerpc/include/asm/config.h
> @@ -78,7 +78,7 @@
>  /* All PPC boards must swap IDE bytes */
>  #define CONFIG_IDE_SWAP_IO
>
> -#if defined(CONFIG_DM_SERIAL)
> +#if defined(CONFIG_DM_SERIAL) && !defined(CONFIG_CLK_MPC83XX)
>  /*
>   * TODO: Convert this to a clock driver exists that can give us the UART
>   * clock here.
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index edb4ca58ea5..e6ebff0a9d4 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -98,4 +98,10 @@ config ICS8N3QV01
>           Crystal Oscillator). The output frequency can be programmed via an
>           I2C interface.
>
> +config CLK_MPC83XX
> +       bool "Enable MPC83xx clock driver"
> +       depends on CLK
> +       help
> +         Support for the clock driver of the MPC83xx series of SoCs.
> +
>  endmenu
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 58139b13a89..58f497d3a15 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
>  obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
>  obj-$(CONFIG_CLK_EXYNOS) += exynos/
>  obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
> +obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
>  obj-$(CONFIG_CLK_RENESAS) += renesas/
>  obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
>  obj-$(CONFIG_CLK_STM32MP1) += clk_stm32mp1.o
> diff --git a/drivers/clk/mpc83xx_clk.c b/drivers/clk/mpc83xx_clk.c
> new file mode 100644
> index 00000000000..80be597332d
> --- /dev/null
> +++ b/drivers/clk/mpc83xx_clk.c
> @@ -0,0 +1,426 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2017
> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
> + */
> +
> +#include <common.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <dm/lists.h>
> +#include <dt-bindings/clk/mpc83xx-clk.h>
> +
> +#include "mpc83xx_clk.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static u32 *speed;
> +
> +struct mpc83xx_clk_priv {
> +       u32 *speed;
> +};
> +
> +static const char * const names[] = {
> +       [MPC83XX_CLK_CORE] = "Core",
> +       [MPC83XX_CLK_CSB] = "Coherent System Bus",
> +       [MPC83XX_CLK_QE] = "QE",
> +       [MPC83XX_CLK_BRG] = "BRG",
> +       [MPC83XX_CLK_LBIU] = "Local Bus Controller",
> +       [MPC83XX_CLK_LCLK] = "Local Bus",
> +       [MPC83XX_CLK_MEM] = "DDR",
> +       [MPC83XX_CLK_MEM_SEC] = "DDR Secondary",
> +       [MPC83XX_CLK_ENC] = "SEC",
> +       [MPC83XX_CLK_I2C1] = "I2C1",
> +       [MPC83XX_CLK_I2C2] = "I2C2",
> +       [MPC83XX_CLK_TDM] = "TDM",
> +       [MPC83XX_CLK_SDHC] = "SDHC",
> +       [MPC83XX_CLK_TSEC1] = "TSEC1",
> +       [MPC83XX_CLK_TSEC2] = "TSEC2",
> +       [MPC83XX_CLK_USBDR] = "USB DR",
> +       [MPC83XX_CLK_USBMPH] = "USB MPH",
> +       [MPC83XX_CLK_PCIEXP1] = "PCIEXP1",
> +       [MPC83XX_CLK_PCIEXP2] = "PCIEXP2",
> +       [MPC83XX_CLK_SATA] = "SATA",
> +       [MPC83XX_CLK_DMAC] = "DMAC",
> +       [MPC83XX_CLK_PCI] = "PCI",
> +};
> +
> +struct clk_mode {
> +       u8 low;
> +       u8 high;
> +       int type;
> +};
> +
> +const struct clk_mode modes[] = {
> +       [MPC83XX_CLK_CORE] = {0, 0, TYPE_SPECIAL},
> +       [MPC83XX_CLK_CSB] = {0, 0, TYPE_SPECIAL},
> +       [MPC83XX_CLK_QE] = {0, 0, TYPE_SPECIAL},
> +       [MPC83XX_CLK_BRG] = {0, 0, TYPE_SPECIAL},
> +       [MPC83XX_CLK_MEM] = {1, 1, TYPE_SPMR_DIRECT_MULTIPLY },
> +       [MPC83XX_CLK_LBIU] = {0, 0, TYPE_SPMR_DIRECT_MULTIPLY },
> +       [MPC83XX_CLK_LCLK] = {0, 0, TYPE_SPECIAL},
> +       [MPC83XX_CLK_MEM_SEC] = {0, 0, TYPE_SPMR_DIRECT_MULTIPLY }, /* The same as LBIU */
> +#ifndef CONFIG_MPC8313
> +       [MPC83XX_CLK_TSEC1] = {0, 1, TYPE_SCCR_STANDARD },
> +       [MPC83XX_CLK_TSEC2] = {2, 3, TYPE_SCCR_STANDARD },
> +#else
> +       [MPC83XX_CLK_TSEC1] = {0, 1, TYPE_SCCR_STANDARD }, /* FIXME: This has separate enable/disable bit! */
> +       [MPC83XX_CLK_TSEC2] = {0, 1, TYPE_SCCR_STANDARD }, /* FIXME: This has separate enable/disable bit! */
> +#endif

Do you really need all these #ifdefs? It's really unfortunate to have
a driver which requires build-time #ifdefs. You have the device tree
which should be enough to determine what to do. What is the issue
here?

Regards,
Simon

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver Mario Six
@ 2018-05-25  2:42   ` Simon Glass
  2018-06-25  9:32     ` Mario Six
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Glass @ 2018-05-25  2:42 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
> Add a timer driver for the MPC83xx architecture.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> * Got rid of the static variables
> * Added driver files to MAINTAINERS
>
> v1 -> v2:
> * Removed now-superfluous comments
> * Removed usage of uclass_{first,next}_device_compat
> * Switched to usage of new board uclass (instead of devinfo)
>
> ---
>  MAINTAINERS                    |   1 +
>  arch/powerpc/cpu/mpc83xx/cpu.c |   4 +-
>  arch/powerpc/lib/Makefile      |   4 +
>  arch/powerpc/lib/interrupts.c  |   5 +-
>  drivers/timer/Kconfig          |   7 ++
>  drivers/timer/Makefile         |   1 +
>  drivers/timer/mpc83xx_timer.c  | 182 +++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 201 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/timer/mpc83xx_timer.c
>
[..]

> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
> index ee2fcb1fa71..75360d81de3 100644
> --- a/drivers/timer/Makefile
> +++ b/drivers/timer/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
>  obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
>  obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
>  obj-$(CONFIG_STM32_TIMER)      += stm32_timer.o
> +obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
> diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c
> new file mode 100644
> index 00000000000..148fb2550ca
> --- /dev/null
> +++ b/drivers/timer/mpc83xx_timer.c
> @@ -0,0 +1,182 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2018
> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <clk.h>
> +#include <timer.h>
> +#include <watchdog.h>
> +#include <board.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct mpc83xx_timer_priv {
> +       uint decrementer_count; /* count value for 1e6/HZ microseconds */
> +       ulong timestamp;
> +};
> +
> +static inline unsigned long get_dec(void)
> +{
> +       unsigned long val;
> +
> +       asm volatile ("mfdec %0" : "=r" (val) : );
> +
> +       return val;
> +}
> +
> +static inline void set_dec(unsigned long val)
> +{
> +       if (val)
> +               asm volatile ("mtdec %0"::"r" (val));
> +}
> +
> +/* TODO(mario.six at gdsys.cc): This should really be done by timer_init, and the
> + * interrupt init should go into a interrupt driver.
> + */
> +int interrupt_init(void)
> +{
> +       immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
> +       struct udevice *csb;
> +       struct udevice *board;
> +       struct udevice *timer = gd->timer;
> +       struct mpc83xx_timer_priv *timer_priv = dev_get_priv(timer);
> +       struct clk clock;
> +       int ret;
> +
> +       if (get_board(&board)) {
> +               debug("%s: board device could not be fetched.\n", __func__);
> +               return -ENOENT;
> +       }
> +
> +       ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, board,
> +                                          "csb", &csb);
> +       if (ret) {
> +               debug("%s: Could not retrieve CSB device (error: %d)",
> +                     __func__, ret);
> +               return ret;
> +       }
> +
> +       ret = clk_get_by_index(csb, 0, &clock);
> +       if (ret) {
> +               debug("%s: Could not retrieve clock (error: %d)",
> +                     __func__, ret);
> +               return ret;
> +       }
> +
> +       timer_priv->decrementer_count = (clk_get_rate(&clock) / 4)
> +                                       / CONFIG_SYS_HZ;
> +       /* Enable e300 time base */
> +       setbits_be32(&immr->sysconf.spcr, 0x00400000);
> +
> +       set_dec(timer_priv->decrementer_count);
> +
> +       set_msr(get_msr() | MSR_EE);
> +
> +       return 0;
> +}
> +
> +void timer_interrupt(struct pt_regs *regs)
> +{
> +       struct udevice *timer = gd->timer;
> +       struct mpc83xx_timer_priv *priv = dev_get_priv(timer);
> +
> +       /* Restore Decrementer Count */
> +       set_dec(priv->decrementer_count);
> +
> +       priv->timestamp++;
> +
> +#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
> +       if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
> +               WATCHDOG_RESET();
> +#endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
> +
> +#ifdef CONFIG_LED_STATUS
> +       status_led_tick(priv->timestamp);
> +#endif /* CONFIG_LED_STATUS */
> +
> +#ifdef CONFIG_SHOW_ACTIVITY
> +       board_show_activity(priv->timestamp);
> +#endif /* CONFIG_SHOW_ACTIVITY */
> +}
> +
> +ulong get_timer(ulong base)

How come you are defining that? The standard one should work, and it
calls get_ticks() which should call your driver.

Regards,
Simon

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active Mario Six
@ 2018-05-25  2:42   ` Simon Glass
  2018-06-25  9:33     ` Mario Six
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Glass @ 2018-05-25  2:42 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
> When the DM CPU drivers are active, printing information about a CPU
> should be delegated to a matching driver.
>
> Hence, add a static print_cpuinfo that implements this delegation when
> DM CPU drivers are active.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> No changes
>
> v1 -> v2:
> New in v2
>
> ---
>  common/board_f.c | 16 ++++++++++++++++
>  include/init.h   |  2 ++
>  2 files changed, 18 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

See below

>
> diff --git a/common/board_f.c b/common/board_f.c
> index a716eeb8990..327c7d83e2c 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -11,6 +11,7 @@
>
>  #include <common.h>
>  #include <console.h>
> +#include <cpu.h>
>  #include <dm.h>
>  #include <environment.h>
>  #include <fdtdec.h>
> @@ -165,6 +166,21 @@ static int print_resetinfo(void)
>  }
>  #endif
>
> +#if defined(CONFIG_DISPLAY_CPUINFO) && defined(CONFIG_CPU)
> +static int print_cpuinfo(void)
> +{
> +       struct udevice *dev;
> +       char desc[512];
> +
> +       uclass_first_device_err(UCLASS_CPU, &dev);
> +
> +       cpu_get_desc(dev, desc, sizeof(desc));

If this returns an error, I think you should print the error instead

> +       printf("%s", desc);
> +
> +       return 0;
> +}
> +#endif
> +
>  static int announce_dram_init(void)
>  {
>         puts("DRAM:  ");
> diff --git a/include/init.h b/include/init.h
> index f114a889631..38c9680c7a7 100644
> --- a/include/init.h
> +++ b/include/init.h
> @@ -107,7 +107,9 @@ int arch_reserve_stacks(void);
>   */
>  int init_cache_f_r(void);
>
> +#ifndef CONFIG_CPU
>  int print_cpuinfo(void);
> +#endif
>  int timer_init(void);
>  int reserve_mmu(void);
>  int misc_init_f(void);
> --
> 2.11.0
>

Regards,
SImon

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver Mario Six
@ 2018-05-25  2:42   ` Simon Glass
  2018-06-25  9:34     ` Mario Six
  0 siblings, 1 reply; 22+ messages in thread
From: Simon Glass @ 2018-05-25  2:42 UTC (permalink / raw)
  To: u-boot

Hi Mario,

On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
> Add a CPU driver for the MPC83xx architecture.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> * Added driver files to MAINTAINERS
>
> v1 -> v2:
> * Removed cpu_print_info
> * Fixed CPU info printing
> * Removed usage of uclass_{first,next}_device_compat
> * Removed printing of reset status
>
> ---
>  MAINTAINERS                          |   2 +
>  arch/powerpc/cpu/mpc83xx/cpu.c       |   2 +
>  arch/powerpc/cpu/mpc83xx/cpu_init.c  |   2 +
>  arch/powerpc/include/asm/processor.h |   2 +
>  drivers/cpu/Kconfig                  |   7 +
>  drivers/cpu/Makefile                 |   1 +
>  drivers/cpu/mpc83xx_cpu.c            | 265 +++++++++++++++++++++++++++++++++++
>  drivers/cpu/mpc83xx_cpu.h            | 172 +++++++++++++++++++++++
>  include/cpu.h                        |   1 +
>  9 files changed, 454 insertions(+)
>  create mode 100644 drivers/cpu/mpc83xx_cpu.c
>  create mode 100644 drivers/cpu/mpc83xx_cpu.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f03cfcc73b0..11965be1402 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -475,6 +475,8 @@ F:  drivers/clk/mpc83xx_clk.c
>  F:     drivers/clk/mpc83xx_clk.h
>  F:     include/dt-bindings/clk/mpc83xx-clk.h
>  F:     drivers/timer/mpc83xx_timer.c
> +F:     drivers/cpu/mpc83xx_cpu.c
> +F:     drivers/cpu/mpc83xx_cpu.h
>  F:     arch/powerpc/cpu/mpc83xx/
>  F:     arch/powerpc/include/asm/arch-mpc83xx/
>
> diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
> index ffb42415feb..b29f271e9bc 100644
> --- a/arch/powerpc/cpu/mpc83xx/cpu.c
> +++ b/arch/powerpc/cpu/mpc83xx/cpu.c
> @@ -25,6 +25,7 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +#ifndef CONFIG_CPU_MPC83XX
>  int checkcpu(void)
>  {
>         volatile immap_t *immr;
> @@ -114,6 +115,7 @@ int checkcpu(void)
>
>         return 0;
>  }
> +#endif
>
>  #ifndef CONFIG_SYSRESET
>  int
> diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
> index fcac9f63a81..1555205e069 100644
> --- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
> +++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
> @@ -464,6 +464,7 @@ static int print_83xx_arb_event(int force)
>  }
>  #endif /* CONFIG_DISPLAY_AER_xxxx */
>
> +#ifndef CONFIG_CPU_MPC83XX
>  /*
>   * Figure out the cause of the reset
>   */
> @@ -505,3 +506,4 @@ int prt_83xx_rsr(void)
>
>         return 0;
>  }
> +#endif
> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
> index 6fbe8c46b31..f97ce48cc27 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -1325,7 +1325,9 @@ void ll_puts(const char *);
>  /* In misc.c */
>  void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
>
> +#ifndef CONFIG_CPU_MPC83XX
>  int prt_83xx_rsr(void);
> +#endif
>
>  #endif /* ndef ASSEMBLY*/
>
> diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
> index 0d1424d38e9..d4052005e24 100644
> --- a/drivers/cpu/Kconfig
> +++ b/drivers/cpu/Kconfig
> @@ -6,3 +6,10 @@ config CPU
>           multiple CPUs, then normally have to be set up in U-Boot so that
>           they can work correctly in the OS. This provides a framework for
>           finding out information about available CPUs and making changes.
> +
> +config CPU_MPC83XX
> +       bool "Enable MPC83xx CPU driver"
> +       depends on CPU
> +       select CLK_MPC83XX
> +       help
> +         Support CPU cores for SoCs of the MPC83xx series.
> diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
> index db515f6f177..29d7da42fad 100644
> --- a/drivers/cpu/Makefile
> +++ b/drivers/cpu/Makefile
> @@ -7,3 +7,4 @@
>  obj-$(CONFIG_CPU) += cpu-uclass.o
>
>  obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
> +obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
> diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c
> new file mode 100644
> index 00000000000..550a7ad89f1
> --- /dev/null
> +++ b/drivers/cpu/mpc83xx_cpu.c
> @@ -0,0 +1,265 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2018
> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <cpu.h>
> +#include <clk.h>
> +#include <asm/immap_83xx.h>
> +
> +#include "mpc83xx_cpu.h"
> +
> +struct mpc83xx_cpu_priv {
> +       struct mpc83xx_cpu_info info;
> +};
> +
> +int checkcpu(void)
> +{
> +       struct udevice *cpu;
> +
> +       for (uclass_first_device(UCLASS_CPU, &cpu);
> +            cpu;
> +            uclass_next_device(&cpu)) {
> +       }

Can you please create a function in the CPU uclass to do this in a
separate patch? (probe all CPUs). It should return an error if
something goes wrong, but not print anything.

Then you can call it here.

[...]

> diff --git a/include/cpu.h b/include/cpu.h
> index 5cc7c5abd72..e1de356b543 100644
> --- a/include/cpu.h
> +++ b/include/cpu.h
> @@ -43,6 +43,7 @@ enum {
>  struct cpu_info {
>         ulong cpu_freq;
>         ulong features;
> +       void *specific_info;

Did you mean to add that?

Regards,
Simon

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 11/11] misc: Add MPC83xx serdes driver
  2018-05-24  8:42 ` [U-Boot] [PATCH v3 11/11] misc: Add MPC83xx serdes driver Mario Six
@ 2018-05-25  2:42   ` Simon Glass
  0 siblings, 0 replies; 22+ messages in thread
From: Simon Glass @ 2018-05-25  2:42 UTC (permalink / raw)
  To: u-boot

On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
> Add a driver to configure the SerDes (Serializer/Deserializer) lanes on
> the MPC83xx architecture.
>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>
> ---
>
> v2 -> v3:
> * Added driver file to MAINTAINERS
>
> v1 -> v2:
> No changes
>
> ---
>  MAINTAINERS                                   |   1 +
>  arch/powerpc/cpu/mpc83xx/serdes.c             |   4 +
>  arch/powerpc/include/asm/fsl_mpc83xx_serdes.h |   4 +
>  drivers/misc/Kconfig                          |   7 +
>  drivers/misc/Makefile                         |   1 +
>  drivers/misc/mpc83xx_serdes.c                 | 228 ++++++++++++++++++++++++++
>  6 files changed, 245 insertions(+)
>  create mode 100644 drivers/misc/mpc83xx_serdes.c

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status
  2018-05-25  2:41   ` Simon Glass
@ 2018-06-25  9:26     ` Mario Six
  0 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-06-25  9:26 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, May 25, 2018 at 4:41 AM, Simon Glass <sjg@chromium.org> wrote:
> On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
>> Add some tests for sysreset_get_status.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>
>> ---
>>
>> v2 -> v3:
>> New in v3.
>>
>> ---
>>  drivers/sysreset/sysreset_sandbox.c | 16 ++++++++++++++++
>>  test/dm/sysreset.c                  | 19 +++++++++++++++++++
>>  2 files changed, 35 insertions(+)
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
>>
>> diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
>> index f12c4e84198..e03b5c122fe 100644
>> --- a/drivers/sysreset/sysreset_sandbox.c
>> +++ b/drivers/sysreset/sysreset_sandbox.c
>> @@ -29,6 +29,13 @@ static int sandbox_warm_sysreset_request(struct udevice *dev,
>>         return -EINPROGRESS;
>>  }
>>
>> +int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size)
>> +{
>> +       strncpy(buf, "Reset Status: WARM", size);
>
> strlcpy() might be better.
>

OK, will use strlcpy() in v4.

Best regards,
Mario

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver
  2018-05-25  2:42   ` Simon Glass
@ 2018-06-25  9:30     ` Mario Six
  0 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-06-25  9:30 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, May 25, 2018 at 4:42 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
>> Add a clock driver for the MPC83xx architecture.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>
>> ---
>>
>> v2 -> v3:
>> * Added driver files to MAINTAINERS
>>
>> v1 -> v2:
>> * Added binding of sysreset driver
>>
>> ---
>>  MAINTAINERS                           |   3 +
>>  arch/powerpc/cpu/mpc83xx/speed.c      |   4 +
>>  arch/powerpc/include/asm/config.h     |   2 +-
>>  drivers/clk/Kconfig                   |   6 +
>>  drivers/clk/Makefile                  |   1 +
>>  drivers/clk/mpc83xx_clk.c             | 426 ++++++++++++++++++++++++++++++++++
>>  drivers/clk/mpc83xx_clk.h             | 121 ++++++++++
>>  include/dt-bindings/clk/mpc83xx-clk.h |  33 +++
>>  8 files changed, 595 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/clk/mpc83xx_clk.c
>>  create mode 100644 drivers/clk/mpc83xx_clk.h
>>  create mode 100644 include/dt-bindings/clk/mpc83xx-clk.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index b43e4bc179d..ab0f6a0a5d0 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -471,6 +471,9 @@ T:  git git://git.denx.de/u-boot-mpc83xx.git
>>  F:     drivers/ram/mpc83xx_sdram.c
>>  F:     include/dt-bindings/memory/mpc83xx-sdram.h
>>  F:     drivers/sysreset/sysreset_mpc83xx.c
>> +F:     drivers/clk/mpc83xx_clk.c
>> +F:     drivers/clk/mpc83xx_clk.h
>> +F:     include/dt-bindings/clk/mpc83xx-clk.h
>>  F:     arch/powerpc/cpu/mpc83xx/
>>  F:     arch/powerpc/include/asm/arch-mpc83xx/
>>
>> diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
>> index f0945281cd2..39bc1c53406 100644
>> --- a/arch/powerpc/cpu/mpc83xx/speed.c
>> +++ b/arch/powerpc/cpu/mpc83xx/speed.c
>> @@ -6,6 +6,8 @@
>>   * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
>>   */
>>
>> +#ifndef CONFIG_CLK_MPC83XX
>> +
>>  #include <common.h>
>>  #include <mpc83xx.h>
>>  #include <command.h>
>> @@ -590,3 +592,5 @@ U_BOOT_CMD(clocks, 1, 0, do_clocks,
>>         "print clock configuration",
>>         "    clocks"
>>  );
>> +
>> +#endif
>> diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
>> index 284cfe21ab0..7bc8f5006ec 100644
>> --- a/arch/powerpc/include/asm/config.h
>> +++ b/arch/powerpc/include/asm/config.h
>> @@ -78,7 +78,7 @@
>>  /* All PPC boards must swap IDE bytes */
>>  #define CONFIG_IDE_SWAP_IO
>>
>> -#if defined(CONFIG_DM_SERIAL)
>> +#if defined(CONFIG_DM_SERIAL) && !defined(CONFIG_CLK_MPC83XX)
>>  /*
>>   * TODO: Convert this to a clock driver exists that can give us the UART
>>   * clock here.
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index edb4ca58ea5..e6ebff0a9d4 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -98,4 +98,10 @@ config ICS8N3QV01
>>           Crystal Oscillator). The output frequency can be programmed via an
>>           I2C interface.
>>
>> +config CLK_MPC83XX
>> +       bool "Enable MPC83xx clock driver"
>> +       depends on CLK
>> +       help
>> +         Support for the clock driver of the MPC83xx series of SoCs.
>> +
>>  endmenu
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 58139b13a89..58f497d3a15 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -16,6 +16,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
>>  obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
>>  obj-$(CONFIG_CLK_EXYNOS) += exynos/
>>  obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
>> +obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
>>  obj-$(CONFIG_CLK_RENESAS) += renesas/
>>  obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
>>  obj-$(CONFIG_CLK_STM32MP1) += clk_stm32mp1.o
>> diff --git a/drivers/clk/mpc83xx_clk.c b/drivers/clk/mpc83xx_clk.c
>> new file mode 100644
>> index 00000000000..80be597332d
>> --- /dev/null
>> +++ b/drivers/clk/mpc83xx_clk.c
>> @@ -0,0 +1,426 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2017
>> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
>> + */
>> +
>> +#include <common.h>
>> +#include <clk-uclass.h>
>> +#include <dm.h>
>> +#include <dm/lists.h>
>> +#include <dt-bindings/clk/mpc83xx-clk.h>
>> +
>> +#include "mpc83xx_clk.h"
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +static u32 *speed;
>> +
>> +struct mpc83xx_clk_priv {
>> +       u32 *speed;
>> +};
>> +
>> +static const char * const names[] = {
>> +       [MPC83XX_CLK_CORE] = "Core",
>> +       [MPC83XX_CLK_CSB] = "Coherent System Bus",
>> +       [MPC83XX_CLK_QE] = "QE",
>> +       [MPC83XX_CLK_BRG] = "BRG",
>> +       [MPC83XX_CLK_LBIU] = "Local Bus Controller",
>> +       [MPC83XX_CLK_LCLK] = "Local Bus",
>> +       [MPC83XX_CLK_MEM] = "DDR",
>> +       [MPC83XX_CLK_MEM_SEC] = "DDR Secondary",
>> +       [MPC83XX_CLK_ENC] = "SEC",
>> +       [MPC83XX_CLK_I2C1] = "I2C1",
>> +       [MPC83XX_CLK_I2C2] = "I2C2",
>> +       [MPC83XX_CLK_TDM] = "TDM",
>> +       [MPC83XX_CLK_SDHC] = "SDHC",
>> +       [MPC83XX_CLK_TSEC1] = "TSEC1",
>> +       [MPC83XX_CLK_TSEC2] = "TSEC2",
>> +       [MPC83XX_CLK_USBDR] = "USB DR",
>> +       [MPC83XX_CLK_USBMPH] = "USB MPH",
>> +       [MPC83XX_CLK_PCIEXP1] = "PCIEXP1",
>> +       [MPC83XX_CLK_PCIEXP2] = "PCIEXP2",
>> +       [MPC83XX_CLK_SATA] = "SATA",
>> +       [MPC83XX_CLK_DMAC] = "DMAC",
>> +       [MPC83XX_CLK_PCI] = "PCI",
>> +};
>> +
>> +struct clk_mode {
>> +       u8 low;
>> +       u8 high;
>> +       int type;
>> +};
>> +
>> +const struct clk_mode modes[] = {
>> +       [MPC83XX_CLK_CORE] = {0, 0, TYPE_SPECIAL},
>> +       [MPC83XX_CLK_CSB] = {0, 0, TYPE_SPECIAL},
>> +       [MPC83XX_CLK_QE] = {0, 0, TYPE_SPECIAL},
>> +       [MPC83XX_CLK_BRG] = {0, 0, TYPE_SPECIAL},
>> +       [MPC83XX_CLK_MEM] = {1, 1, TYPE_SPMR_DIRECT_MULTIPLY },
>> +       [MPC83XX_CLK_LBIU] = {0, 0, TYPE_SPMR_DIRECT_MULTIPLY },
>> +       [MPC83XX_CLK_LCLK] = {0, 0, TYPE_SPECIAL},
>> +       [MPC83XX_CLK_MEM_SEC] = {0, 0, TYPE_SPMR_DIRECT_MULTIPLY }, /* The same as LBIU */
>> +#ifndef CONFIG_MPC8313
>> +       [MPC83XX_CLK_TSEC1] = {0, 1, TYPE_SCCR_STANDARD },
>> +       [MPC83XX_CLK_TSEC2] = {2, 3, TYPE_SCCR_STANDARD },
>> +#else
>> +       [MPC83XX_CLK_TSEC1] = {0, 1, TYPE_SCCR_STANDARD }, /* FIXME: This has separate enable/disable bit! */
>> +       [MPC83XX_CLK_TSEC2] = {0, 1, TYPE_SCCR_STANDARD }, /* FIXME: This has separate enable/disable bit! */
>> +#endif
>
> Do you really need all these #ifdefs? It's really unfortunate to have
> a driver which requires build-time #ifdefs. You have the device tree
> which should be enough to determine what to do. What is the issue
> here?
>

The code was mostly copied from the old MPC83xx support, which uses ifdefs to
distinguish between the different types of MPC83xx SoCs, which all have
slightly different memory layout in regards to the clock registers.

It shouldn't be too hard to make the decision depend on the compatible string.
Will be done for v4.

> Regards,
> Simon

Best regards,
Mario

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver
  2018-05-25  2:42   ` Simon Glass
@ 2018-06-25  9:32     ` Mario Six
  0 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-06-25  9:32 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, May 25, 2018 at 4:42 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
>> Add a timer driver for the MPC83xx architecture.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>
>> ---
>>
>> v2 -> v3:
>> * Got rid of the static variables
>> * Added driver files to MAINTAINERS
>>
>> v1 -> v2:
>> * Removed now-superfluous comments
>> * Removed usage of uclass_{first,next}_device_compat
>> * Switched to usage of new board uclass (instead of devinfo)
>>
>> ---
>>  MAINTAINERS                    |   1 +
>>  arch/powerpc/cpu/mpc83xx/cpu.c |   4 +-
>>  arch/powerpc/lib/Makefile      |   4 +
>>  arch/powerpc/lib/interrupts.c  |   5 +-
>>  drivers/timer/Kconfig          |   7 ++
>>  drivers/timer/Makefile         |   1 +
>>  drivers/timer/mpc83xx_timer.c  | 182 +++++++++++++++++++++++++++++++++++++++++
>>  7 files changed, 201 insertions(+), 3 deletions(-)
>>  create mode 100644 drivers/timer/mpc83xx_timer.c
>>
> [..]
>
>> diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
>> index ee2fcb1fa71..75360d81de3 100644
>> --- a/drivers/timer/Makefile
>> +++ b/drivers/timer/Makefile
>> @@ -16,3 +16,4 @@ obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
>>  obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
>>  obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
>>  obj-$(CONFIG_STM32_TIMER)      += stm32_timer.o
>> +obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
>> diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c
>> new file mode 100644
>> index 00000000000..148fb2550ca
>> --- /dev/null
>> +++ b/drivers/timer/mpc83xx_timer.c
>> @@ -0,0 +1,182 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2018
>> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <clk.h>
>> +#include <timer.h>
>> +#include <watchdog.h>
>> +#include <board.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +struct mpc83xx_timer_priv {
>> +       uint decrementer_count; /* count value for 1e6/HZ microseconds */
>> +       ulong timestamp;
>> +};
>> +
>> +static inline unsigned long get_dec(void)
>> +{
>> +       unsigned long val;
>> +
>> +       asm volatile ("mfdec %0" : "=r" (val) : );
>> +
>> +       return val;
>> +}
>> +
>> +static inline void set_dec(unsigned long val)
>> +{
>> +       if (val)
>> +               asm volatile ("mtdec %0"::"r" (val));
>> +}
>> +
>> +/* TODO(mario.six at gdsys.cc): This should really be done by timer_init, and the
>> + * interrupt init should go into a interrupt driver.
>> + */
>> +int interrupt_init(void)
>> +{
>> +       immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
>> +       struct udevice *csb;
>> +       struct udevice *board;
>> +       struct udevice *timer = gd->timer;
>> +       struct mpc83xx_timer_priv *timer_priv = dev_get_priv(timer);
>> +       struct clk clock;
>> +       int ret;
>> +
>> +       if (get_board(&board)) {
>> +               debug("%s: board device could not be fetched.\n", __func__);
>> +               return -ENOENT;
>> +       }
>> +
>> +       ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, board,
>> +                                          "csb", &csb);
>> +       if (ret) {
>> +               debug("%s: Could not retrieve CSB device (error: %d)",
>> +                     __func__, ret);
>> +               return ret;
>> +       }
>> +
>> +       ret = clk_get_by_index(csb, 0, &clock);
>> +       if (ret) {
>> +               debug("%s: Could not retrieve clock (error: %d)",
>> +                     __func__, ret);
>> +               return ret;
>> +       }
>> +
>> +       timer_priv->decrementer_count = (clk_get_rate(&clock) / 4)
>> +                                       / CONFIG_SYS_HZ;
>> +       /* Enable e300 time base */
>> +       setbits_be32(&immr->sysconf.spcr, 0x00400000);
>> +
>> +       set_dec(timer_priv->decrementer_count);
>> +
>> +       set_msr(get_msr() | MSR_EE);
>> +
>> +       return 0;
>> +}
>> +
>> +void timer_interrupt(struct pt_regs *regs)
>> +{
>> +       struct udevice *timer = gd->timer;
>> +       struct mpc83xx_timer_priv *priv = dev_get_priv(timer);
>> +
>> +       /* Restore Decrementer Count */
>> +       set_dec(priv->decrementer_count);
>> +
>> +       priv->timestamp++;
>> +
>> +#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
>> +       if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
>> +               WATCHDOG_RESET();
>> +#endif    /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
>> +
>> +#ifdef CONFIG_LED_STATUS
>> +       status_led_tick(priv->timestamp);
>> +#endif /* CONFIG_LED_STATUS */
>> +
>> +#ifdef CONFIG_SHOW_ACTIVITY
>> +       board_show_activity(priv->timestamp);
>> +#endif /* CONFIG_SHOW_ACTIVITY */
>> +}
>> +
>> +ulong get_timer(ulong base)
>
> How come you are defining that? The standard one should work, and it
> calls get_ticks() which should call your driver.
>

I see. I wasn't aware of the fact that the default timer driver infrastructure
already does that, so I copied the old get_timer implementation over to this
driver.

I'll use the default function in v4.

> Regards,
> Simon

Best regards,
Mario

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active
  2018-05-25  2:42   ` Simon Glass
@ 2018-06-25  9:33     ` Mario Six
  0 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-06-25  9:33 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, May 25, 2018 at 4:42 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
>> When the DM CPU drivers are active, printing information about a CPU
>> should be delegated to a matching driver.
>>
>> Hence, add a static print_cpuinfo that implements this delegation when
>> DM CPU drivers are active.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>
>> ---
>>
>> v2 -> v3:
>> No changes
>>
>> v1 -> v2:
>> New in v2
>>
>> ---
>>  common/board_f.c | 16 ++++++++++++++++
>>  include/init.h   |  2 ++
>>  2 files changed, 18 insertions(+)
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> See below
>
>>
>> diff --git a/common/board_f.c b/common/board_f.c
>> index a716eeb8990..327c7d83e2c 100644
>> --- a/common/board_f.c
>> +++ b/common/board_f.c
>> @@ -11,6 +11,7 @@
>>
>>  #include <common.h>
>>  #include <console.h>
>> +#include <cpu.h>
>>  #include <dm.h>
>>  #include <environment.h>
>>  #include <fdtdec.h>
>> @@ -165,6 +166,21 @@ static int print_resetinfo(void)
>>  }
>>  #endif
>>
>> +#if defined(CONFIG_DISPLAY_CPUINFO) && defined(CONFIG_CPU)
>> +static int print_cpuinfo(void)
>> +{
>> +       struct udevice *dev;
>> +       char desc[512];
>> +
>> +       uclass_first_device_err(UCLASS_CPU, &dev);
>> +
>> +       cpu_get_desc(dev, desc, sizeof(desc));
>
> If this returns an error, I think you should print the error instead
>

OK, will be fixed in v4.

>> +       printf("%s", desc);
>> +
>> +       return 0;
>> +}
>> +#endif
>> +
>>  static int announce_dram_init(void)
>>  {
>>         puts("DRAM:  ");
>> diff --git a/include/init.h b/include/init.h
>> index f114a889631..38c9680c7a7 100644
>> --- a/include/init.h
>> +++ b/include/init.h
>> @@ -107,7 +107,9 @@ int arch_reserve_stacks(void);
>>   */
>>  int init_cache_f_r(void);
>>
>> +#ifndef CONFIG_CPU
>>  int print_cpuinfo(void);
>> +#endif
>>  int timer_init(void);
>>  int reserve_mmu(void);
>>  int misc_init_f(void);
>> --
>> 2.11.0
>>
>
> Regards,
> SImon

Best regards,
Mario

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver
  2018-05-25  2:42   ` Simon Glass
@ 2018-06-25  9:34     ` Mario Six
  0 siblings, 0 replies; 22+ messages in thread
From: Mario Six @ 2018-06-25  9:34 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, May 25, 2018 at 4:42 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 24 May 2018 at 02:42, Mario Six <mario.six@gdsys.cc> wrote:
>> Add a CPU driver for the MPC83xx architecture.
>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>>
>> ---
>>
>> v2 -> v3:
>> * Added driver files to MAINTAINERS
>>
>> v1 -> v2:
>> * Removed cpu_print_info
>> * Fixed CPU info printing
>> * Removed usage of uclass_{first,next}_device_compat
>> * Removed printing of reset status
>>
>> ---
>>  MAINTAINERS                          |   2 +
>>  arch/powerpc/cpu/mpc83xx/cpu.c       |   2 +
>>  arch/powerpc/cpu/mpc83xx/cpu_init.c  |   2 +
>>  arch/powerpc/include/asm/processor.h |   2 +
>>  drivers/cpu/Kconfig                  |   7 +
>>  drivers/cpu/Makefile                 |   1 +
>>  drivers/cpu/mpc83xx_cpu.c            | 265 +++++++++++++++++++++++++++++++++++
>>  drivers/cpu/mpc83xx_cpu.h            | 172 +++++++++++++++++++++++
>>  include/cpu.h                        |   1 +
>>  9 files changed, 454 insertions(+)
>>  create mode 100644 drivers/cpu/mpc83xx_cpu.c
>>  create mode 100644 drivers/cpu/mpc83xx_cpu.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index f03cfcc73b0..11965be1402 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -475,6 +475,8 @@ F:  drivers/clk/mpc83xx_clk.c
>>  F:     drivers/clk/mpc83xx_clk.h
>>  F:     include/dt-bindings/clk/mpc83xx-clk.h
>>  F:     drivers/timer/mpc83xx_timer.c
>> +F:     drivers/cpu/mpc83xx_cpu.c
>> +F:     drivers/cpu/mpc83xx_cpu.h
>>  F:     arch/powerpc/cpu/mpc83xx/
>>  F:     arch/powerpc/include/asm/arch-mpc83xx/
>>
>> diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
>> index ffb42415feb..b29f271e9bc 100644
>> --- a/arch/powerpc/cpu/mpc83xx/cpu.c
>> +++ b/arch/powerpc/cpu/mpc83xx/cpu.c
>> @@ -25,6 +25,7 @@
>>
>>  DECLARE_GLOBAL_DATA_PTR;
>>
>> +#ifndef CONFIG_CPU_MPC83XX
>>  int checkcpu(void)
>>  {
>>         volatile immap_t *immr;
>> @@ -114,6 +115,7 @@ int checkcpu(void)
>>
>>         return 0;
>>  }
>> +#endif
>>
>>  #ifndef CONFIG_SYSRESET
>>  int
>> diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
>> index fcac9f63a81..1555205e069 100644
>> --- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
>> +++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
>> @@ -464,6 +464,7 @@ static int print_83xx_arb_event(int force)
>>  }
>>  #endif /* CONFIG_DISPLAY_AER_xxxx */
>>
>> +#ifndef CONFIG_CPU_MPC83XX
>>  /*
>>   * Figure out the cause of the reset
>>   */
>> @@ -505,3 +506,4 @@ int prt_83xx_rsr(void)
>>
>>         return 0;
>>  }
>> +#endif
>> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
>> index 6fbe8c46b31..f97ce48cc27 100644
>> --- a/arch/powerpc/include/asm/processor.h
>> +++ b/arch/powerpc/include/asm/processor.h
>> @@ -1325,7 +1325,9 @@ void ll_puts(const char *);
>>  /* In misc.c */
>>  void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
>>
>> +#ifndef CONFIG_CPU_MPC83XX
>>  int prt_83xx_rsr(void);
>> +#endif
>>
>>  #endif /* ndef ASSEMBLY*/
>>
>> diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
>> index 0d1424d38e9..d4052005e24 100644
>> --- a/drivers/cpu/Kconfig
>> +++ b/drivers/cpu/Kconfig
>> @@ -6,3 +6,10 @@ config CPU
>>           multiple CPUs, then normally have to be set up in U-Boot so that
>>           they can work correctly in the OS. This provides a framework for
>>           finding out information about available CPUs and making changes.
>> +
>> +config CPU_MPC83XX
>> +       bool "Enable MPC83xx CPU driver"
>> +       depends on CPU
>> +       select CLK_MPC83XX
>> +       help
>> +         Support CPU cores for SoCs of the MPC83xx series.
>> diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
>> index db515f6f177..29d7da42fad 100644
>> --- a/drivers/cpu/Makefile
>> +++ b/drivers/cpu/Makefile
>> @@ -7,3 +7,4 @@
>>  obj-$(CONFIG_CPU) += cpu-uclass.o
>>
>>  obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
>> +obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
>> diff --git a/drivers/cpu/mpc83xx_cpu.c b/drivers/cpu/mpc83xx_cpu.c
>> new file mode 100644
>> index 00000000000..550a7ad89f1
>> --- /dev/null
>> +++ b/drivers/cpu/mpc83xx_cpu.c
>> @@ -0,0 +1,265 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2018
>> + * Mario Six, Guntermann & Drunck GmbH, mario.six at gdsys.cc
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <cpu.h>
>> +#include <clk.h>
>> +#include <asm/immap_83xx.h>
>> +
>> +#include "mpc83xx_cpu.h"
>> +
>> +struct mpc83xx_cpu_priv {
>> +       struct mpc83xx_cpu_info info;
>> +};
>> +
>> +int checkcpu(void)
>> +{
>> +       struct udevice *cpu;
>> +
>> +       for (uclass_first_device(UCLASS_CPU, &cpu);
>> +            cpu;
>> +            uclass_next_device(&cpu)) {
>> +       }
>
> Can you please create a function in the CPU uclass to do this in a
> separate patch? (probe all CPUs). It should return an error if
> something goes wrong, but not print anything.
>
> Then you can call it here.
>

OK, will add a function like that in v4.

> [...]
>
>> diff --git a/include/cpu.h b/include/cpu.h
>> index 5cc7c5abd72..e1de356b543 100644
>> --- a/include/cpu.h
>> +++ b/include/cpu.h
>> @@ -43,6 +43,7 @@ enum {
>>  struct cpu_info {
>>         ulong cpu_freq;
>>         ulong features;
>> +       void *specific_info;
>
> Did you mean to add that?
>

No, that was a development artifact; thanks for noticing!

> Regards,
> Simon

Best regards,
Mario

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2018-06-25  9:34 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-24  8:41 [U-Boot] [PATCH v3 01/11] ram: Add driver for MPC83xx Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 02/11] sysreset: Add get_status method Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 03/11] test: Add tests for sysreset_get_status Mario Six
2018-05-25  2:41   ` Simon Glass
2018-06-25  9:26     ` Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 04/11] board_f: Add reset status printing Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 05/11] mpc83xx: Add sysreset driver Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 06/11] clk: Add MPC83xx clock driver Mario Six
2018-05-25  2:42   ` Simon Glass
2018-06-25  9:30     ` Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 07/11] timer: Add MPC83xx timer driver Mario Six
2018-05-25  2:42   ` Simon Glass
2018-06-25  9:32     ` Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 08/11] common: board_f: Sort includes Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 09/11] board_f: Use static print_cpuinfo if CONFIG_CPU is active Mario Six
2018-05-25  2:42   ` Simon Glass
2018-06-25  9:33     ` Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 10/11] cpu: Add MPC83xx CPU driver Mario Six
2018-05-25  2:42   ` Simon Glass
2018-06-25  9:34     ` Mario Six
2018-05-24  8:42 ` [U-Boot] [PATCH v3 11/11] misc: Add MPC83xx serdes driver Mario Six
2018-05-25  2:42   ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.