Kaynağa Gözat

Merge branch '2020-03-31-master-imports'

- mpc8xxx GPIO, SPI bugfixes
- Add VxWorks to FIT images
- macb ethernet driver bugfix
Tom Rini 4 yıl önce
ebeveyn
işleme
150db4264d

+ 7 - 0
arch/powerpc/dts/gdsys/mpc8308.dtsi

@@ -17,6 +17,7 @@
 /dts-v1/;
 
 #include <dt-bindings/memory/mpc83xx-sdram.h>
+#include <dt-bindings/clk/mpc83xx-clk.h>
 
 / {
 	compatible = "fsl,mpc8308rdb";
@@ -50,6 +51,11 @@
 		};
 	};
 
+	socclocks: clocks {
+		compatible = "fsl,mpc8308-clk";
+		#clock-cells = <1>;
+	};
+
 	board_lbc: localbus@e0005000 {
 		#address-cells = <2>;
 		#size-cells = <1>;
@@ -173,6 +179,7 @@
 			reg = <0x7000 0x1000>;
 			interrupts = <16 0x8>;
 			interrupt-parent = <&ipic>;
+			clocks = <&socclocks MPC83XX_CLK_CSB>;
 			mode = "cpu";
 		};
 

+ 2 - 2
cmd/mmc.c

@@ -264,7 +264,7 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
 		return CMD_RET_FAILURE;
 
 	if (!(mmc->version & MMC_VERSION_MMC)) {
-		printf("It is not a EMMC device\n");
+		printf("It is not an eMMC device\n");
 		return CMD_RET_FAILURE;
 	}
 	if (mmc->version < MMC_VERSION_4_41) {
@@ -718,7 +718,7 @@ static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
 		return CMD_RET_FAILURE;
 
 	if (IS_SD(mmc)) {
-		printf("It is not a EMMC device\n");
+		printf("It is not an eMMC device\n");
 		return CMD_RET_FAILURE;
 	}
 

+ 2 - 1
common/image-fit.c

@@ -2007,7 +2007,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
 		fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
 		fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
 		fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) ||
