summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/dts/gdsys/mpc8308.dtsi7
-rw-r--r--cmd/mmc.c4
-rw-r--r--common/image-fit.c3
-rw-r--r--doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt22
-rw-r--r--drivers/gpio/Kconfig8
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/mpc83xx_spisel_boot.c148
-rw-r--r--drivers/gpio/mpc8xxx_gpio.c41
-rw-r--r--drivers/net/macb.c2
-rw-r--r--drivers/spi/mpc8xxx_spi.c141
10 files changed, 287 insertions, 90 deletions
diff --git a/arch/powerpc/dts/gdsys/mpc8308.dtsi b/arch/powerpc/dts/gdsys/mpc8308.dtsi
index 23e7403d91..1a319e2328 100644
--- a/arch/powerpc/dts/gdsys/mpc8308.dtsi
+++ b/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";
};
diff --git a/cmd/mmc.c b/cmd/mmc.c
index 6f3cb85cc0..1860a3f2e5 100644
--- a/cmd/mmc.c
+++ b/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;
}
diff --git a/common/image-fit.c b/common/image-fit.c
index 4435bc4f1d..6da69d25ff 100644
--- a/common/image-fit.c
+++ b/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
diff --git a/doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt b/doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
new file mode 100644
index 0000000000..52d8bb0a5c
--- /dev/null
+++ b/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>;
+ };
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f751a8b9ea..2081520f42 100644
--- a/drivers/gpio/Kconfig
+++ b/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
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9dd5a58389..7638259007 100644
--- a/drivers/gpio/Makefile
+++ b/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
diff --git a/drivers/gpio/mpc83xx_spisel_boot.c b/drivers/gpio/mpc83xx_spisel_boot.c
new file mode 100644
index 0000000000..c7b08404d9
--- /dev/null
+++ b/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),
+};
diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c
index c273c2c8a4..4b385b8b39 100644
--- a/drivers/gpio/mpc8xxx_gpio.c
+++ b/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;
}
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 631b53b093..bd588cab06 100644
--- a/drivers/net/macb.c
+++ b/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);
diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c
index 1c7bf10f91..1bde31ad34 100644
--- a/drivers/spi/mpc8xxx_spi.c
+++ b/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)