mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
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:
commit
150db4264d
10 changed files with 287 additions and 90 deletions
|
@ -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";
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
Normal file
22
doc/device-tree-bindings/gpio/fsl,mpc83xx-spisel-boot.txt
Normal 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>;
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
drivers/gpio/mpc83xx_spisel_boot.c
Normal file
148
drivers/gpio/mpc83xx_spisel_boot.c
Normal 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),
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue