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

- mpc8xxx GPIO, SPI bugfixes
- Add VxWorks to FIT images
- macb ethernet driver bugfix
This commit is contained in:
Tom Rini 2020-03-31 10:07:01 -04:00
commit 150db4264d
10 changed files with 287 additions and 90 deletions

View file

@ -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";
};

View file

@ -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;
}

View file

@ -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

View file

@ -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>;
};

View file

@ -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

View file

@ -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

View file

@ -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),
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
__spi_set_speed(priv->spi, 16666667);
/* set len to 8 bits */
setbits_be32(&spi->mode, (8 - 1) << SPI_MODE_LEN_SHIFT);
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;
return __spi_set_speed(priv->spi, speed);
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);
}
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)