-		fit_image_check_os(fit, noffset, IH_OS_EFI);
+		fit_image_check_os(fit, noffset, IH_OS_EFI) ||
+		fit_image_check_os(fit, noffset, IH_OS_VXWORKS);
 
 	/*
 	 * If either of the checks fail, we should report an error, but

+ 22 - 0
doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt

@@ -0,0 +1,22 @@
+MPC83xx SPISEL_BOOT gpio controller
+
+Provide access to MPC83xx SPISEL_BOOT signal as a gpio to allow it to be
+easily bound as a SPI controller chip select.
+
+The SPISEL_BOOT signal is always an output.
+
+Required properties:
+
+- compatible: must be "fsl,mpc83xx-spisel-boot" or "fsl,mpc8309-spisel-boot".
+- reg: must point to the SPI_CS register in the SoC register map.
+- ngpios: number of gpios provided by driver, normally 1.
+
+Example:
+
+	spisel_boot: spisel_boot@14c {
+		compatible = "fsl,mpc8309-spisel-boot";
+		reg = <0x14c 0x04>;
+		#gpio-cells = <2>;
+		device_type = "gpio";
+		ngpios = <1>;
+	};

+ 8 - 0
drivers/gpio/Kconfig

@@ -423,6 +423,14 @@ config MPC8XXX_GPIO
 	  value setting, the open-drain feature, which can configure individual
 	  GPIOs to work as open-drain outputs, is supported.
 
+config MPC83XX_SPISEL_BOOT
+	bool "Freescale MPC83XX SPISEL_BOOT driver"
+	depends on DM_GPIO && ARCH_MPC830X
+	help
+	  GPIO driver to set/clear dedicated SPISEL_BOOT output on MPC83XX.
+
+	  This pin is typically used as spi chip select to a spi nor flash.
+
 config MT7621_GPIO
 	bool "MediaTek MT7621 GPIO driver"
 	depends on DM_GPIO && SOC_MT7628

+ 1 - 0
drivers/gpio/Makefile

@@ -40,6 +40,7 @@ obj-$(CONFIG_DM644X_GPIO)	+= da8xx_gpio.o
 obj-$(CONFIG_ALTERA_PIO)	+= altera_pio.o
 obj-$(CONFIG_MPC83XX_GPIO)	+= mpc83xx_gpio.o
 obj-$(CONFIG_MPC8XXX_GPIO)	+= mpc8xxx_gpio.o
+obj-$(CONFIG_MPC83XX_SPISEL_BOOT)	+= mpc83xx_spisel_boot.o
 obj-$(CONFIG_SH_GPIO_PFC)	+= sh_pfc.o
 obj-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 obj-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o

+ 148 - 0
drivers/gpio/mpc83xx_spisel_boot.c

@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 DEIF A/S
+ *
+ * GPIO driver to set/clear SPISEL_BOOT pin on mpc83xx.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <asm/gpio.h>
+
+struct mpc83xx_spisel_boot {
+	u32 __iomem *spi_cs;
+	ulong addr;
+	uint gpio_count;
+	ulong type;
+};
+
+static u32 gpio_mask(uint gpio)
+{
+	return (1U << (31 - (gpio)));
+}
+
+static int mpc83xx_spisel_boot_direction_input(struct udevice *dev, uint gpio)
+{
+	return -EINVAL;
+}
+
+static int mpc83xx_spisel_boot_set_value(struct udevice *dev, uint gpio, int value)
+{
+	struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
+
+	debug("%s: gpio=%d, value=%u, gpio_mask=0x%08x\n", __func__,
+	      gpio, value, gpio_mask(gpio));
+
+	if (value)
+		setbits_be32(data->spi_cs, gpio_mask(gpio));
+	else
+		clrbits_be32(data->spi_cs, gpio_mask(gpio));
+
+	return 0;
+}
+
+static int mpc83xx_spisel_boot_direction_output(struct udevice *dev, uint gpio, int value)
+{
+	return 0;
+}
+
+static int mpc83xx_spisel_boot_get_value(struct udevice *dev, uint gpio)
+{
+	struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
+
+	return !!(in_be32(data->spi_cs) & gpio_mask(gpio));
+}
+
+static int mpc83xx_spisel_boot_get_function(struct udevice *dev, uint gpio)
+{
+	return GPIOF_OUTPUT;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int mpc83xx_spisel_boot_ofdata_to_platdata(struct udevice *dev)
+{
+	struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
+	fdt_addr_t addr;
+	u32 reg[2];
+
+	dev_read_u32_array(dev, "reg", reg, 2);
+	addr = dev_translate_address(dev, reg);
+
+	plat->addr = addr;
+	plat->size = reg[1];
+	plat->ngpios = dev_read_u32_default(dev, "ngpios", 1);
+
+	return 0;
+}
+#endif
+
+static int mpc83xx_spisel_boot_platdata_to_priv(struct udevice *dev)
+{
+	struct mpc83xx_spisel_boot *priv = dev_get_priv(dev);
+	struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
+	unsigned long size = plat->size;
+	ulong driver_data = dev_get_driver_data(dev);
+
+	if (size == 0)
+		size = 0x04;
+
+	priv->addr = plat->addr;
+	priv->spi_cs = map_sysmem(plat->addr, size);
+
+	if (!priv->spi_cs)
+		return -ENOMEM;
+
+	priv->gpio_count = plat->ngpios;
+
+	priv->type = driver_data;
+
+	return 0;
+}
+
+static int mpc83xx_spisel_boot_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
+	char name[32], *str;
+
+	mpc83xx_spisel_boot_platdata_to_priv(dev);
+
+	snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
+	str = strdup(name);
+
+	if (!str)
+		return -ENOMEM;
+
+	uc_priv->bank_name = str;
+	uc_priv->gpio_count = data->gpio_count;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops mpc83xx_spisel_boot_ops = {
+	.direction_input	= mpc83xx_spisel_boot_direction_input,
+	.direction_output	= mpc83xx_spisel_boot_direction_output,
+	.get_value		= mpc83xx_spisel_boot_get_value,
+	.set_value		= mpc83xx_spisel_boot_set_value,
+	.get_function		= mpc83xx_spisel_boot_get_function,
+};
+
+static const struct udevice_id mpc83xx_spisel_boot_ids[] = {
+	{ .compatible = "fsl,mpc8309-spisel-boot" },
+	{ .compatible = "fsl,mpc83xx-spisel-boot" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(spisel_boot_mpc83xx) = {
+	.name	= "spisel_boot_mpc83xx",
+	.id	= UCLASS_GPIO,
+	.ops	= &mpc83xx_spisel_boot_ops,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.ofdata_to_platdata = mpc83xx_spisel_boot_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mpc8xxx_gpio_plat),
+	.of_match = mpc83xx_spisel_boot_ids,
+#endif
+	.probe	= mpc83xx_spisel_boot_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc83xx_spisel_boot),
+};

+ 15 - 26
drivers/gpio/mpc8xxx_gpio.c

@@ -57,27 +57,6 @@ static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
 	return in_be32(&base->gpdir) & mask;
 }
 
-static inline void mpc8xxx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
-{
-	clrbits_be32(&base->gpdat, gpios);
-	/* GPDIR register 0 -> input */
-	clrbits_be32(&base->gpdir, gpios);
-}
-
-static inline void mpc8xxx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
-{
-	clrbits_be32(&base->gpdat, gpios);
-	/* GPDIR register 1 -> output */
-	setbits_be32(&base->gpdir, gpios);
-}
-
-static inline void mpc8xxx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
-{
-	setbits_be32(&base->gpdat, gpios);
-	/* GPDIR register 1 -> output */
-	setbits_be32(&base->gpdir, gpios);
-}
-
 static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
 {
 	return in_be32(&base->gpodr) & mask;
@@ -100,22 +79,32 @@ static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base,
 static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio)
 {
 	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+	u32 mask = gpio_mask(gpio);
+
+	/* GPDIR register 0 -> input */
+	clrbits_be32(&data->base->gpdir, mask);
 
-	mpc8xxx_gpio_set_in(data->base, gpio_mask(gpio));
 	return 0;
 }
 
 static int mpc8xxx_gpio_set_value(struct udevice *dev, uint gpio, int value)
 {
 	struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
+	struct ccsr_gpio *base = data->base;
+	u32 mask = gpio_mask(gpio);
+	u32 gpdir;
 
 	if (value) {
-		data->dat_shadow |= gpio_mask(gpio);
-		mpc8xxx_gpio_set_high(data->base, gpio_mask(gpio));
+		data->dat_shadow |= mask;
 	} else {
-		data->dat_shadow &= ~gpio_mask(gpio);
-		mpc8xxx_gpio_set_low(data->base, gpio_mask(gpio));
+		data->dat_shadow &= ~mask;
 	}
+
+	gpdir = in_be32(&base->gpdir);
+	gpdir |= gpio_mask(gpio);
+	out_be32(&base->gpdat, gpdir & data->dat_shadow);
+	out_be32(&base->gpdir, gpdir);
+
 	return 0;
 }
 

+ 1 - 1
drivers/net/macb.c

@@ -807,7 +807,7 @@ static int _macb_init(struct macb_device *macb, const char *name)
 	macb->next_rx_tail = 0;
 
 #ifdef CONFIG_MACB_ZYNQ
-	macb_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
+	gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
 #endif
 
 	macb_writel(macb, RBQP, macb->rx_ring_dma);

+ 81 - 60
drivers/spi/mpc8xxx_spi.c

@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
@@ -27,6 +28,8 @@ enum {
 	SPI_MODE_EN    = BIT(31 - 7),	/* Enable interface */
 
 	SPI_MODE_LEN_MASK = 0xf00000,
+	SPI_MODE_LEN_SHIFT = 20,
+	SPI_MODE_PM_SHIFT = 16,
 	SPI_MODE_PM_MASK = 0xf0000,
 
 	SPI_COM_LST = BIT(31 - 9),
@@ -35,46 +38,38 @@ enum {
 struct mpc8xxx_priv {
 	spi8xxx_t *spi;
 	struct gpio_desc gpios[16];
-	int max_cs;
+	int cs_count;
+	ulong clk_rate;
 };
 
-static inline u32 to_prescale_mod(u32 val)
-{
-	return (min(val, (u32)15) << 16);
-}
-
-static void set_char_len(spi8xxx_t *spi, u32 val)
-{
-	clrsetbits_be32(&spi->mode, SPI_MODE_LEN_MASK, (val << 20));
-}
-
 #define SPI_TIMEOUT	1000
 
-static int __spi_set_speed(spi8xxx_t *spi, uint speed)
-{
-	/* TODO(mario.six@gdsys.cc): This only ever sets one fixed speed */
-
-	/* Use SYSCLK / 8 (16.67MHz typ.) */
-	clrsetbits_be32(&spi->mode, SPI_MODE_PM_MASK, to_prescale_mod(1));
-
-	return 0;
-}
-
 static int mpc8xxx_spi_ofdata_to_platdata(struct udevice *dev)
 {
 	struct mpc8xxx_priv *priv = dev_get_priv(dev);
+	struct clk clk;
 	int ret;
 
 	priv->spi = (spi8xxx_t *)dev_read_addr(dev);
 
-	/* TODO(mario.six@gdsys.cc): Read clock and save the value */
-
 	ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
 					ARRAY_SIZE(priv->gpios), GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
 	if (ret < 0)
 		return -EINVAL;
 
-	priv->max_cs = ret;
+	priv->cs_count = ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret) {
+		dev_err(dev, "%s: clock not defined\n", __func__);
+		return ret;
+	}
+
+	priv->clk_rate = clk_get_rate(&clk);
+	if (!priv->clk_rate) {
+		dev_err(dev, "%s: failed to get clock rate\n", __func__);
+		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -82,14 +77,18 @@ static int mpc8xxx_spi_ofdata_to_platdata(struct udevice *dev)
 static int mpc8xxx_spi_probe(struct udevice *dev)
 {
 	struct mpc8xxx_priv *priv = dev_get_priv(dev);
+	spi8xxx_t *spi = priv->spi;
 
 	/*
 	 * SPI pins on the MPC83xx are not muxed, so all we do is initialize
 	 * some registers
 	 */
-	out_be32(&priv->spi->mode, SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN);
+	out_be32(&priv->spi->mode, SPI_MODE_REV | SPI_MODE_MS);
+
+	/* set len to 8 bits */
+	setbits_be32(&spi->mode, (8 - 1) << SPI_MODE_LEN_SHIFT);
 
-	__spi_set_speed(priv->spi, 16666667);
+	setbits_be32(&spi->mode, SPI_MODE_EN);
 
 	/* Clear all SPI events */
 	setbits_be32(&priv->spi->event, 0xffffffff);
@@ -126,45 +125,35 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
 	struct mpc8xxx_priv *priv = dev_get_priv(bus);
 	spi8xxx_t *spi = priv->spi;
 	struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
-	u32 tmpdin = 0;
-	int num_blks = DIV_ROUND_UP(bitlen, 32);
+	u32 tmpdin = 0, tmpdout = 0, n;
+	const u8 *cout = dout;
+	u8 *cin = din;
 
 	debug("%s: slave %s:%u dout %08X din %08X bitlen %u\n", __func__,
-	      bus->name, platdata->cs, *(uint *)dout, *(uint *)din, bitlen);
+	      bus->name, platdata->cs, (uint)dout, (uint)din, bitlen);
+	if (platdata->cs >= priv->cs_count) {
+		dev_err(dev, "chip select index %d too large (cs_count=%d)\n",
+			platdata->cs, priv->cs_count);
+		return -EINVAL;
+	}
+	if (bitlen % 8) {
+		printf("*** spi_xfer: bitlen must be multiple of 8\n");
+		return -ENOTSUPP;
+	}
 
 	if (flags & SPI_XFER_BEGIN)
 		mpc8xxx_spi_cs_activate(dev);
 
 	/* Clear all SPI events */
 	setbits_be32(&spi->event, 0xffffffff);
+	n = bitlen / 8;
 
-	/* Handle data in 32-bit chunks */
-	while (num_blks--) {
-		u32 tmpdout = 0;
-		uchar xfer_bitlen = (bitlen >= 32 ? 32 : bitlen);
+	/* Handle data in 8-bit chunks */
+	while (n--) {
 		ulong start;
 
-		clrbits_be32(&spi->mode, SPI_MODE_EN);
-
-		/* Set up length for this transfer */
-
-		if (bitlen <= 4) /* 4 bits or less */
-			set_char_len(spi, 3);
-		else if (bitlen <= 16) /* at most 16 bits */
-			set_char_len(spi, bitlen - 1);
-		else /* more than 16 bits -> full 32 bit transfer */
-			set_char_len(spi, 0);
-
-		setbits_be32(&spi->mode, SPI_MODE_EN);
-
-		/* Shift data so it's msb-justified */
-		tmpdout = *(u32 *)dout >> (32 - xfer_bitlen);
-
-		if (bitlen > 32) {
-			/* Set up the next iteration if sending > 32 bits */
-			bitlen -= 32;
-			dout += 4;
-		}
+		if (cout)
+			tmpdout = *cout++;
 
 		/* Write the data out */
 		out_be32(&spi->tx, tmpdout);
@@ -188,11 +177,8 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
 			tmpdin = in_be32(&spi->rx);
 			setbits_be32(&spi->event, SPI_EV_NE);
 
-			*(u32 *)din = (tmpdin << (32 - xfer_bitlen));
-			if (xfer_bitlen == 32) {
-				/* Advance output buffer by 32 bits */
-				din += 4;
-			}
+			if (cin)
+				*cin++ = tmpdin;
 
 			/*
 			 * Only bail when we've had both NE and NF events.
@@ -224,8 +210,43 @@ static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
 static int mpc8xxx_spi_set_speed(struct udevice *dev, uint speed)
 {
 	struct mpc8xxx_priv *priv = dev_get_priv(dev);
+	spi8xxx_t *spi = priv->spi;
+	u32 bits, mask, div16, pm;
+	u32 mode;
+	ulong clk;
+
+	clk = priv->clk_rate;
+	if (clk / 64 > speed) {
+		div16 = SPI_MODE_DIV16;
+		clk /= 16;
+	} else {
+		div16 = 0;
+	}
+	pm = (clk - 1)/(4*speed) + 1;
+	if (pm > 16) {
+		dev_err(dev, "requested speed %u too small\n", speed);
+		return -EINVAL;
+	}
+	pm--;
+
+	bits = div16 | (pm << SPI_MODE_PM_SHIFT);
+	mask = SPI_MODE_DIV16 | SPI_MODE_PM_MASK;
+	mode = in_be32(&spi->mode);
+	if ((mode & mask) != bits) {
+		/* Must clear mode[EN] while changing speed. */
+		mode &= ~(mask | SPI_MODE_EN);
+		out_be32(&spi->mode, mode);
+		mode |= bits;
+		out_be32(&spi->mode, mode);
+		mode |= SPI_MODE_EN;
+		out_be32(&spi->mode, mode);
+	}
 
-	return __spi_set_speed(priv->spi, speed);
+	debug("requested speed %u, set speed to %lu/(%s4*%u) == %lu\n",
+	      speed, priv->clk_rate, div16 ? "16*" : "", pm + 1,
+	      clk/(4*(pm + 1)));
+
+	return 0;
 }
 
 static int mpc8xxx_spi_set_mode(struct udevice *dev, uint mode)