From d895821f4c3c21f034780814cb73842b7219c4f2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 31 Jan 2015 14:47:34 +0800 Subject: gpio: at91: Fix getting address of private data Use dev_get_priv() rather than dev_get_platdata() to get correct address of private data. Signed-off-by: Axel Lin Acked-by: Simon Glass --- drivers/gpio/at91_gpio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 6129c02..22fbd63 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -451,7 +451,7 @@ struct at91_port_priv { /* set GPIO pin 'gpio' as an input */ static int at91_gpio_direction_input(struct udevice *dev, unsigned offset) { - struct at91_port_priv *port = dev_get_platdata(dev); + struct at91_port_priv *port = dev_get_priv(dev); at91_set_port_input(port->regs, offset, 0); @@ -462,7 +462,7 @@ static int at91_gpio_direction_input(struct udevice *dev, unsigned offset) static int at91_gpio_direction_output(struct udevice *dev, unsigned offset, int value) { - struct at91_port_priv *port = dev_get_platdata(dev); + struct at91_port_priv *port = dev_get_priv(dev); at91_set_port_output(port->regs, offset, value); @@ -472,7 +472,7 @@ static int at91_gpio_direction_output(struct udevice *dev, unsigned offset, /* read GPIO IN value of pin 'gpio' */ static int at91_gpio_get_value(struct udevice *dev, unsigned offset) { - struct at91_port_priv *port = dev_get_platdata(dev); + struct at91_port_priv *port = dev_get_priv(dev); return at91_get_port_value(port->regs, offset); } @@ -481,7 +481,7 @@ static int at91_gpio_get_value(struct udevice *dev, unsigned offset) static int at91_gpio_set_value(struct udevice *dev, unsigned offset, int value) { - struct at91_port_priv *port = dev_get_platdata(dev); + struct at91_port_priv *port = dev_get_priv(dev); at91_set_port_value(port->regs, offset, value); @@ -490,7 +490,7 @@ static int at91_gpio_set_value(struct udevice *dev, unsigned offset, static int at91_gpio_get_function(struct udevice *dev, unsigned offset) { - struct at91_port_priv *port = dev_get_platdata(dev); + struct at91_port_priv *port = dev_get_priv(dev); /* GPIOF_FUNC is not implemented yet */ if (at91_get_port_output(port->regs, offset)) -- cgit v1.1 From 26c0472cb07bc23e21fc8148565f7f2be746a8a0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 31 Jan 2015 22:23:38 +0800 Subject: gpio: omap: Pass correct argument to _get_gpio_direction() Pass bank rather than bank->base to _get_gpio_direction(). Signed-off-by: Axel Lin Acked-by: Simon Glass --- drivers/gpio/omap_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index f3a7ccb..19fc451 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -291,7 +291,7 @@ static int omap_gpio_get_function(struct udevice *dev, unsigned offset) struct gpio_bank *bank = dev_get_priv(dev); /* GPIOF_FUNC is not implemented yet */ - if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT) + if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT) return GPIOF_OUTPUT; else return GPIOF_INPUT; -- cgit v1.1 From a3e757a5d295329b504123f0995b35cf694c7613 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 27 Jan 2015 13:36:35 +0100 Subject: i2c: s3c24x0: reduce transmission status timeout If no device is connected to I2C bus, the i2c probe command can take a lot of time for probe each address. This commit reduces the busy timeout to 10ms for standard and high speed modes. This doesn't break the transmission an also allow for properly probe the devices. Signed-off-by: Przemyslaw Marczak Changes v3: - new commit, after split the next one Tested-by: Simon Glass --- drivers/i2c/s3c24x0_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 0dd1abc..b4ee33f 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -112,9 +112,9 @@ #define I2C_START_STOP 0x20 /* START / STOP */ #define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */ -#define I2C_TIMEOUT_MS 1000 /* 1 second */ +#define I2C_TIMEOUT_MS 10 /* 10 ms */ -#define HSI2C_TIMEOUT_US 100000 /* 100 ms, finer granularity */ +#define HSI2C_TIMEOUT_US 10000 /* 10 ms, finer granularity */ /* To support VCMA9 boards and other who dont define max_i2c_num */ -- cgit v1.1 From fad486ce51b7ae96f5004e50249c675d5ac20136 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 7 Feb 2015 11:51:47 -0700 Subject: powerpc: Add serial driver for driver model This uses the ns16550 driver but sets up the clock at run-time. It does not seem to be available in the device tree. Signed-off-by: Simon Glass --- drivers/serial/Makefile | 1 + drivers/serial/serial_ppc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 drivers/serial/serial_ppc.c (limited to 'drivers') diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 4cc00cd..63b0cbf 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -8,6 +8,7 @@ ifdef CONFIG_DM_SERIAL obj-y += serial-uclass.o obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o +obj-$(CONFIG_PPC) += serial_ppc.o else obj-y += serial.o obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o diff --git a/drivers/serial/serial_ppc.c b/drivers/serial/serial_ppc.c new file mode 100644 index 0000000..47141c6 --- /dev/null +++ b/drivers/serial/serial_ppc.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static const struct udevice_id ppc_serial_ids[] = { + { .compatible = "ns16550" }, + { } +}; + +static int ppc_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct ns16550_platdata *plat = dev_get_platdata(dev); + int ret; + + ret = ns16550_serial_ofdata_to_platdata(dev); + if (ret) + return ret; + plat->clock = get_serial_clock(); + + return 0; +} + +U_BOOT_DRIVER(serial_ns16550) = { + .name = "serial_ppc", + .id = UCLASS_SERIAL, + .of_match = ppc_serial_ids, + .ofdata_to_platdata = ppc_serial_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), + .priv_auto_alloc_size = sizeof(struct NS16550), + .probe = ns16550_serial_probe, + .ops = &ns16550_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit v1.1 From ca88b9b93916f66c6737527aa955d2c1b4758080 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 5 Feb 2015 21:41:32 -0700 Subject: dm: i2c: Add a dm_ prefix to driver model bus speed functions As with i2c_read() and i2c_write(), add a dm_ prefix to the driver model versions of these functions to avoid conflicts. Signed-off-by: Simon Glass Acked-by: Heiko Schocher --- drivers/i2c/i2c-uclass.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index eafa457..a6991bf 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -325,7 +325,7 @@ int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags, return ret; } -int i2c_set_bus_speed(struct udevice *bus, unsigned int speed) +int dm_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) { struct dm_i2c_ops *ops = i2c_get_ops(bus); struct dm_i2c_bus *i2c = bus->uclass_priv; @@ -346,12 +346,7 @@ int i2c_set_bus_speed(struct udevice *bus, unsigned int speed) return 0; } -/* - * i2c_get_bus_speed: - * - * Returns speed of selected I2C bus in Hz - */ -int i2c_get_bus_speed(struct udevice *bus) +int dm_i2c_get_bus_speed(struct udevice *bus) { struct dm_i2c_ops *ops = i2c_get_ops(bus); struct dm_i2c_bus *i2c = bus->uclass_priv; @@ -440,7 +435,7 @@ static int i2c_post_probe(struct udevice *dev) i2c->speed_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "clock-frequency", 100000); - return i2c_set_bus_speed(dev, i2c->speed_hz); + return dm_i2c_set_bus_speed(dev, i2c->speed_hz); } static int i2c_post_bind(struct udevice *dev) -- cgit v1.1 From fffff7268b6c30dc7058d3615021628d4f60fac5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 5 Feb 2015 21:41:33 -0700 Subject: dm: i2c: Make API accessible even without CONFIG_DM Make the driver model I2C API available always, even if driver model is not enabled. This allows for a 'soft' switch-over, where drivers can use the new structures in code which is compiled but not yet used. This makes migration easier in some cases. Fix up the existing drivers which define their own 'struct i2c_msg'. Signed-off-by: Simon Glass Acked-by: Heiko Schocher --- drivers/i2c/adi_i2c.c | 6 +++--- drivers/i2c/kona_i2c.c | 16 ++++++++-------- drivers/i2c/mv_i2c.c | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c index 20495b1..c58f14a 100644 --- a/drivers/i2c/adi_i2c.c +++ b/drivers/i2c/adi_i2c.c @@ -63,7 +63,7 @@ struct twi_regs { #endif /* All transfers are described by this data structure */ -struct i2c_msg { +struct adi_i2c_msg { u8 flags; #define I2C_M_COMBO 0x4 #define I2C_M_STOP 0x2 @@ -81,7 +81,7 @@ struct i2c_msg { * wait_for_completion - manage the actual i2c transfer * @msg: the i2c msg */ -static int wait_for_completion(struct twi_regs *twi, struct i2c_msg *msg) +static int wait_for_completion(struct twi_regs *twi, struct adi_i2c_msg *msg) { u16 int_stat, ctl; ulong timebase = get_timer(0); @@ -151,7 +151,7 @@ static int i2c_transfer(struct i2c_adapter *adap, uint8_t chip, uint addr, (addr >> 8), (addr >> 16), }; - struct i2c_msg msg = { + struct adi_i2c_msg msg = { .flags = flags | (len >= 0xff ? I2C_M_STOP : 0), .buf = buffer, .len = len, diff --git a/drivers/i2c/kona_i2c.c b/drivers/i2c/kona_i2c.c index 5eab338..9af496b 100644 --- a/drivers/i2c/kona_i2c.c +++ b/drivers/i2c/kona_i2c.c @@ -156,7 +156,7 @@ static struct bcm_kona_i2c_dev g_i2c_devs[CONFIG_SYS_MAX_I2C_BUS] = { #define I2C_M_RD 0x0001 /* read data */ #define I2C_M_NOSTART 0x4000 /* no restart between msgs */ -struct i2c_msg { +struct kona_i2c_msg { uint16_t addr; uint16_t flags; uint16_t len; @@ -297,7 +297,7 @@ static int bcm_kona_i2c_read_fifo_single(struct bcm_kona_i2c_dev *dev, /* Read any amount of data using the RX FIFO from the i2c bus */ static int bcm_kona_i2c_read_fifo(struct bcm_kona_i2c_dev *dev, - struct i2c_msg *msg) + struct kona_i2c_msg *msg) { unsigned int bytes_to_read = MAX_RX_FIFO_SIZE; unsigned int last_byte_nak = 0; @@ -392,7 +392,7 @@ static int bcm_kona_i2c_write_fifo_single(struct bcm_kona_i2c_dev *dev, /* Write any amount of data using TX FIFO to the i2c bus */ static int bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev, - struct i2c_msg *msg) + struct kona_i2c_msg *msg) { unsigned int bytes_to_write = MAX_TX_FIFO_SIZE; unsigned int bytes_written = 0; @@ -418,7 +418,7 @@ static int bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev, /* Send i2c address */ static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev, - struct i2c_msg *msg) + struct kona_i2c_msg *msg) { unsigned char addr; @@ -480,9 +480,9 @@ static void bcm_kona_i2c_config_timing(struct bcm_kona_i2c_dev *dev) /* Master transfer function */ static int bcm_kona_i2c_xfer(struct bcm_kona_i2c_dev *dev, - struct i2c_msg msgs[], int num) + struct kona_i2c_msg msgs[], int num) { - struct i2c_msg *pmsg; + struct kona_i2c_msg *pmsg; int rc = 0; int i; @@ -635,7 +635,7 @@ static int kona_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, int alen, uchar *buffer, int len) { /* msg[0] writes the addr, msg[1] reads the data */ - struct i2c_msg msg[2]; + struct kona_i2c_msg msg[2]; unsigned char msgbuf0[64]; struct bcm_kona_i2c_dev *dev = kona_get_dev(adap); @@ -663,7 +663,7 @@ static int kona_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, static int kona_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, int alen, uchar *buffer, int len) { - struct i2c_msg msg[1]; + struct kona_i2c_msg msg[1]; unsigned char msgbuf0[64]; unsigned int i; struct bcm_kona_i2c_dev *dev = kona_get_dev(adap); diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c index dac3463..e65cce0 100644 --- a/drivers/i2c/mv_i2c.c +++ b/drivers/i2c/mv_i2c.c @@ -31,7 +31,7 @@ #endif /* All transfers are described by this data structure */ -struct i2c_msg { +struct mv_i2c_msg { u8 condition; u8 acknack; u8 direction; @@ -157,7 +157,7 @@ static int i2c_isr_set_cleared(unsigned long set_mask, * -5: illegal parameters * -6: bus is busy and couldn't be aquired */ -int i2c_transfer(struct i2c_msg *msg) +int i2c_transfer(struct mv_i2c_msg *msg) { int ret; @@ -286,7 +286,7 @@ void i2c_init(int speed, int slaveaddr) */ int i2c_probe(uchar chip) { - struct i2c_msg msg; + struct mv_i2c_msg msg; i2c_reset(); @@ -322,7 +322,7 @@ int i2c_probe(uchar chip) */ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) { - struct i2c_msg msg; + struct mv_i2c_msg msg; u8 addr_bytes[3]; /* lowest...highest byte of data address */ PRINTD(("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " @@ -410,7 +410,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) */ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) { - struct i2c_msg msg; + struct mv_i2c_msg msg; u8 addr_bytes[3]; /* lowest...highest byte of data address */ PRINTD(("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, " -- cgit v1.1 From 2a4eeadd56e0760b33c7ebef383c105479a93cac Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 5 Feb 2015 21:41:34 -0700 Subject: dm: Add Kconfig for driver/demo Add a suitable Kconfig for this directory. Signed-off-by: Simon Glass Reviewed-by: Masahiro Yamada --- drivers/Kconfig | 2 ++ drivers/demo/Kconfig | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 drivers/demo/Kconfig (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 128736d..021293e 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -2,6 +2,8 @@ menu "Device Drivers" source "drivers/core/Kconfig" +source "drivers/demo/Kconfig" + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/drivers/demo/Kconfig b/drivers/demo/Kconfig new file mode 100644 index 0000000..7a8ce18 --- /dev/null +++ b/drivers/demo/Kconfig @@ -0,0 +1,26 @@ +config DM_DEMO + bool "Enable demo uclass support" + depends on DM + help + This uclass allows you to play around with driver model. It provides + an interface to a couple of demo devices. You can access it using + the 'demo' command or by calling the uclass functions from your + own code. + +config DM_DEMO_SIMPLE + bool "Enable simple demo device for driver model" + depends on DM_DEMO + help + This device allows you to play around with driver model. It prints + a message when the 'demo hello' command is executed which targets + this device. It can be used to help understand how driver model + works. + +config DM_DEMO_SHAPE + bool "Enable shape demo device for driver model" + depends on DM_DEMO + help + This device allows you to play around with driver model. It prints + a shape when the 'demo hello' command is executed which targets + this device. It can be used to help understand how driver model + works. -- cgit v1.1 From f94a1bed07e2af1c46ddcf2046cddd979ebfd994 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 5 Feb 2015 21:41:35 -0700 Subject: dm: Expand and complete Kconfig in drivers/ Expand the help messages for each driver. Add missing Kconfig for I2C, SPI flash and thermal. Signed-off-by: Simon Glass Reviewed-by: Masahiro Yamada --- drivers/Kconfig | 2 ++ drivers/core/Kconfig | 6 ++++-- drivers/gpio/Kconfig | 7 +++++-- drivers/i2c/Kconfig | 12 ++++++++++-- drivers/misc/Kconfig | 9 +++++++++ drivers/mtd/Kconfig | 2 ++ drivers/mtd/spi/Kconfig | 14 ++++++++++++++ drivers/serial/Kconfig | 6 ++++-- drivers/spi/Kconfig | 10 ++++++++-- drivers/thermal/Kconfig | 7 +++++++ 10 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 drivers/mtd/spi/Kconfig create mode 100644 drivers/thermal/Kconfig (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 021293e..dcce532 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -50,4 +50,6 @@ source "drivers/dma/Kconfig" source "drivers/crypto/Kconfig" +source "drivers/thermal/Kconfig" + endmenu diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index d2799dc..dc32385 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -2,5 +2,7 @@ config DM bool "Enable Driver Model" depends on !SPL_BUILD help - This config option enables Driver Model. - To use legacy drivers, say N. + This config option enables Driver Model. This brings in the core + support, including scanning of platform data on start-up. If + CONFIG_OF_CONTROL is enabled, the device tree will be scanned also + when available. diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d21302f..b609e73 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -2,5 +2,8 @@ config DM_GPIO bool "Enable Driver Model for GPIO drivers" depends on DM help - If you want to use driver model for GPIO drivers, say Y. - To use legacy GPIO drivers, say N. + Enable driver model for GPIO access. The standard GPIO + interface (gpio_get_value(), etc.) is then implemented by + the GPIO uclass. Drivers provide methods to query the + particular GPIOs that they provide. The uclass interface + is defined in include/asm-generic/gpio.h. diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 202ea5d..2cc776c 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -2,8 +2,16 @@ config DM_I2C bool "Enable Driver Model for I2C drivers" depends on DM help - If you want to use driver model for I2C drivers, say Y. - To use legacy I2C drivers, say N. + Enable driver model for I2C. This SPI flash interface + (spi_flash_probe(), spi_flash_write(), etc.) is then + implemented by the SPI flash uclass. There is one standard + SPI flash driver which knows how to probe most chips + supported by U-Boot. The uclass interface is defined in + include/spi_flash.h, but is currently fully compatible + with the old interface to avoid confusion and duplication + during the transition parent. SPI and SPI flash must be + enabled together (it is not possible to use driver model + for one and not the other). config SYS_I2C_UNIPHIER bool "UniPhier I2C driver" diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e69de29..813d1c2 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -0,0 +1,9 @@ +config DM_CROS_EC + bool "Enable Driver Model for Chrome OS EC" + depends on DM + help + Enable driver model for the Chrome OS EC interface. This + allows the cros_ec SPI driver to operate with CONFIG_DM_SPI + but otherwise makes few changes. Since cros_ec also supports + I2C and LPC (which don't support driver model yet), a full + conversion is not yet possible. diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 415ab4e..59278d1 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1 +1,3 @@ source "drivers/mtd/nand/Kconfig" + +source "drivers/mtd/spi/Kconfig" diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig new file mode 100644 index 0000000..2dc46b4 --- /dev/null +++ b/drivers/mtd/spi/Kconfig @@ -0,0 +1,14 @@ +config DM_SPI_FLASH + bool "Enable Driver Model for SPI flash" + depends on DM && SPI + help + Enable driver model for SPI flash. This SPI flash interface + (spi_flash_probe(), spi_flash_write(), etc.) is then + implemented by the SPI flash uclass. There is one standard + SPI flash driver which knows how to probe most chips + supported by U-Boot. The uclass interface is defined in + include/spi_flash.h, but is currently fully compatible + with the old interface to avoid confusion and duplication + during the transition parent. SPI and SPI flash must be + enabled together (it is not possible to use driver model + for one and not the other). diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index a0b6e02..c94353b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -2,8 +2,10 @@ config DM_SERIAL bool "Enable Driver Model for serial drivers" depends on DM help - If you want to use driver model for serial drivers, say Y. - To use legacy serial drivers, say N. + Enable driver model for serial. This replaces + drivers/serial/serial.c with the serial uclass, which + implements serial_putc() etc. The uclass interface is + defined in include/serial.h. config UNIPHIER_SERIAL bool "UniPhier on-chip UART support" diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index e1678e6..7ae2727 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -2,5 +2,11 @@ config DM_SPI bool "Enable Driver Model for SPI drivers" depends on DM help - If you want to use driver model for SPI drivers, say Y. - To use legacy SPI drivers, say N. + Enable driver model for SPI. The SPI slave interface + (spi_setup_slave(), spi_xfer(), etc.) is then implemented by + the SPI uclass. Drivers provide methods to access the SPI + buses that they control. The uclass interface is defined in + include/spi.h. The existing spi_slave structure is attached + as 'parent data' to every slave on each bus. Slaves + typically use driver-private data instead of extending the + spi_slave structure. diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig new file mode 100644 index 0000000..3c6b36d --- /dev/null +++ b/drivers/thermal/Kconfig @@ -0,0 +1,7 @@ +config DM_THERMAL + bool "Driver support for thermal devices" + help + Enable support for temporary-sensing devices. Some SoCs have on-chip + temperature sensors to permit warnings, speed throttling or even + automatic power-off when the temperature gets too high or low. Other + devices may be discrete but connected on a suitable bus. -- cgit v1.1 From 91a91ff804d50d7a4b7560d10fa6863fc4c04307 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 5 Feb 2015 21:41:36 -0700 Subject: dm: Add Kconfig options for driver model SPL support The SPL support cannot be enabled yet, but we can add the Kconfig options in preparation for this. Signed-off-by: Simon Glass --- drivers/core/Kconfig | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index dc32385..f0d6110 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -6,3 +6,47 @@ config DM support, including scanning of platform data on start-up. If CONFIG_OF_CONTROL is enabled, the device tree will be scanned also when available. + +config SPL_DM + bool "Enable Driver Model for SPL" + depends on DM && SPL + help + Enable driver model in SPL. You will need to provide a + suitable malloc() implementation. If you are not using the + full malloc() enabled by CONFIG_SYS_SPL_MALLOC_START, + consider using CONFIG_SYS_MALLOC_SIMPLE. In that case you + must provide CONFIG_SYS_MALLOC_F_LEN to set the size. + In most cases driver model will only allocate a few uclasses + and devices in SPL, so 1KB should be enable. See + CONFIG_SYS_MALLOC_F_LEN for more details on how to enable it. + +config DM_WARN + bool "Enable warnings in driver model" + help + The dm_warn() function can use up quite a bit of space for its + strings. By default this is disabled for SPL builds to save space. + This will cause dm_warn() to be compiled out - it will do nothing + when called. + depends on DM + default y if !SPL_BUILD + default n if SPL_BUILD + +config DM_DEVICE_REMOVE + bool "Support device removal" + help + We can save some code space by dropping support for removing a + device. This is not normally required in SPL, so by default this + option is disabled for SPL. + depends on DM + default y if !SPL_BUILD + default n if SPL_BUILD + +config DM_STDIO + bool "Support stdio registration" + help + Normally serial drivers register with stdio so that they can be used + as normal output devices. In SPL we don't normally use stdio, so + we can omit this feature. + depends on DM + default y if !SPL_BUILD + default n if SPL_BUILD -- cgit v1.1 From 59088e4a762d5ea2791b6ecd39c81765ba4c4546 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 12 Feb 2015 13:48:04 +0900 Subject: dm: sh: serial: Add support driver model This adds driver model support with this driver. This was tested by Koelsch board and Gose board. Signed-off-by: Nobuhiro Iwamatsu Acked-by: Simon Glass --- drivers/serial/serial_sh.c | 321 +++++++++++++++++++++++++++++++-------------- drivers/serial/serial_sh.h | 30 +++-- 2 files changed, 238 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 7c1f271..3641c9f 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -1,78 +1,21 @@ /* * SuperH SCIF device driver. * Copyright (C) 2013 Renesas Electronics Corporation - * Copyright (C) 2007,2008,2010 Nobuhiro Iwamatsu + * Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu * Copyright (C) 2002 - 2008 Paul Mundt * * SPDX-License-Identifier: GPL-2.0+ */ #include +#include +#include #include #include -#include "serial_sh.h" #include #include - -#if defined(CONFIG_CONS_SCIF0) -# define SCIF_BASE SCIF0_BASE -#elif defined(CONFIG_CONS_SCIF1) -# define SCIF_BASE SCIF1_BASE -#elif defined(CONFIG_CONS_SCIF2) -# define SCIF_BASE SCIF2_BASE -#elif defined(CONFIG_CONS_SCIF3) -# define SCIF_BASE SCIF3_BASE -#elif defined(CONFIG_CONS_SCIF4) -# define SCIF_BASE SCIF4_BASE -#elif defined(CONFIG_CONS_SCIF5) -# define SCIF_BASE SCIF5_BASE -#elif defined(CONFIG_CONS_SCIF6) -# define SCIF_BASE SCIF6_BASE -#elif defined(CONFIG_CONS_SCIF7) -# define SCIF_BASE SCIF7_BASE -#else -# error "Default SCIF doesn't set....." -#endif - -#if defined(CONFIG_SCIF_A) - #define SCIF_BASE_PORT PORT_SCIFA -#else - #define SCIF_BASE_PORT PORT_SCIF -#endif - -static struct uart_port sh_sci = { - .membase = (unsigned char*)SCIF_BASE, - .mapbase = SCIF_BASE, - .type = SCIF_BASE_PORT, -}; - -static void sh_serial_setbrg(void) -{ - DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_SCIF_USE_EXT_CLK - unsigned short dl = DL_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ); - sci_out(&sh_sci, DL, dl); - /* Need wait: Clock * 1/dl $B!_(B 1/16 */ - udelay((1000000 * dl * 16 / CONFIG_SYS_CLK_FREQ) * 1000 + 1); -#else - sci_out(&sh_sci, SCBRR, - SCBRR_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ)); -#endif -} - -static int sh_serial_init(void) -{ - sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); - sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); - sci_out(&sh_sci, SCSMR, 0); - sci_out(&sh_sci, SCSMR, 0); - sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST); - sci_in(&sh_sci, SCFCR); - sci_out(&sh_sci, SCFCR, 0); - - serial_setbrg(); - return 0; -} +#include +#include "serial_sh.h" #if defined(CONFIG_CPU_SH7760) || \ defined(CONFIG_CPU_SH7780) || \ @@ -86,7 +29,7 @@ static int scif_rxfill(struct uart_port *port) static int scif_rxfill(struct uart_port *port) { if ((port->mapbase == 0xffe00000) || - (port->mapbase == 0xffe08000)) { + (port->mapbase == 0xffe08000)) { /* SCIF0/1*/ return sci_in(port, SCRFDR) & 0xff; } else { @@ -109,80 +52,253 @@ static int scif_rxfill(struct uart_port *port) } #endif -static int serial_rx_fifo_level(void) +static void sh_serial_init_generic(struct uart_port *port) { - return scif_rxfill(&sh_sci); + sci_out(port, SCSCR , SCSCR_INIT(port)); + sci_out(port, SCSCR , SCSCR_INIT(port)); + sci_out(port, SCSMR, 0); + sci_out(port, SCSMR, 0); + sci_out(port, SCFCR, SCFCR_RFRST|SCFCR_TFRST); + sci_in(port, SCFCR); + sci_out(port, SCFCR, 0); } -static void handle_error(void) +static void +sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) { - sci_in(&sh_sci, SCxSR); - sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); - sci_in(&sh_sci, SCLSR); - sci_out(&sh_sci, SCLSR, 0x00); + if (port->clk_mode == EXT_CLK) { + unsigned short dl = DL_VALUE(baudrate, clk); + sci_out(port, DL, dl); + /* Need wait: Clock * 1/dl $B!_(B 1/16 */ + udelay((1000000 * dl * 16 / clk) * 1000 + 1); + } else { + sci_out(port, SCBRR, SCBRR_VALUE(baudrate, clk)); + } } -static void serial_raw_putc(const char c) +static void handle_error(struct uart_port *port) { - while (1) { - /* Tx fifo is empty */ - if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) - break; - } + sci_in(port, SCxSR); + sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + sci_in(port, SCLSR); + sci_out(port, SCLSR, 0x00); +} + +static int serial_raw_putc(struct uart_port *port, const char c) +{ + /* Tx fifo is empty */ + if (!(sci_in(port, SCxSR) & SCxSR_TEND(port))) + return -EAGAIN; - sci_out(&sh_sci, SCxTDR, c); - sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); + sci_out(port, SCxTDR, c); + sci_out(port, SCxSR, sci_in(port, SCxSR) & ~SCxSR_TEND(port)); + + return 0; } -static void sh_serial_putc(const char c) +static int serial_rx_fifo_level(struct uart_port *port) { - if (c == '\n') - serial_raw_putc('\r'); - serial_raw_putc(c); + return scif_rxfill(port); } -static int sh_serial_tstc(void) +static int sh_serial_tstc_generic(struct uart_port *port) { - if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) { - handle_error(); + if (sci_in(port, SCxSR) & SCIF_ERRORS) { + handle_error(port); return 0; } - return serial_rx_fifo_level() ? 1 : 0; + return serial_rx_fifo_level(port) ? 1 : 0; } - -static int serial_getc_check(void) +static int serial_getc_check(struct uart_port *port) { unsigned short status; - status = sci_in(&sh_sci, SCxSR); + status = sci_in(port, SCxSR); if (status & SCIF_ERRORS) - handle_error(); - if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) - handle_error(); - return status & (SCIF_DR | SCxSR_RDxF(&sh_sci)); + handle_error(port); + if (sci_in(port, SCLSR) & SCxSR_ORER(port)) + handle_error(port); + return status & (SCIF_DR | SCxSR_RDxF(port)); } -static int sh_serial_getc(void) +static int sh_serial_getc_generic(struct uart_port *port) { unsigned short status; char ch; - while (!serial_getc_check()) - ; + if (!serial_getc_check(port)) + return -EAGAIN; - ch = sci_in(&sh_sci, SCxRDR); - status = sci_in(&sh_sci, SCxSR); + ch = sci_in(port, SCxRDR); + status = sci_in(port, SCxSR); - sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); + sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); if (status & SCIF_ERRORS) - handle_error(); + handle_error(port); + + if (sci_in(port, SCLSR) & SCxSR_ORER(port)) + handle_error(port); + + return ch; +} + +#ifdef CONFIG_DM_SERIAL + +static int sh_serial_pending(struct udevice *dev, bool input) +{ + struct uart_port *priv = dev_get_priv(dev); + + return sh_serial_tstc_generic(priv); +} + +static int sh_serial_putc(struct udevice *dev, const char ch) +{ + struct uart_port *priv = dev_get_priv(dev); + + return serial_raw_putc(priv, ch); +} + +static int sh_serial_getc(struct udevice *dev) +{ + struct uart_port *priv = dev_get_priv(dev); + + return sh_serial_getc_generic(priv); +} + +static int sh_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct sh_serial_platdata *plat = dev_get_platdata(dev); + struct uart_port *priv = dev_get_priv(dev); + + sh_serial_setbrg_generic(priv, plat->clk, baudrate); + + return 0; +} + +static int sh_serial_probe(struct udevice *dev) +{ + struct sh_serial_platdata *plat = dev_get_platdata(dev); + struct uart_port *priv = dev_get_priv(dev); + + priv->membase = (unsigned char *)plat->base; + priv->mapbase = plat->base; + priv->type = plat->type; + priv->clk_mode = plat->clk_mode; + + sh_serial_init_generic(priv); + + return 0; +} + +static const struct dm_serial_ops sh_serial_ops = { + .putc = sh_serial_putc, + .pending = sh_serial_pending, + .getc = sh_serial_getc, + .setbrg = sh_serial_setbrg, +}; + +U_BOOT_DRIVER(serial_sh) = { + .name = "serial_sh", + .id = UCLASS_SERIAL, + .probe = sh_serial_probe, + .ops = &sh_serial_ops, + .flags = DM_FLAG_PRE_RELOC, + .priv_auto_alloc_size = sizeof(struct uart_port), +}; + +#else /* CONFIG_DM_SERIAL */ + +#if defined(CONFIG_CONS_SCIF0) +# define SCIF_BASE SCIF0_BASE +#elif defined(CONFIG_CONS_SCIF1) +# define SCIF_BASE SCIF1_BASE +#elif defined(CONFIG_CONS_SCIF2) +# define SCIF_BASE SCIF2_BASE +#elif defined(CONFIG_CONS_SCIF3) +# define SCIF_BASE SCIF3_BASE +#elif defined(CONFIG_CONS_SCIF4) +# define SCIF_BASE SCIF4_BASE +#elif defined(CONFIG_CONS_SCIF5) +# define SCIF_BASE SCIF5_BASE +#elif defined(CONFIG_CONS_SCIF6) +# define SCIF_BASE SCIF6_BASE +#elif defined(CONFIG_CONS_SCIF7) +# define SCIF_BASE SCIF7_BASE +#else +# error "Default SCIF doesn't set....." +#endif + +#if defined(CONFIG_SCIF_A) + #define SCIF_BASE_PORT PORT_SCIFA +#else + #define SCIF_BASE_PORT PORT_SCIF +#endif + +static struct uart_port sh_sci = { + .membase = (unsigned char *)SCIF_BASE, + .mapbase = SCIF_BASE, + .type = SCIF_BASE_PORT, +#ifdef CONFIG_SCIF_USE_EXT_CLK + .clk_mode = EXT_CLK, +#endif +}; + +static void sh_serial_setbrg(void) +{ + DECLARE_GLOBAL_DATA_PTR; + struct uart_port *port = &sh_sci; + + sh_serial_setbrg_generic(port, CONFIG_SH_SCIF_CLK_FREQ, gd->baudrate); +} + +static int sh_serial_init(void) +{ + struct uart_port *port = &sh_sci; + + sh_serial_init_generic(port); + serial_setbrg(); + + return 0; +} + +static void sh_serial_putc(const char c) +{ + struct uart_port *port = &sh_sci; + + if (c == '\n') { + while (1) { + if (serial_raw_putc(port, '\r') != -EAGAIN) + break; + } + } + while (1) { + if (serial_raw_putc(port, c) != -EAGAIN) + break; + } +} + +static int sh_serial_tstc(void) +{ + struct uart_port *port = &sh_sci; + + return sh_serial_tstc_generic(port); +} + +static int sh_serial_getc(void) +{ + struct uart_port *port = &sh_sci; + int ch; + + while (1) { + ch = sh_serial_getc_generic(port); + if (ch != -EAGAIN) + break; + } - if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) - handle_error(); return ch; } @@ -206,3 +322,4 @@ __weak struct serial_device *default_serial_console(void) { return &sh_serial_drv; } +#endif /* CONFIG_DM_SERIAL */ diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h index ef88c8f..528aa73 100644 --- a/drivers/serial/serial_sh.h +++ b/drivers/serial/serial_sh.h @@ -2,18 +2,16 @@ * Copy and modify from linux/drivers/serial/sh-sci.h */ +#include + struct uart_port { unsigned long iobase; /* in/out[bwl] */ unsigned char *membase; /* read/write[bwl] */ unsigned long mapbase; /* for ioremap */ - unsigned int type; /* port type */ + enum sh_serial_type type; /* port type */ + enum sh_clk_mode clk_mode; /* clock mode */ }; -#define PORT_SCI 52 -#define PORT_SCIF 53 -#define PORT_SCIFA 83 -#define PORT_SCIFB 93 - #if defined(CONFIG_H83007) || defined(CONFIG_H83068) #include #endif @@ -526,6 +524,7 @@ SCIF_FNS(SCFDR, 0x1c, 16) SCIF_FNS(SCxTDR, 0x20, 8) SCIF_FNS(SCxRDR, 0x24, 8) SCIF_FNS(SCLSR, 0x00, 0) +SCIF_FNS(DL, 0x00, 0) /* dummy */ #elif defined(CONFIG_ARCH_SH7372) || \ defined(CONFIG_R8A7740) SCIF_FNS(SCSMR, 0x00, 16) @@ -541,6 +540,7 @@ SCIF_FNS(SCRFDR, 0x3c, 16) SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8) SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8) SCIF_FNS(SCLSR, 0x00, 0) +SCIF_FNS(DL, 0x00, 0) /* dummy */ #elif defined(CONFIG_CPU_SH7723) ||\ defined(CONFIG_CPU_SH7724) SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) @@ -555,6 +555,7 @@ SCIF_FNS(SCFER, 0x10, 16) SCIF_FNS(SCFCR, 0x18, 16) SCIF_FNS(SCFDR, 0x1c, 16) SCIF_FNS(SCLSR, 0x24, 16) +SCIF_FNS(DL, 0x00, 0) /* dummy */ #else /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/ /* name off sz off sz off sz off sz off sz*/ @@ -583,18 +584,21 @@ SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) SCIF_FNS(SCLSR, 0, 0, 0x28, 16) #else + SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) #if defined(CONFIG_CPU_SH7722) SCIF_FNS(SCSPTR, 0, 0, 0, 0) #else SCIF_FNS(SCSPTR, 0, 0, 0x20, 16) #endif +SCIF_FNS(SCLSR, 0, 0, 0x24, 16) +#endif #if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) SCIF_FNS(DL, 0, 0, 0x30, 16) SCIF_FNS(CKS, 0, 0, 0x34, 16) -#endif -SCIF_FNS(SCLSR, 0, 0, 0x24, 16) +#else +SCIF_FNS(DL, 0, 0, 0x0, 0) /* dummy */ #endif #endif #define sci_in(port, reg) sci_##reg##_in(port) @@ -725,14 +729,14 @@ static inline int sci_rxd_in(struct uart_port *port) #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) #elif defined(CONFIG_CPU_SH7723) ||\ defined(CONFIG_CPU_SH7724) -static inline int scbrr_calc(struct uart_port port, int bps, int clk) +static inline int scbrr_calc(struct uart_port *port, int bps, int clk) { - if (port.type == PORT_SCIF) + if (port->type == PORT_SCIF) return (clk+16*bps)/(32*bps)-1; else return ((clk*2)+16*bps)/(16*bps)-1; } -#define SCBRR_VALUE(bps, clk) scbrr_calc(sh_sci, bps, clk) +#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk) #elif defined(__H8300H__) || defined(__H8300S__) #define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1) #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ @@ -742,3 +746,7 @@ static inline int scbrr_calc(struct uart_port port, int bps, int clk) #else /* Generic SH */ #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) #endif + +#ifndef DL_VALUE +#define DL_VALUE(bps, clk) 0 +#endif -- cgit v1.1 From c9cac3f8413c1f67d1e1b7a1770e584584107cd2 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 10 Feb 2015 14:46:32 +0800 Subject: dm: introduce dev_get_addr interface Abstracting dev_get_addr can improve drivers that want to get device's address. Signed-off-by: Peng Fan Acked-by: Igor Grinberg Acked-by: Simon Glass --- drivers/core/device.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/core/device.c b/drivers/core/device.c index b73d3b8..73c3e07 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -449,3 +449,15 @@ enum uclass_id device_get_uclass_id(struct udevice *dev) { return dev->uclass->uc_drv->id; } + +#ifdef CONFIG_OF_CONTROL +fdt_addr_t dev_get_addr(struct udevice *dev) +{ + return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); +} +#else +fdt_addr_t dev_get_addr(struct udevice *dev) +{ + return FDT_ADDR_T_NONE; +} +#endif -- cgit v1.1 From 637a7693185d00c392df8a9886cb17f462e9a51b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 10 Feb 2015 14:46:33 +0800 Subject: dm:gpio:mxc add a bank_index entry in platdata Add a new entry in platdata structure and intialize bank_index in mxc_plat array. This new entry can avoid using `plat - mxc_plat` by using `plat->bank_index`. Signed-off-by: Peng Fan Acked-by: Igor Grinberg Acked-by: Simon Glass --- drivers/gpio/mxc_gpio.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c index 8bb9e39..c52dd19 100644 --- a/drivers/gpio/mxc_gpio.c +++ b/drivers/gpio/mxc_gpio.c @@ -23,6 +23,7 @@ enum mxc_gpio_direction { #define GPIO_PER_BANK 32 struct mxc_gpio_plat { + int bank_index; struct gpio_regs *regs; }; @@ -259,19 +260,19 @@ static const struct dm_gpio_ops gpio_mxc_ops = { }; static const struct mxc_gpio_plat mxc_plat[] = { - { (struct gpio_regs *)GPIO1_BASE_ADDR }, - { (struct gpio_regs *)GPIO2_BASE_ADDR }, - { (struct gpio_regs *)GPIO3_BASE_ADDR }, + { 0, (struct gpio_regs *)GPIO1_BASE_ADDR }, + { 1, (struct gpio_regs *)GPIO2_BASE_ADDR }, + { 2, (struct gpio_regs *)GPIO3_BASE_ADDR }, #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ defined(CONFIG_MX53) || defined(CONFIG_MX6) - { (struct gpio_regs *)GPIO4_BASE_ADDR }, + { 3, (struct gpio_regs *)GPIO4_BASE_ADDR }, #endif #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) - { (struct gpio_regs *)GPIO5_BASE_ADDR }, - { (struct gpio_regs *)GPIO6_BASE_ADDR }, + { 4, (struct gpio_regs *)GPIO5_BASE_ADDR }, + { 5, (struct gpio_regs *)GPIO6_BASE_ADDR }, #endif #if defined(CONFIG_MX53) || defined(CONFIG_MX6) - { (struct gpio_regs *)GPIO7_BASE_ADDR }, + { 6, (struct gpio_regs *)GPIO7_BASE_ADDR }, #endif }; @@ -283,7 +284,7 @@ static int mxc_gpio_probe(struct udevice *dev) int banknum; char name[18], *str; - banknum = plat - mxc_plat; + banknum = plat->bank_index; sprintf(name, "GPIO%d_", banknum + 1); str = strdup(name); if (!str) -- cgit v1.1 From 99c0ae16d8b2ebfb7381ba77d4e37e7bda734402 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 10 Feb 2015 14:46:34 +0800 Subject: dm:gpio:mxc add DT support This patch add DT support for mxc gpio driver. There are one place using CONFIG_OF_CONTROL macro. 1. The U_BOOT_DEVICES and mxc_plat array are complied out. To DT, platdata is alloced using calloc, so there is no need to use mxc_plat. The following situations are tested, and all work fine: 1. with DM, without DT 2. with DM and DT 3. without DM Since device tree has not been upstreamed, if want to test this patch. The followings need to be done. + pieces of code does not gpio_request when using gpio_direction_xxx and etc, need to request gpio. + move the gpio settings from board_early_init_f to board_init + define CONFIG_DM ,CONFIG_DM_GPIO and CONFIG_OF_CONTROL + Add device tree file and do related configuration in `make ARCH=arm menuconfig` These will be done in future patches by step. Signed-off-by: Peng Fan Acked-by: Igor Grinberg Acked-by: Simon Glass --- drivers/gpio/mxc_gpio.c | 81 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c index c52dd19..815407b 100644 --- a/drivers/gpio/mxc_gpio.c +++ b/drivers/gpio/mxc_gpio.c @@ -151,6 +151,9 @@ int gpio_direction_output(unsigned gpio, int value) #endif #ifdef CONFIG_DM_GPIO +#include +DECLARE_GLOBAL_DATA_PTR; + static int mxc_gpio_is_output(struct gpio_regs *regs, int offset) { u32 val; @@ -259,23 +262,6 @@ static const struct dm_gpio_ops gpio_mxc_ops = { .get_function = mxc_gpio_get_function, }; -static const struct mxc_gpio_plat mxc_plat[] = { - { 0, (struct gpio_regs *)GPIO1_BASE_ADDR }, - { 1, (struct gpio_regs *)GPIO2_BASE_ADDR }, - { 2, (struct gpio_regs *)GPIO3_BASE_ADDR }, -#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ - defined(CONFIG_MX53) || defined(CONFIG_MX6) - { 3, (struct gpio_regs *)GPIO4_BASE_ADDR }, -#endif -#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) - { 4, (struct gpio_regs *)GPIO5_BASE_ADDR }, - { 5, (struct gpio_regs *)GPIO6_BASE_ADDR }, -#endif -#if defined(CONFIG_MX53) || defined(CONFIG_MX6) - { 6, (struct gpio_regs *)GPIO7_BASE_ADDR }, -#endif -}; - static int mxc_gpio_probe(struct udevice *dev) { struct mxc_bank_info *bank = dev_get_priv(dev); @@ -296,12 +282,72 @@ static int mxc_gpio_probe(struct udevice *dev) return 0; } +static int mxc_gpio_bind(struct udevice *dev) +{ + struct mxc_gpio_plat *plat = dev->platdata; + fdt_addr_t addr; + + /* + * If platdata already exsits, directly return. + * Actually only when DT is not supported, platdata + * is statically initialized in U_BOOT_DEVICES.Here + * will return. + */ + if (plat) + return 0; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + /* + * TODO: + * When every board is converted to driver model and DT is supported, + * this can be done by auto-alloc feature, but not using calloc + * to alloc memory for platdata. + */ + plat = calloc(1, sizeof(*plat)); + if (!plat) + return -ENOMEM; + + plat->regs = (struct gpio_regs *)addr; + plat->bank_index = dev->req_seq; + dev->platdata = plat; + + return 0; +} + +static const struct udevice_id mxc_gpio_ids[] = { + { .compatible = "fsl,imx35-gpio" }, + { } +}; + U_BOOT_DRIVER(gpio_mxc) = { .name = "gpio_mxc", .id = UCLASS_GPIO, .ops = &gpio_mxc_ops, .probe = mxc_gpio_probe, .priv_auto_alloc_size = sizeof(struct mxc_bank_info), + .of_match = mxc_gpio_ids, + .bind = mxc_gpio_bind, +}; + +#ifndef CONFIG_OF_CONTROL +static const struct mxc_gpio_plat mxc_plat[] = { + { 0, (struct gpio_regs *)GPIO1_BASE_ADDR }, + { 1, (struct gpio_regs *)GPIO2_BASE_ADDR }, + { 2, (struct gpio_regs *)GPIO3_BASE_ADDR }, +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ + defined(CONFIG_MX53) || defined(CONFIG_MX6) + { 3, (struct gpio_regs *)GPIO4_BASE_ADDR }, +#endif +#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) + { 4, (struct gpio_regs *)GPIO5_BASE_ADDR }, + { 5, (struct gpio_regs *)GPIO6_BASE_ADDR }, +#endif +#if defined(CONFIG_MX53) || defined(CONFIG_MX6) + { 6, (struct gpio_regs *)GPIO7_BASE_ADDR }, +#endif }; U_BOOT_DEVICES(mxc_gpios) = { @@ -321,3 +367,4 @@ U_BOOT_DEVICES(mxc_gpios) = { #endif }; #endif +#endif -- cgit v1.1 From 484fdf5ba058b07be5ca82763aa2b72063540ef3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 2 Feb 2015 16:31:59 +0100 Subject: dm: Add support for all targets which requires MANUAL_RELOC Targets with CONFIG_NEEDS_MANUAL_RELOC do not use REL/RELA relocation (mostly only GOT) where functions aray are not updated. This patch is fixing function pointers for DM core and serial-uclass to ensure that relocated functions are called. Signed-off-by: Michal Simek Acked-by: Simon Glass --- drivers/core/root.c | 64 ++++++++++++++++++++++++++++++++++++++++++ drivers/serial/serial-uclass.c | 16 +++++++++++ 2 files changed, 80 insertions(+) (limited to 'drivers') diff --git a/drivers/core/root.c b/drivers/core/root.c index 73e3c72..9b5c6bb 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -37,6 +37,65 @@ struct udevice *dm_root(void) return gd->dm_root; } +#if defined(CONFIG_NEEDS_MANUAL_RELOC) +void fix_drivers(void) +{ + struct driver *drv = + ll_entry_start(struct driver, driver); + const int n_ents = ll_entry_count(struct driver, driver); + struct driver *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (entry->of_match) + entry->of_match = (const struct udevice_id *) + ((u32)entry->of_match + gd->reloc_off); + if (entry->bind) + entry->bind += gd->reloc_off; + if (entry->probe) + entry->probe += gd->reloc_off; + if (entry->remove) + entry->remove += gd->reloc_off; + if (entry->unbind) + entry->unbind += gd->reloc_off; + if (entry->ofdata_to_platdata) + entry->ofdata_to_platdata += gd->reloc_off; + if (entry->child_pre_probe) + entry->child_pre_probe += gd->reloc_off; + if (entry->child_post_remove) + entry->child_post_remove += gd->reloc_off; + /* OPS are fixed in every uclass post_probe function */ + if (entry->ops) + entry->ops += gd->reloc_off; + } +} + +void fix_uclass(void) +{ + struct uclass_driver *uclass = + ll_entry_start(struct uclass_driver, uclass); + const int n_ents = ll_entry_count(struct uclass_driver, uclass); + struct uclass_driver *entry; + + for (entry = uclass; entry != uclass + n_ents; entry++) { + if (entry->post_bind) + entry->post_bind += gd->reloc_off; + if (entry->pre_unbind) + entry->pre_unbind += gd->reloc_off; + if (entry->post_probe) + entry->post_probe += gd->reloc_off; + if (entry->pre_remove) + entry->pre_remove += gd->reloc_off; + if (entry->init) + entry->init += gd->reloc_off; + if (entry->destroy) + entry->destroy += gd->reloc_off; + /* FIXME maybe also need to fix these ops */ + if (entry->ops) + entry->ops += gd->reloc_off; + } +} +#endif + int dm_init(void) { int ret; @@ -47,6 +106,11 @@ int dm_init(void) } INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST); +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + fix_drivers(); + fix_uclass(); +#endif + ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST); if (ret) return ret; diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 9131a8f..3fc7104 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -258,6 +258,22 @@ static int serial_post_probe(struct udevice *dev) #endif int ret; +#if defined(CONFIG_NEEDS_MANUAL_RELOC) + if (ops->setbrg) + ops->setbrg += gd->reloc_off; + if (ops->getc) + ops->getc += gd->reloc_off; + if (ops->putc) + ops->putc += gd->reloc_off; + if (ops->pending) + ops->pending += gd->reloc_off; + if (ops->clear) + ops->clear += gd->reloc_off; +#if CONFIG_POST & CONFIG_SYS_POST_UART + if (ops->loop) + ops->loop += gd->reloc_off +#endif +#endif /* Set the baud rate */ if (ops->setbrg) { ret = ops->setbrg(dev, gd->baudrate); -- cgit v1.1 From 89831112d46fb19127f3de9cec781e5a9c28b281 Mon Sep 17 00:00:00 2001 From: "Egli, Samuel" Date: Fri, 13 Feb 2015 15:47:10 +0100 Subject: mtd, omap: fix case NAND_OMAP_GPMC_PREFETCH not defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch c316f577b4b72d1a1aeb559e9b3fad20808f1ffd breaks siemens boards because prefetch mode is not enabled. I assume it breaks other boards as well that don't use prefetch. This patch sets read_buf to nand_read_buf if NAND_OMAP_GPMC_PREFETCH is not defined. Signed-off-by: Samuel Egli CC: Daniel Mack CC: Guido Martínez CC: Tom Rini CC: Heiko Schocher --- drivers/mtd/nand/omap_gpmc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index fc64f48..24123fc 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -989,12 +989,15 @@ int board_nand_init(struct nand_chip *nand) if (err) return err; -#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH /* TODO: Implement for 16-bit bus width */ if (nand->options & NAND_BUSWIDTH_16) nand->read_buf = nand_read_buf16; +#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH else nand->read_buf = omap_nand_read_prefetch8; +#else + else + nand->read_buf = nand_read_buf; #endif nand->dev_ready = omap_dev_ready; -- cgit v1.1 From 312aca4e6964812007c8218c0b4b0737e9e0f46a Mon Sep 17 00:00:00 2001 From: Vitaly Andrianov Date: Wed, 11 Feb 2015 14:05:41 -0500 Subject: net: keystone_net: move serdes setup to initialization function On Keystone2 devices serdes must be initialized before accessing MDIO bus. This commit moves the keystone2_net_serdes_setup() from keystone2_eth_open to keystone2_emac_initialize to meet that requirement. This also eliminates unnecessary serdes initializatin every time when the keystone2_eth_open is being called. Signed-off-by: Vitaly Andrianov Acked-by: Joe Hershberger Tested-by: Nishanth Menon --- drivers/net/keystone_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index bedab1d..35f1a57 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -398,8 +398,6 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) sys_has_mdio = (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; - keystone2_net_serdes_setup(); - if (sys_has_mdio) keystone2_mdio_reset(mdio_bus); @@ -556,6 +554,8 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) return res; } + keystone2_net_serdes_setup(); + /* Create phy device and bind it with driver */ #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr, -- cgit v1.1 From 5633a296ebb970d0a6be839fb37eaf8a11aa35f8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 2 Feb 2015 17:13:29 +0100 Subject: sunxi: video: Do not use CONFIG_SYS_MEM_TOP_HIDE for the framebuffer Do not use CONFIG_SYS_MEM_TOP_HIDE for the framebuffer, instead override board_get_usable_ram_top to make sure that u-boot is not relocated into the area where we want to use the framebuffer, and patch the devicetree from sunxi_simplefb_setup() to tell the kernel to not touch the framebuffer. This makes u-boot properly see the framebuffer as dram, and initalize the level 2 cache for it, fixing the very slow cfb scrolling problem. As an added bonus this stops us from reserving the framebuffer when simplefb is not used because an older kernel is booted, or hdp is used and no hdmi cable was plugged in, freeing up the memory for kernel use in these cases. Reported-by: Siarhei Siamashka Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/video/sunxi_display.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index f5f24fc..cd5963a 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -1060,6 +1060,11 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor) return NULL; /* never reached */ } +ulong board_get_usable_ram_top(ulong total_size) +{ + return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE; +} + void *video_hw_init(void) { static GraphicDevice *graphic_device = &sunxi_display.graphic_device; @@ -1076,7 +1081,7 @@ void *video_hw_init(void) memset(&sunxi_display, 0, sizeof(struct sunxi_display)); printf("Reserved %dkB of RAM for Framebuffer.\n", - CONFIG_SUNXI_FB_SIZE >> 10); + CONFIG_SUNXI_MAX_FB_SIZE >> 10); gd->fb_base = gd->ram_top; video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode, @@ -1194,6 +1199,7 @@ int sunxi_simplefb_setup(void *blob) { static GraphicDevice *graphic_device = &sunxi_display.graphic_device; int offset, ret; + u64 start, size; const char *pipeline = NULL; #ifdef CONFIG_MACH_SUN4I @@ -1237,6 +1243,20 @@ int sunxi_simplefb_setup(void *blob) return 0; /* Keep older kernels working */ } + /* + * Do not report the framebuffer as free RAM to the OS, note we cannot + * use fdt_add_mem_rsv() here, because then it is still seen as RAM, + * and e.g. Linux refuses to iomap RAM on ARM, see: + * linux/arch/arm/mm/ioremap.c around line 301. + */ + start = gd->bd->bi_dram[0].start; + size = gd->bd->bi_dram[0].size - CONFIG_SUNXI_MAX_FB_SIZE; + ret = fdt_fixup_memory_banks(blob, &start, &size, 1); + if (ret) { + eprintf("Cannot setup simplefb: Error reserving memory\n"); + return ret; + } + ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base, graphic_device->winSizeX, graphic_device->winSizeY, graphic_device->winSizeX * graphic_device->gdfBytesPP, -- cgit v1.1 From 20779ec3a5d7b3cad4fdc960d9e2e898fab259b3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 2 Feb 2015 18:00:53 +0100 Subject: sunxi: video: Dynamically reserve framebuffer memory Only use CONFIG_SUNXI_MAX_FB_SIZE to reserve memory at the top when relocating u-boot, and calculate the actual amount of memory necessary when setting up the video-mode and use only that, freeing up some additional memory for use by the kernel. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/video/sunxi_display.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index cd5963a..dbda97e 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -46,6 +46,7 @@ struct sunxi_display { GraphicDevice graphic_device; enum sunxi_monitor monitor; unsigned int depth; + unsigned int fb_size; } sunxi_display; #ifdef CONFIG_VIDEO_HDMI @@ -1080,10 +1081,6 @@ void *video_hw_init(void) memset(&sunxi_display, 0, sizeof(struct sunxi_display)); - printf("Reserved %dkB of RAM for Framebuffer.\n", - CONFIG_SUNXI_MAX_FB_SIZE >> 10); - gd->fb_base = gd->ram_top; - video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode, &sunxi_display.depth, &options); #ifdef CONFIG_VIDEO_HDMI @@ -1174,6 +1171,17 @@ void *video_hw_init(void) mode->yres, sunxi_get_mon_desc(sunxi_display.monitor)); } + sunxi_display.fb_size = + (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff; + if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) { + printf("Error need %dkB for fb, but only %dkB is reserved\n", + sunxi_display.fb_size >> 10, + CONFIG_SUNXI_MAX_FB_SIZE >> 10); + return NULL; + } + + gd->fb_base = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - sunxi_display.fb_size; sunxi_engines_init(); sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE); @@ -1250,7 +1258,7 @@ int sunxi_simplefb_setup(void *blob) * linux/arch/arm/mm/ioremap.c around line 301. */ start = gd->bd->bi_dram[0].start; - size = gd->bd->bi_dram[0].size - CONFIG_SUNXI_MAX_FB_SIZE; + size = gd->bd->bi_dram[0].size - sunxi_display.fb_size; ret = fdt_fixup_memory_banks(blob, &start, &size, 1); if (ret) { eprintf("Cannot setup simplefb: Error reserving memory\n"); -- cgit v1.1 From b1b912ddf3041627e99899cfc09e015a54f9910e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 11 Feb 2015 09:05:18 +0100 Subject: sunxi: otg: Fix peripheral mode Peripheral mode needs us to signal vusb high to the phy for it to work, just like the host mode does. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/musb-new/sunxi.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 778916d..4646a3d 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -145,16 +145,6 @@ static void USBC_ForceIdToHigh(__iomem void *base) musb_writel(base, USBC_REG_o_ISCR, reg_val); } -static void USBC_ForceVbusValidDisable(__iomem void *base) -{ - u32 reg_val; - - reg_val = musb_readl(base, USBC_REG_o_ISCR); - reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID); - reg_val = USBC_WakeUp_ClearChangeDetect(reg_val); - musb_writel(base, USBC_REG_o_ISCR, reg_val); -} - static void USBC_ForceVbusValidToHigh(__iomem void *base) { u32 reg_val; @@ -248,12 +238,11 @@ static int sunxi_musb_init(struct musb *musb) if (is_host_enabled(musb)) { /* Host mode */ USBC_ForceIdToLow(musb->mregs); - USBC_ForceVbusValidToHigh(musb->mregs); } else { /* Peripheral mode */ USBC_ForceIdToHigh(musb->mregs); - USBC_ForceVbusValidDisable(musb->mregs); } + USBC_ForceVbusValidToHigh(musb->mregs); return 0; } -- cgit v1.1 From 6eefd5279c4e80d613420066364ec3c8ba551a56 Mon Sep 17 00:00:00 2001 From: David Feng Date: Mon, 2 Feb 2015 16:53:13 +0800 Subject: PCI: add 64-bit prefetchable memory support PCI specification allow prefetchable memory to be 32-bit or 64-bit. PCI express specification states that all memmory bars for prefetchable memory must be implemented as 64-bit. They all require that 64 bit prefetchble memory are suported especially when u-boot is ported to more and more 64bit processors. Signed-off-by: David Feng Reviewed-by: Bin Meng --- drivers/pci/pci_auto.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index ed92857..378efbf 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -223,9 +223,12 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose, struct pci_region *pci_mem = hose->pci_mem; struct pci_region *pci_prefetch = hose->pci_prefetch; struct pci_region *pci_io = hose->pci_io; - u16 cmdstat; + u16 cmdstat, prefechable_64; pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); + pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE, + &prefechable_64); + prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; /* Configure bus number registers */ pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, @@ -252,12 +255,26 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose, /* Set up memory and I/O filter limits, assume 32-bit I/O space */ pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, (pci_prefetch->bus_lower & 0xfff00000) >> 16); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) +#ifdef CONFIG_SYS_PCI_64BIT + pci_hose_write_config_dword(hose, dev, + PCI_PREF_BASE_UPPER32, + pci_prefetch->bus_lower >> 32); +#else + pci_hose_write_config_dword(hose, dev, + PCI_PREF_BASE_UPPER32, + 0x0); +#endif cmdstat |= PCI_COMMAND_MEMORY; } else { /* We don't support prefetchable memory for now, so disable */ pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000); pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) { + pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0); + pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0); + } } if (pci_io) { @@ -297,11 +314,28 @@ void pciauto_postscan_setup_bridge(struct pci_controller *hose, } if (pci_prefetch) { + u16 prefechable_64; + + pci_hose_read_config_word(hose, dev, + PCI_PREF_MEMORY_LIMIT, + &prefechable_64); + prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; + /* Round memory allocator to 1MB boundary */ pciauto_region_align(pci_prefetch, 0x100000); pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, (pci_prefetch->bus_lower - 1) >> 16); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) +#ifdef CONFIG_SYS_PCI_64BIT + pci_hose_write_config_dword(hose, dev, + PCI_PREF_LIMIT_UPPER32, + (pci_prefetch->bus_lower - 1) >> 32); +#else + pci_hose_write_config_dword(hose, dev, + PCI_PREF_LIMIT_UPPER32, + 0x0); +#endif } if (pci_io) { -- cgit v1.1 From 6fb9ac15ebac4bcc4864be7958bf9b2b2b7420de Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 13 Feb 2015 12:20:47 -0700 Subject: dm: cros_ec: Convert to Kconfig Since both I2C and SPI are converted to Kconfig, we can convert cros_ec to Kconfig for these buses. LPC will need to wait until driver mode PCI is available. Signed-off-by: Simon Glass --- drivers/input/Kconfig | 6 ++++++ drivers/misc/Kconfig | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index e69de29..bb00de7 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -0,0 +1,6 @@ +config CROS_EC_KEYB + bool "Enable Chrome OS EC keyboard support" + help + Most ARM Chromebooks use an EC to provide access to the keyboard. + Messages are used to request key scans from the EC and these are + then decoded into keys by this driver. diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 813d1c2..0df25c3 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -1,3 +1,49 @@ +config CMD_CROS_EC + bool "Enable crosec command" + depends on CROS_EC + help + Enable command-line access to the Chrome OS EC (Embedded + Controller). This provides the 'crosec' command which has + a number of sub-commands for performing EC tasks such as + updating its flash, accessing a small saved context area + and talking to the I2C bus behind the EC (if there is one). + +config CROS_EC + bool "Enable Chrome OS EC" + help + Enable access to the Chrome OS EC. This is a separate + microcontroller typically available on a SPI bus on Chromebooks. It + provides access to the keyboard, some internal storage and may + control access to the battery and main PMIC depending on the + device. You can use the 'crosec' command to access it. + +config CROS_EC_I2C + bool "Enable Chrome OS EC I2C driver" + depends on CROS_EC + help + Enable I2C access to the Chrome OS EC. This is used on older + ARM Chromebooks such as snow and spring before the standard bus + changed to SPI. The EC will accept commands across the I2C using + a special message protocol, and provide responses. + +config CROS_EC_LPC + bool "Enable Chrome OS EC LPC driver" + depends on CROS_EC + help + Enable I2C access to the Chrome OS EC. This is used on x86 + Chromebooks such as link and falco. The keyboard is provided + through a legacy port interface, so on x86 machines the main + function of the EC is power and thermal management. + +config CROS_EC_SPI + bool "Enable Chrome OS EC SPI driver" + depends on CROS_EC + help + Enable SPI access to the Chrome OS EC. This is used on newer + ARM Chromebooks such as pit, pi and nyan-big. The SPI interface + provides a faster and more robust interface than I2C but the bugs + are less interesting. + config DM_CROS_EC bool "Enable Driver Model for Chrome OS EC" depends on DM @@ -5,5 +51,5 @@ config DM_CROS_EC Enable driver model for the Chrome OS EC interface. This allows the cros_ec SPI driver to operate with CONFIG_DM_SPI but otherwise makes few changes. Since cros_ec also supports - I2C and LPC (which don't support driver model yet), a full + LPC (which doesn't support driver model yet), a full conversion is not yet possible. -- cgit v1.1 From 4bba9d3f77061ea742d8f697ce72251fb79c8016 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 13 Feb 2015 12:20:48 -0700 Subject: dm: Move CONFIG_I2C_COMPAT to Kconfig Make this option available in Kconfig and clean up the board that uses it. Note there is also an entry in exynos5-common.h but this affects multiple boards and should be dropped as part of the Samsung I2C migration to driver model. Signed-off-by: Simon Glass --- drivers/i2c/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 2cc776c..692810d 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -13,6 +13,15 @@ config DM_I2C enabled together (it is not possible to use driver model for one and not the other). +config DM_I2C_COMPAT + bool "Enable I2C compatibility layer" + depends on DM + help + Enable old-style I2C functions for compatibility with existing code. + This option can be enabled as a temporary measure to avoid needing + to convert all code for a board in a single commit. It should not + be enabled for any board in an official release. + config SYS_I2C_UNIPHIER bool "UniPhier I2C driver" depends on ARCH_UNIPHIER && DM_I2C -- cgit v1.1 From 2f964aa7b1bf7de50587a1864cf60d187ebefb2c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Jan 2015 18:27:07 -0700 Subject: serial: Support an early UART for debugging This came up in a discussion on the mailing list here: https://patchwork.ozlabs.org/patch/384613/ My concerns at the time were: - it doesn't need to be written in assembler - it doesn't need to be ARM-specific This patch provides a possible alternative. It works by allowing any serial driver to export one init function and provide a putc() function. These can be used to output debug data before the real serial driver is available. This implementation does not depend on driver model, and it is possible for it to operate without a stack on some architectures (e.g. PowerPC, ARM). It provides the same features as the ARM-specific debug.S but with more UART and architecture support. Signed-off-by: Simon Glass --- drivers/serial/Kconfig | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index c94353b..6313258 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -7,6 +7,52 @@ config DM_SERIAL implements serial_putc() etc. The uclass interface is defined in include/serial.h. +config DEBUG_UART + bool "Enable an early debug UART for debugging" + help + The debug UART is intended for use very early in U-Boot to debug + problems when an ICE or other debug mechanism is not available. + + To use it you should: + - Make sure your UART supports this interface + - Enable CONFIG_DEBUG_UART + - Enable the CONFIG for your UART to tell it to provide this interface + (e.g. CONFIG_DEBUG_UART_NS16550) + - Define the required settings as needed (see below) + - Call debug_uart_init() before use + - Call debug_uart_putc() to output a character + + Depending on your platform it may be possible to use this UART before + a stack is available. + + If your UART does not support this interface you can probably add + support quite easily. Remember that you cannot use driver model and + it is preferred to use no stack. + + You must not use this UART once driver model is working and the + serial drivers are up and running (done in serial_init()). Otherwise + the drivers may conflict and you will get strange output. + +config DEBUG_UART_BASE + hex "Base address of UART" + depends on DEBUG_UART + help + This is the base address of your UART for memory-mapped UARTs. + + A default should be provided by your board, but if not you will need + to use the correct value here. + +config DEBUG_UART_CLOCK + int "UART input clock" + depends on DEBUG_UART + help + The UART input clock determines the speed of the internal UART + circuitry. The baud rate is derived from this by dividing the input + clock down. + + A default should be provided by your board, but if not you will need + to use the correct value here. + config UNIPHIER_SERIAL bool "UniPhier on-chip UART support" depends on ARCH_UNIPHIER && DM_SERIAL -- cgit v1.1 From 765716744f6743d6c1e6b3c92eea163b4ee59f3c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Jan 2015 18:27:08 -0700 Subject: serial: ns16550: Add access functions that don't need platdata For the debug UART we need to be able to provide any parameters before driver model is set up. Add parameters to the low-level access functions to make this possible. Signed-off-by: Simon Glass --- drivers/serial/ns16550.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 70c9462..57e6125 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -55,17 +55,9 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* CONFIG_SYS_NS16550_IER */ #ifdef CONFIG_DM_SERIAL -static void ns16550_writeb(NS16550_t port, int offset, int value) -{ - struct ns16550_platdata *plat = port->plat; - unsigned char *addr; - offset *= 1 << plat->reg_shift; - addr = map_sysmem(plat->base, 0) + offset; - /* - * As far as we know it doesn't make sense to support selection of - * these options at run-time, so use the existing CONFIG options. - */ +static inline void serial_out_shift(unsigned char *addr, int shift, int value) +{ #ifdef CONFIG_SYS_NS16550_PORT_MAPPED outb(value, (ulong)addr); #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) @@ -73,19 +65,14 @@ static void ns16550_writeb(NS16550_t port, int offset, int value) #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) out_be32(addr, value); #elif defined(CONFIG_SYS_BIG_ENDIAN) - writeb(value, addr + (1 << plat->reg_shift) - 1); + writeb(value, addr + (1 << shift) - 1); #else writeb(value, addr); #endif } -static int ns16550_readb(NS16550_t port, int offset) +static inline int serial_in_shift(unsigned char *addr, int shift) { - struct ns16550_platdata *plat = port->plat; - unsigned char *addr; - - offset *= 1 << plat->reg_shift; - addr = map_sysmem(plat->base, 0) + offset; #ifdef CONFIG_SYS_NS16550_PORT_MAPPED return inb((ulong)addr); #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) @@ -93,12 +80,37 @@ static int ns16550_readb(NS16550_t port, int offset) #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) return in_be32(addr); #elif defined(CONFIG_SYS_BIG_ENDIAN) - return readb(addr + (1 << plat->reg_shift) - 1); + return readb(addr + (1 << reg_shift) - 1); #else return readb(addr); #endif } +static void ns16550_writeb(NS16550_t port, int offset, int value) +{ + struct ns16550_platdata *plat = port->plat; + unsigned char *addr; + + offset *= 1 << plat->reg_shift; + addr = map_sysmem(plat->base, 0) + offset; + /* + * As far as we know it doesn't make sense to support selection of + * these options at run-time, so use the existing CONFIG options. + */ + serial_out_shift(addr, plat->reg_shift, value); +} + +static int ns16550_readb(NS16550_t port, int offset) +{ + struct ns16550_platdata *plat = port->plat; + unsigned char *addr; + + offset *= 1 << plat->reg_shift; + addr = map_sysmem(plat->base, 0) + offset; + + return serial_in_shift(addr, plat->reg_shift); +} + /* We can clean these up once everything is moved to driver model */ #define serial_out(value, addr) \ ns16550_writeb(com_port, addr - (unsigned char *)com_port, value) -- cgit v1.1 From 21d004368fc8a4da07147c58dfe9a4e16d4ab761 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 26 Jan 2015 18:27:09 -0700 Subject: serial: ns16550: Support debug UART Add debug UART functions to permit ns16550 to provide an early debug UART. Try to avoid using the stack so that this can be called from assembler before a stack is set up (at least on ARM and PowerPC). Signed-off-by: Simon Glass --- drivers/serial/Kconfig | 13 +++++++++++++ drivers/serial/ns16550.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 6313258..1686a1f 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -33,6 +33,19 @@ config DEBUG_UART serial drivers are up and running (done in serial_init()). Otherwise the drivers may conflict and you will get strange output. +choice + prompt "Select which UART will provide the debug UART" + depends on DEBUG_UART + +config DEBUG_UART_NS16550 + bool "ns16550" + help + Select this to enable a debug UART using the ns16550 driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver model serial is running. + +endchoice + config DEBUG_UART_BASE hex "Base address of UART" depends on DEBUG_UART diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 57e6125..eb00f1c 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -118,10 +118,15 @@ static int ns16550_readb(NS16550_t port, int offset) ns16550_readb(com_port, addr - (unsigned char *)com_port) #endif -int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) +static inline int calc_divisor(NS16550_t port, int clock, int baudrate) { const unsigned int mode_x_div = 16; + return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); +} + +int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) +{ #ifdef CONFIG_OMAP1510 /* If can't cleanly clock 115200 set div to 1 */ if ((clock == 12000000) && (baudrate == 115200)) { @@ -131,7 +136,7 @@ int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) port->osc_12m_sel = 0; /* clear if previsouly set */ #endif - return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); + return calc_divisor(port, clock, baudrate); } static void NS16550_setbrg(NS16550_t com_port, int baud_divisor) @@ -231,6 +236,47 @@ int NS16550_tstc(NS16550_t com_port) #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ +#ifdef CONFIG_DEBUG_UART_NS16550 + +#include + +void debug_uart_init(void) +{ + struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; + int baud_divisor; + + /* + * We copy the code from above because it is already horribly messy. + * Trying to refactor to nicely remove the duplication doesn't seem + * feasible. The better fix is to move all users of this driver to + * driver model. + */ + baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); + + serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER); + serial_out_shift(&com_port->mcr, 0, UART_MCRVAL); + serial_out_shift(&com_port->fcr, 0, UART_FCRVAL); + + serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL); + serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff); + serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff); + serial_out_shift(&com_port->lcr, 0, UART_LCRVAL); +} + +static inline void _debug_uart_putc(int ch) +{ + struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; + + while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE)) + ; + serial_out_shift(&com_port->thr, 0, ch); +} + +DEBUG_UART_FUNCS + +#endif + #ifdef CONFIG_DM_SERIAL static int ns16550_serial_putc(struct udevice *dev, const char ch) { -- cgit v1.1 From 242e3d893d1311ea38abd25613076a29961d422e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 17:26:41 +0100 Subject: sunxi: video: Add support for LCD reset pin On some boards there is a gpio to reset the LCD panel, add support for this. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/video/sunxi_display.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index dbda97e..7f01401 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -592,7 +592,7 @@ static void sunxi_lcdc_enable(void) static void sunxi_lcdc_panel_enable(void) { - int pin; + int pin, reset_pin; /* * Start with backlight disabled to avoid the screen flashing to @@ -610,6 +610,12 @@ static void sunxi_lcdc_panel_enable(void) gpio_direction_output(pin, PWM_OFF); } + reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET); + if (reset_pin != -1) { + gpio_request(reset_pin, "lcd_reset"); + gpio_direction_output(reset_pin, 0); /* Assert reset */ + } + /* Give the backlight some time to turn off and power up the panel. */ mdelay(40); pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER); @@ -617,6 +623,9 @@ static void sunxi_lcdc_panel_enable(void) gpio_request(pin, "lcd_power"); gpio_direction_output(pin, 1); } + + if (reset_pin != -1) + gpio_direction_output(reset_pin, 1); /* De-assert reset */ } static void sunxi_lcdc_backlight_enable(void) -- cgit v1.1 From aad2ac24c0871bb897be676aca946f37dd05f187 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 17:49:47 +0100 Subject: sunxi: video: Add support for tl059wv5c0 lcd panels Add support for the 6" 480x800 tl059wv5c0 panel used on e.g. Utoo P66 and Aigo M60/M608/M606 tablets. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/video/sunxi_display.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 7f01401..4e12150 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "videomodes.h" #include "hitachi_tx18d42vm_lcd.h" @@ -1030,6 +1031,12 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, mdelay(50); /* Wait for lcd controller power on */ hitachi_tx18d42vm_init(); } + if (IS_ENABLED(CONFIG_VIDEO_LCD_TL059WV5C0)) { + unsigned int orig_i2c_bus = i2c_get_bus_num(); + i2c_set_bus_num(CONFIG_VIDEO_LCD_I2C_BUS); + i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */ + i2c_set_bus_num(orig_i2c_bus); + } sunxi_composer_mode_set(mode, address); sunxi_lcdc_tcon0_mode_set(mode, false); sunxi_composer_enable(); -- cgit v1.1 From 1de32b8a69eebdd208914c2a90dfb6cdd8ea8352 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 19 Feb 2015 20:34:32 +0100 Subject: sunxi: mmc: Always declare High Capacity capability High Capacity (e)MMC cards work fine on sun4i / sun5i, and not having this capability set causes u-boot to not recognize the eMMC on an Utoo P66 A13 tablet, so always set it thereby fixing this. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/mmc/sunxi_mmc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index ebfec7c..2233545 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -449,11 +449,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; - cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; -#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \ - defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN9I) - cfg->host_caps |= MMC_MODE_HC; -#endif + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->f_min = 400000; -- cgit v1.1 From 52defe8f65700ad625c3ca63f723564210b2dc82 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 22:13:43 +0100 Subject: sunxi: musb: Check Vbus-det before enabling otg port power Sending out 5V when there is a charger connected to the otg port is not a good idea, so check for this and error out. Note this commit currently breaks otg support on the q8h tablets, as we need to do some magic with the pmic there to get vbus info, this is deliberate (better safe then sorry), fixing this is on my TODO list. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/musb-new/sunxi.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 4646a3d..fe45db1 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -22,7 +22,9 @@ */ #include #include +#include #include +#include #include "linux-compat.h" #include "musb_core.h" @@ -224,6 +226,33 @@ static int sunxi_musb_init(struct musb *musb) pr_debug("%s():\n", __func__); + if (is_host_enabled(musb)) { + int vbus_det = sunxi_name_to_gpio(CONFIG_USB0_VBUS_DET); + if (vbus_det == -1) { + eprintf("Error invalid Vusb-det pin\n"); + return -EINVAL; + } + + err = gpio_request(vbus_det, "vbus0_det"); + if (err) + return err; + + err = gpio_direction_input(vbus_det); + if (err) { + gpio_free(vbus_det); + return err; + } + + err = gpio_get_value(vbus_det); + if (err) { + eprintf("Error: A charger is plugged into the OTG\n"); + gpio_free(vbus_det); + return -EIO; + } + + gpio_free(vbus_det); + } + err = sunxi_usbc_request_resources(0); if (err) return err; -- cgit v1.1 From afc9e2b509a6db3b716c81c97f9147491ebf76ba Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 14 Jan 2015 17:37:53 +0900 Subject: mmc: dw_mmc: fixed the wrong bit control If mode is not DDR-mode, then it needs to clear it. Signed-off-by: Jaehoon Chung --- drivers/mmc/dw_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index b18c75d..76fa0b0 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -321,7 +321,7 @@ static void dwmci_set_ios(struct mmc *mmc) if (mmc->ddr_mode) regs |= DWMCI_DDR_MODE; else - regs &= DWMCI_DDR_MODE; + regs &= ~DWMCI_DDR_MODE; dwmci_writel(host, DWMCI_UHS_REG, regs); -- cgit v1.1 From 3a33bb1874a75abde8872915f808945b6d20f6f2 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 4 Feb 2015 15:48:39 +0900 Subject: mmc: exynos_dw_mmc: set to clksel_val into board-init function "clksel_val" is assigned to property of mmc or defined value. But it doesn't write at initial sequence. There is a reason that get the wrong source-clock value. This patch fixed it. Signed-off-by: Jaehoon Chung --- drivers/mmc/exynos_dw_mmc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index dfa209b..3936660 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -64,6 +64,10 @@ static void exynos_dwmci_board_init(struct dwmci_host *host) MPSCTRL_NON_SECURE_READ_BIT | MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID); } + + /* Set to clksel_val at initial time */ + if (host->clksel_val) + exynos_dwmci_clksel(host); } static int exynos_dwmci_core_init(struct dwmci_host *host, int index) -- cgit v1.1 From 5dab81cea5500558b7bfc43a7364ae7ed706d2fc Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 4 Feb 2015 15:48:40 +0900 Subject: mmc: exynos_dw_mmc: use the exynos specific data structure Clksel value is exynos specific value. It removed "clksel_val" into dwmci_host and created the "dwmci_exynos_priv_data" structure for exynos specific data. Signed-off-by: Jaehoon Chung --- drivers/mmc/exynos_dw_mmc.c | 60 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 3936660..c66c0b0 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -19,8 +19,13 @@ #define DWMMC_MAX_CH_NUM 4 #define DWMMC_MAX_FREQ 52000000 #define DWMMC_MIN_FREQ 400000 -#define DWMMC_MMC0_CLKSEL_VAL 0x03030001 -#define DWMMC_MMC2_CLKSEL_VAL 0x03020001 +#define DWMMC_MMC0_SDR_TIMING_VAL 0x03030001 +#define DWMMC_MMC2_SDR_TIMING_VAL 0x03020001 + +/* Exynos implmentation specific drver private data */ +struct dwmci_exynos_priv_data { + u32 sdr_timing; +}; /* * Function used as callback function to initialise the @@ -28,7 +33,9 @@ */ static void exynos_dwmci_clksel(struct dwmci_host *host) { - dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val); + struct dwmci_exynos_priv_data *priv = host->priv; + + dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing); } unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) @@ -55,6 +62,8 @@ unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) static void exynos_dwmci_board_init(struct dwmci_host *host) { + struct dwmci_exynos_priv_data *priv = host->priv; + if (host->quirks & DWMCI_QUIRK_DISABLE_SMU) { dwmci_writel(host, EMMCP_MPSBEGIN0, 0); dwmci_writel(host, EMMCP_SEND0, 0); @@ -65,8 +74,8 @@ static void exynos_dwmci_board_init(struct dwmci_host *host) MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID); } - /* Set to clksel_val at initial time */ - if (host->clksel_val) + /* Set to timing value at initial time */ + if (priv->sdr_timing) exynos_dwmci_clksel(host); } @@ -74,6 +83,7 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) { unsigned int div; unsigned long freq, sclk; + struct dwmci_exynos_priv_data *priv = host->priv; if (host->bus_hz) freq = host->bus_hz; @@ -92,11 +102,11 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) #endif host->board_init = exynos_dwmci_board_init; - if (!host->clksel_val) { + if (!priv->sdr_timing) { if (index == 0) - host->clksel_val = DWMMC_MMC0_CLKSEL_VAL; + priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL; else if (index == 2) - host->clksel_val = DWMMC_MMC2_CLKSEL_VAL; + priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL; } host->caps = MMC_MODE_DDR_52MHz; @@ -122,6 +132,7 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) { struct dwmci_host *host = NULL; + struct dwmci_exynos_priv_data *priv; host = malloc(sizeof(struct dwmci_host)); if (!host) { @@ -129,11 +140,19 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) return -ENOMEM; } + priv = malloc(sizeof(struct dwmci_exynos_priv_data)); + if (!priv) { + error("dwmci_exynos_priv_data malloc fail!\n"); + return -ENOMEM; + } + host->ioaddr = (void *)regbase; host->buswidth = bus_width; if (clksel) - host->clksel_val = clksel; + priv->sdr_timing = clksel; + + host->priv = priv; return exynos_dwmci_core_init(host, index); } @@ -161,7 +180,14 @@ static int exynos_dwmci_get_config(const void *blob, int node, struct dwmci_host *host) { int err = 0; - u32 base, clksel_val, timing[3]; + u32 base, timing[3]; + struct dwmci_exynos_priv_data *priv; + + priv = malloc(sizeof(struct dwmci_exynos_priv_data)); + if (!priv) { + error("dwmci_exynos_priv_data malloc fail!\n"); + return -ENOMEM; + } /* Extract device id for each mmc channel */ host->dev_id = pinmux_decode_periph_id(blob, node); @@ -194,16 +220,24 @@ static int exynos_dwmci_get_config(const void *blob, int node, return -EINVAL; } - clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) | + priv->sdr_timing = (DWMCI_SET_SAMPLE_CLK(timing[0]) | DWMCI_SET_DRV_CLK(timing[1]) | DWMCI_SET_DIV_RATIO(timing[2])); - if (clksel_val) - host->clksel_val = clksel_val; + + /* sdr_timing didn't assigned anything, use the default value */ + if (!priv->sdr_timing) { + if (host->dev_index == 0) + priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL; + else if (host->dev_index == 2) + priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL; + } host->fifoth_val = fdtdec_get_int(blob, node, "fifoth_val", 0); host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0); host->div = fdtdec_get_int(blob, node, "div", 0); + host->priv = priv; + return 0; } -- cgit v1.1 From 1f3e877defc5a073f8e93c04e03f9a75f34dd595 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 19 Feb 2015 21:03:21 +0100 Subject: sunxi: mmc: Always declare High Capacity capability High Capacity (e)MMC cards work fine on sun4i / sun5i, and not having this capability set causes u-boot to not recognize the eMMC on an Utoo P66 A13 tablet, so always set it thereby fixing this. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/mmc/sunxi_mmc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index ebfec7c..2233545 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -449,11 +449,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; - cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; -#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \ - defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN9I) - cfg->host_caps |= MMC_MODE_HC; -#endif + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->f_min = 400000; -- cgit v1.1 From 64029f7aeec4e843ab99297c24e0ef4f40267a6e Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Fri, 20 Feb 2015 12:29:26 +0100 Subject: mmc: exynos dwmmc: check boot mode before init dwmmc Before this commit, the mmc devices were always registered in the same order. So dwmmc channel 0 was registered as mmc 0, channel 1 as mmc 1, etc. In case of possibility to boot from more then one device, the CONFIG_SYS_MMC_ENV_DEV should always point to right mmc device. This can be achieved by init boot device as first, so it will be always registered as mmc 0. Thanks to this, the 'saveenv' command will work fine for all mmc boot devices. Exynos based boards usually uses mmc host channels configuration: - 0, or 0+1 for 8 bit - as a default boot device (usually eMMC) - 2 for 4bit - as an optional boot device (usually SD card slot) And usually the boot order is defined by OM pin configuration, which can be changed in a few ways, eg. - Odroid U3 - eMMC card insertion -> first boot from eMMC - Odroid X2/XU3 - boot priority jumper By this commit, Exynos dwmmc driver will check the OM pin configuration, and then try to init the boot device and register it as mmc 0. Signed-off-by: Przemyslaw Marczak Cc: Minkyu Kang Cc: Jaehoon Chung Cc: Pantelis Antoniou Cc: Simon Glass Cc: Akshay Saraswat --- drivers/mmc/exynos_dw_mmc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index c66c0b0..e083745 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -196,7 +197,6 @@ static int exynos_dwmci_get_config(const void *blob, int node, if (host->dev_index == host->dev_id) host->dev_index = host->dev_id - PERIPH_ID_SDMMC0; - /* Get the bus width from the device node */ host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0); if (host->buswidth <= 0) { @@ -267,12 +267,21 @@ int exynos_dwmmc_init(const void *blob) { int compat_id; int node_list[DWMMC_MAX_CH_NUM]; + int boot_dev_node; int err = 0, count; compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC; count = fdtdec_find_aliases_for_id(blob, "mmc", compat_id, node_list, DWMMC_MAX_CH_NUM); + + /* For DWMMC always set boot device as mmc 0 */ + if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) { + boot_dev_node = node_list[2]; + node_list[2] = node_list[0]; + node_list[0] = boot_dev_node; + } + err = exynos_dwmci_process_node(blob, node_list, count); return err; -- cgit v1.1 From 34dd928492fa020455d9b9f59fe4b643c0708306 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Fri, 20 Feb 2015 12:29:27 +0100 Subject: mmc: print SD/eMMC type for inited mmc devices Depending on the boot priority, the eMMC/SD cards, can be initialized with the same numbers for each boot. To be sure which mmc device is SD and which is eMMC, this info is printed by 'mmc list' command, when the init is done. Signed-off-by: Przemyslaw Marczak Cc: Pantelis Antoniou --- drivers/mmc/mmc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index b8039cd..a13769e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1693,11 +1693,19 @@ void print_mmc_devices(char separator) { struct mmc *m; struct list_head *entry; + char *mmc_type; list_for_each(entry, &mmc_devices) { m = list_entry(entry, struct mmc, link); + if (m->has_init) + mmc_type = IS_SD(m) ? "SD" : "eMMC"; + else + mmc_type = NULL; + printf("%s: %d", m->cfg->name, m->block_dev.dev); + if (mmc_type) + printf(" (%s)", mmc_type); if (entry->next != &mmc_devices) { printf("%c", separator); -- cgit v1.1 From f88a429f1179c9d9ab2883fba0ed0aa13c9bd72e Mon Sep 17 00:00:00 2001 From: Matt Reimer Date: Thu, 19 Feb 2015 11:22:53 -0700 Subject: mmc: sdhci: fix bus width switching on Samsung SoCs Fix bus width switching from 8-bit mode down to 4-bit or 1-bit modes on Samsung SoCs using SDHCI_QUIRK_USE_WIDE8. These SoCs report controller version 2.0 yet they support 8-bit bus widths. If 8-bit mode was previously enabled and then an operation like "mmc dev" caused a switch back down to 4-bit or 1-bit mode, WIDE8 was left set, causing failures. This problem was manifested by "mmc dev" timing out. Signed-off-by: Matt Reimer --- drivers/mmc/sdhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index de88e19..82d7984 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -374,7 +374,8 @@ static void sdhci_set_ios(struct mmc *mmc) (host->quirks & SDHCI_QUIRK_USE_WIDE8)) ctrl |= SDHCI_CTRL_8BITBUS; } else { - if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) + if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) || + (host->quirks & SDHCI_QUIRK_USE_WIDE8)) ctrl &= ~SDHCI_CTRL_8BITBUS; if (mmc->bus_width == 4) ctrl |= SDHCI_CTRL_4BITBUS; -- cgit v1.1 From 1f3402e7291afa3ba0a5f4da72640edaf2f65405 Mon Sep 17 00:00:00 2001 From: York Sun Date: Tue, 6 Jan 2015 13:18:45 -0800 Subject: driver/ddr/fsl: Adjust CAS to preamble override for emulator On ZeBu emulator, CAS to preamble overrides need to be set to satisfy the timing. This only impact platforms with CONFIG_EMU. These should be set before MEM_EN is set. Signed-off-by: York Sun --- drivers/ddr/fsl/ctrl_regs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 03d7ff1..b3477f0 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -2372,7 +2372,11 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, #ifdef CONFIG_SYS_FSL_DDR_EMU /* disble DDR training for emulator */ ddr->debug[2] = 0x00000400; - ddr->debug[4] = 0xff800000; + ddr->debug[4] = 0xff800800; + ddr->debug[5] = 0x08000800; + ddr->debug[6] = 0x08000800; + ddr->debug[7] = 0x08000800; + ddr->debug[8] = 0x08000800; #endif #ifdef CONFIG_SYS_FSL_ERRATUM_A004508 if ((ip_rev >= 0x40000) && (ip_rev < 0x40400)) -- cgit v1.1 From 9955b4ab0187e0e9faac57acc01ebe7714d0ec23 Mon Sep 17 00:00:00 2001 From: York Sun Date: Tue, 6 Jan 2015 13:18:47 -0800 Subject: driver/ddr/fsl: Add workaround for A008336 Erratum A008336 requires setting EDDRTQCR1[2] in DDRC DCSR space for 64-bit DDR controllers. Signed-off-by: York Sun --- drivers/ddr/fsl/fsl_ddr_gen4.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 4eef047..5c2579e 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -32,24 +32,39 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, u32 temp_sdram_cfg; u32 total_gb_size_per_controller; int timeout; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 + u32 *eddrtqcr1; +#endif switch (ctrl_num) { case 0: ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR_ADDR + 0x800; +#endif break; #if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) case 1: ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR2_ADDR + 0x800; +#endif break; #endif #if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) case 2: ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR3_ADDR + 0x800; +#endif break; #endif #if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) case 3: ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR4_ADDR + 0x800; +#endif break; #endif default: @@ -60,6 +75,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, if (step == 2) goto step2; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 +#ifdef CONFIG_LS2085A + /* A008336 only applies to general DDR controllers */ + if ((ctrl_num == 0) || (ctrl_num == 1)) +#endif + ddr_out32(eddrtqcr1, 0x63b30002); +#endif if (regs->ddr_eor) ddr_out32(&ddr->eor, regs->ddr_eor); -- cgit v1.1 From 49fd1f3f265efc00d61effa995bd6a733bf273d8 Mon Sep 17 00:00:00 2001 From: York Sun Date: Tue, 6 Jan 2015 13:18:48 -0800 Subject: driver/ddr/fsl: Add workround for erratumn A008514 Erratum A008514 workround requires writing register eddrtqcr1 with value 0x63b20002. Signed-off-by: York Sun --- drivers/ddr/fsl/fsl_ddr_gen4.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 5c2579e..9cca4a0 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -32,21 +32,24 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, u32 temp_sdram_cfg; u32 total_gb_size_per_controller; int timeout; -#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008336) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A008514) u32 *eddrtqcr1; #endif switch (ctrl_num) { case 0: ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; -#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008336) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A008514) eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR_ADDR + 0x800; #endif break; #if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) case 1: ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; -#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008336) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A008514) eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR2_ADDR + 0x800; #endif break; @@ -54,7 +57,8 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, #if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) case 2: ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR; -#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008336) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A008514) eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR3_ADDR + 0x800; #endif break; @@ -62,7 +66,8 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, #if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) case 3: ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; -#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 +#if defined(CONFIG_SYS_FSL_ERRATUM_A008336) || \ + defined(CONFIG_SYS_FSL_ERRATUM_A008514) eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR4_ADDR + 0x800; #endif break; @@ -82,6 +87,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, #endif ddr_out32(eddrtqcr1, 0x63b30002); #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A008514 +#ifdef CONFIG_LS2085A + /* A008514 only applies to DP-DDR controler */ + if (ctrl_num == 2) +#endif + ddr_out32(eddrtqcr1, 0x63b20002); +#endif if (regs->ddr_eor) ddr_out32(&ddr->eor, regs->ddr_eor); -- cgit v1.1 From 03e664d8f4065010ccb6c75648192200a832fd8b Mon Sep 17 00:00:00 2001 From: York Sun Date: Tue, 6 Jan 2015 13:18:50 -0800 Subject: driver/ddr/fsl: Add support for multiple DDR clocks Controller number is passed for function calls to support individual DDR clock, depending on SoC implementation. It is backward compatible with exising platforms. Multiple clocks have been verifyed on LS2085A emulator. Signed-off-by: York Sun --- drivers/ddr/fsl/arm_ddr_gen3.c | 2 +- drivers/ddr/fsl/ctrl_regs.c | 208 +++++++++++++++++--------------- drivers/ddr/fsl/ddr1_dimm_params.c | 18 +-- drivers/ddr/fsl/ddr2_dimm_params.c | 12 +- drivers/ddr/fsl/ddr3_dimm_params.c | 8 +- drivers/ddr/fsl/ddr4_dimm_params.c | 8 +- drivers/ddr/fsl/fsl_ddr_gen4.c | 2 +- drivers/ddr/fsl/lc_common_dimm_params.c | 27 +++-- drivers/ddr/fsl/main.c | 25 ++-- drivers/ddr/fsl/mpc85xx_ddr_gen3.c | 4 +- drivers/ddr/fsl/options.c | 6 +- drivers/ddr/fsl/util.c | 12 +- 12 files changed, 180 insertions(+), 152 deletions(-) (limited to 'drivers') diff --git a/drivers/ddr/fsl/arm_ddr_gen3.c b/drivers/ddr/fsl/arm_ddr_gen3.c index c139da6..7160da4 100644 --- a/drivers/ddr/fsl/arm_ddr_gen3.c +++ b/drivers/ddr/fsl/arm_ddr_gen3.c @@ -222,7 +222,7 @@ step2: bus_width = 3 - ((ddr_in32(&ddr->sdram_cfg) & SDRAM_CFG_DBW_MASK) >> SDRAM_CFG_DBW_SHIFT); timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 / - (get_ddr_freq(0) >> 20)) << 1; + (get_ddr_freq(ctrl_num) >> 20)) << 1; total_gb_size_per_controller >>= 4; /* shift down to gb size */ debug("total %d GB\n", total_gb_size_per_controller); debug("Need to wait up to %d * 10ms\n", timeout); diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index b3477f0..713c3ed 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -17,8 +17,6 @@ #include #include -unsigned int picos_to_mclk(unsigned int picos); - /* * Determine Rtt value. * @@ -78,10 +76,11 @@ static inline int fsl_ddr_get_rtt(void) * 16 for <= 2933MT/s * 18 for higher */ -static inline unsigned int compute_cas_write_latency(void) +static inline unsigned int compute_cas_write_latency( + const unsigned int ctrl_num) { unsigned int cwl; - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); if (mclk_ps >= 1250) cwl = 9; else if (mclk_ps >= 1070) @@ -111,10 +110,11 @@ static inline unsigned int compute_cas_write_latency(void) * 11 if 0.935ns > tCK >= 0.833ns * 12 if 0.833ns > tCK >= 0.75ns */ -static inline unsigned int compute_cas_write_latency(void) +static inline unsigned int compute_cas_write_latency( + const unsigned int ctrl_num) { unsigned int cwl; - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); if (mclk_ps >= 2500) cwl = 5; @@ -287,7 +287,8 @@ static inline int avoid_odt_overlap(const dimm_params_t *dimm_params) * Avoid writing for DDR I. The new PQ38 DDR controller * dreams up non-zero default values to be backwards compatible. */ -static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, +static void set_timing_cfg_0(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const dimm_params_t *dimm_params) { @@ -306,7 +307,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, /* Mode register set cycle time (tMRD). */ unsigned char tmrd_mclk; #if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3) - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); #endif #ifdef CONFIG_SYS_FSL_DDR4 @@ -314,15 +315,15 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */ trwt_mclk = 2; twrt_mclk = 1; - act_pd_exit_mclk = picos_to_mclk(txp); + act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp); pre_pd_exit_mclk = act_pd_exit_mclk; /* * MRS_CYC = max(tMRD, tMOD) * tMRD = 8nCK, tMOD = max(24nCK, 15ns) */ - tmrd_mclk = max(24U, picos_to_mclk(15000)); + tmrd_mclk = max(24U, picos_to_mclk(ctrl_num, 15000)); #elif defined(CONFIG_SYS_FSL_DDR3) - unsigned int data_rate = get_ddr_freq(0); + unsigned int data_rate = get_ddr_freq(ctrl_num); int txp; unsigned int ip_rev; int odt_overlap; @@ -344,7 +345,8 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, * tMRD = 4nCK (8nCK for RDIMM) * tMOD = max(12nCK, 15ns) */ - tmrd_mclk = max((unsigned int)12, picos_to_mclk(15000)); + tmrd_mclk = max((unsigned int)12, + picos_to_mclk(ctrl_num, 15000)); } else { /* * MRS_CYC = tMRD @@ -388,7 +390,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, taxpd_mclk = 1; } else { /* act_pd_exit_mclk = tXARD, see above */ - act_pd_exit_mclk = picos_to_mclk(txp); + act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp); /* Mode register MR0[A12] is '1' - fast exit */ pre_pd_exit_mclk = act_pd_exit_mclk; taxpd_mclk = 1; @@ -424,11 +426,12 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, #endif /* !defined(CONFIG_SYS_FSL_DDR1) */ /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ -static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency, - unsigned int additive_latency) +static void set_timing_cfg_3(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency, + unsigned int additive_latency) { /* Extended precharge to activate interval (tRP) */ unsigned int ext_pretoact = 0; @@ -447,18 +450,18 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, /* Control Adjust */ unsigned int cntl_adj = 0; - ext_pretoact = picos_to_mclk(common_dimm->trp_ps) >> 4; - ext_acttopre = picos_to_mclk(common_dimm->tras_ps) >> 4; - ext_acttorw = picos_to_mclk(common_dimm->trcd_ps) >> 4; + ext_pretoact = picos_to_mclk(ctrl_num, common_dimm->trp_ps) >> 4; + ext_acttopre = picos_to_mclk(ctrl_num, common_dimm->tras_ps) >> 4; + ext_acttorw = picos_to_mclk(ctrl_num, common_dimm->trcd_ps) >> 4; ext_caslat = (2 * cas_latency - 1) >> 4; ext_add_lat = additive_latency >> 4; #ifdef CONFIG_SYS_FSL_DDR4 - ext_refrec = (picos_to_mclk(common_dimm->trfc1_ps) - 8) >> 4; + ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8) >> 4; #else - ext_refrec = (picos_to_mclk(common_dimm->trfc_ps) - 8) >> 4; + ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8) >> 4; /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */ #endif - ext_wrrec = (picos_to_mclk(common_dimm->twr_ps) + + ext_wrrec = (picos_to_mclk(ctrl_num, common_dimm->twr_ps) + (popts->otf_burst_chop_en ? 2 : 0)) >> 4; ddr->timing_cfg_3 = (0 @@ -475,10 +478,11 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, } /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */ -static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency) +static void set_timing_cfg_1(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency) { /* Precharge-to-activate interval (tRP) */ unsigned char pretoact_mclk; @@ -510,9 +514,9 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0}; #endif - pretoact_mclk = picos_to_mclk(common_dimm->trp_ps); - acttopre_mclk = picos_to_mclk(common_dimm->tras_ps); - acttorw_mclk = picos_to_mclk(common_dimm->trcd_ps); + pretoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trp_ps); + acttopre_mclk = picos_to_mclk(ctrl_num, common_dimm->tras_ps); + acttorw_mclk = picos_to_mclk(ctrl_num, common_dimm->trcd_ps); /* * Translate CAS Latency to a DDR controller field value: @@ -547,19 +551,19 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, #endif #ifdef CONFIG_SYS_FSL_DDR4 - refrec_ctrl = picos_to_mclk(common_dimm->trfc1_ps) - 8; - wrrec_mclk = picos_to_mclk(common_dimm->twr_ps); - acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4U); - wrtord_mclk = max(2U, picos_to_mclk(2500)); + refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8; + wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps); + acttoact_mclk = max(picos_to_mclk(ctrl_num, common_dimm->trrds_ps), 4U); + wrtord_mclk = max(2U, picos_to_mclk(ctrl_num, 2500)); if ((wrrec_mclk < 1) || (wrrec_mclk > 24)) printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk); else wrrec_mclk = wrrec_table[wrrec_mclk - 1]; #else - refrec_ctrl = picos_to_mclk(common_dimm->trfc_ps) - 8; - wrrec_mclk = picos_to_mclk(common_dimm->twr_ps); - acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps); - wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps); + refrec_ctrl = picos_to_mclk(ctrl_num, common_dimm->trfc_ps) - 8; + wrrec_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps); + acttoact_mclk = picos_to_mclk(ctrl_num, common_dimm->trrd_ps); + wrtord_mclk = picos_to_mclk(ctrl_num, common_dimm->twtr_ps); if ((wrrec_mclk < 1) || (wrrec_mclk > 16)) printf("Error: WRREC doesn't support %d clocks\n", wrrec_mclk); else @@ -602,11 +606,12 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, } /* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */ -static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency, - unsigned int additive_latency) +static void set_timing_cfg_2(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency, + unsigned int additive_latency) { /* Additive latency */ unsigned char add_lat_mclk; @@ -623,7 +628,7 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, /* Window for four activates (tFAW) */ unsigned short four_act; #ifdef CONFIG_SYS_FSL_DDR3 - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); #endif /* FIXME add check that this must be less than acttorw_mclk */ @@ -641,13 +646,13 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, #elif defined(CONFIG_SYS_FSL_DDR2) wr_lat = cas_latency - 1; #else - wr_lat = compute_cas_write_latency(); + wr_lat = compute_cas_write_latency(ctrl_num); #endif #ifdef CONFIG_SYS_FSL_DDR4 - rd_to_pre = picos_to_mclk(7500); + rd_to_pre = picos_to_mclk(ctrl_num, 7500); #else - rd_to_pre = picos_to_mclk(common_dimm->trtp_ps); + rd_to_pre = picos_to_mclk(ctrl_num, common_dimm->trtp_ps); #endif /* * JEDEC has some min requirements for tRTP @@ -665,19 +670,20 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, wr_data_delay = popts->write_data_delay; #ifdef CONFIG_SYS_FSL_DDR4 cpo = 0; - cke_pls = max(3U, picos_to_mclk(5000)); + cke_pls = max(3U, picos_to_mclk(ctrl_num, 5000)); #elif defined(CONFIG_SYS_FSL_DDR3) /* * cke pulse = max(3nCK, 7.5ns) for DDR3-800 * max(3nCK, 5.625ns) for DDR3-1066, 1333 * max(3nCK, 5ns) for DDR3-1600, 1866, 2133 */ - cke_pls = max(3U, picos_to_mclk(mclk_ps > 1870 ? 7500 : - (mclk_ps > 1245 ? 5625 : 5000))); + cke_pls = max(3U, picos_to_mclk(ctrl_num, mclk_ps > 1870 ? 7500 : + (mclk_ps > 1245 ? 5625 : 5000))); #else cke_pls = FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR; #endif - four_act = picos_to_mclk(popts->tfaw_window_four_activates_ps); + four_act = picos_to_mclk(ctrl_num, + popts->tfaw_window_four_activates_ps); ddr->timing_cfg_2 = (0 | ((add_lat_mclk & 0xf) << 28) @@ -818,7 +824,8 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, } /* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */ -static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const unsigned int unq_mrs_en) { @@ -865,7 +872,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, #endif #if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7) - slow = get_ddr_freq(0) < 1249000000; + slow = get_ddr_freq(ctrl_num) < 1249000000; #endif if (popts->registered_dimm_en) { @@ -915,7 +922,8 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, #ifdef CONFIG_SYS_FSL_DDR4 /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */ -static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode_2(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, const unsigned int unq_mrs_en) @@ -926,10 +934,10 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, unsigned int wr_crc = 0; /* Disable */ unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */ unsigned int srt = 0; /* self-refresh temerature, normal range */ - unsigned int cwl = compute_cas_write_latency() - 9; + unsigned int cwl = compute_cas_write_latency(ctrl_num) - 9; unsigned int mpr = 0; /* serial */ unsigned int wc_lat; - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); if (popts->rtt_override) rtt_wr = popts->rtt_wr_override_value; @@ -1002,7 +1010,8 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, } #elif defined(CONFIG_SYS_FSL_DDR3) /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */ -static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode_2(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, const unsigned int unq_mrs_en) @@ -1013,7 +1022,7 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */ unsigned int srt = 0; /* self-refresh temerature, normal range */ unsigned int asr = 0; /* auto self-refresh disable */ - unsigned int cwl = compute_cas_write_latency() - 5; + unsigned int cwl = compute_cas_write_latency(ctrl_num) - 5; unsigned int pasr = 0; /* partial array self refresh disable */ if (popts->rtt_override) @@ -1077,7 +1086,8 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, #else /* for DDR2 and DDR1 */ /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */ -static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode_2(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, const unsigned int unq_mrs_en) @@ -1144,7 +1154,8 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, } /* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */ -static void set_ddr_sdram_mode_10(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode_10(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, const unsigned int unq_mrs_en) @@ -1152,7 +1163,7 @@ static void set_ddr_sdram_mode_10(fsl_ddr_cfg_regs_t *ddr, int i; unsigned short esdmode6 = 0; /* Extended SDRAM mode 6 */ unsigned short esdmode7 = 0; /* Extended SDRAM mode 7 */ - unsigned int tccdl_min = picos_to_mclk(common_dimm->tccdl_ps); + unsigned int tccdl_min = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps); esdmode6 = ((tccdl_min - 4) & 0x7) << 10; @@ -1196,14 +1207,15 @@ static void set_ddr_sdram_mode_10(fsl_ddr_cfg_regs_t *ddr, #endif /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */ -static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm) +static void set_ddr_sdram_interval(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm) { unsigned int refint; /* Refresh interval */ unsigned int bstopre; /* Precharge interval */ - refint = picos_to_mclk(common_dimm->refresh_rate_ps); + refint = picos_to_mclk(ctrl_num, common_dimm->refresh_rate_ps); bstopre = popts->bstopre; @@ -1217,7 +1229,8 @@ static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr, #ifdef CONFIG_SYS_FSL_DDR4 /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ -static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, unsigned int cas_latency, @@ -1292,7 +1305,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, * 1=fast exit DLL on (tXP) */ - wr_mclk = picos_to_mclk(common_dimm->twr_ps); + wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps); if (wr_mclk <= 24) { wr = wr_table[wr_mclk - 10]; } else { @@ -1387,7 +1400,8 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, #elif defined(CONFIG_SYS_FSL_DDR3) /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ -static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, unsigned int cas_latency, @@ -1466,7 +1480,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, */ dll_on = 1; - wr_mclk = picos_to_mclk(common_dimm->twr_ps); + wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps); if (wr_mclk <= 16) { wr = wr_table[wr_mclk - 5]; } else { @@ -1582,7 +1596,8 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, #else /* !CONFIG_SYS_FSL_DDR3 */ /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ -static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, +static void set_ddr_sdram_mode(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, unsigned int cas_latency, @@ -1654,7 +1669,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, #if defined(CONFIG_SYS_FSL_DDR1) wr = 0; /* Historical */ #elif defined(CONFIG_SYS_FSL_DDR2) - wr = picos_to_mclk(common_dimm->twr_ps); + wr = picos_to_mclk(ctrl_num, common_dimm->twr_ps); #endif dll_res = 0; mode = 0; @@ -1842,15 +1857,16 @@ static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr) debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6); } -static void set_timing_cfg_7(fsl_ddr_cfg_regs_t *ddr, - const common_timing_params_t *common_dimm) +static void set_timing_cfg_7(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, + const common_timing_params_t *common_dimm) { unsigned int txpr, tcksre, tcksrx; unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd; - txpr = max(5U, picos_to_mclk(common_dimm->trfc1_ps + 10000)); - tcksre = max(5U, picos_to_mclk(10000)); - tcksrx = max(5U, picos_to_mclk(10000)); + txpr = max(5U, picos_to_mclk(ctrl_num, common_dimm->trfc1_ps + 10000)); + tcksre = max(5U, picos_to_mclk(ctrl_num, 10000)); + tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000)); par_lat = 0; cs_to_cmd = 0; @@ -1883,14 +1899,15 @@ static void set_timing_cfg_7(fsl_ddr_cfg_regs_t *ddr, debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7); } -static void set_timing_cfg_8(fsl_ddr_cfg_regs_t *ddr, +static void set_timing_cfg_8(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts, const common_timing_params_t *common_dimm, unsigned int cas_latency) { unsigned int rwt_bg, wrt_bg, rrt_bg, wwt_bg; unsigned int acttoact_bg, wrtord_bg, pre_all_rec; - unsigned int tccdl = picos_to_mclk(common_dimm->tccdl_ps); + unsigned int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps); unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) + ((ddr->timing_cfg_2 & 0x00040000) >> 14); @@ -1914,8 +1931,8 @@ static void set_timing_cfg_8(fsl_ddr_cfg_regs_t *ddr, wwt_bg = tccdl - 4; } - acttoact_bg = picos_to_mclk(common_dimm->trrdl_ps); - wrtord_bg = max(4U, picos_to_mclk(7500)); + acttoact_bg = picos_to_mclk(ctrl_num, common_dimm->trrdl_ps); + wrtord_bg = max(4U, picos_to_mclk(ctrl_num, 7500)); if (popts->otf_burst_chop_en) wrtord_bg += 2; @@ -2147,7 +2164,8 @@ check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) } unsigned int -compute_fsl_memctl_config_regs(const memctl_options_t *popts, +compute_fsl_memctl_config_regs(const unsigned int ctrl_num, + const memctl_options_t *popts, fsl_ddr_cfg_regs_t *ddr, const common_timing_params_t *common_dimm, const dimm_params_t *dimm_params, @@ -2319,14 +2337,14 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, set_ddr_eor(ddr, popts); #if !defined(CONFIG_SYS_FSL_DDR1) - set_timing_cfg_0(ddr, popts, dimm_params); + set_timing_cfg_0(ctrl_num, ddr, popts, dimm_params); #endif - set_timing_cfg_3(ddr, popts, common_dimm, cas_latency, + set_timing_cfg_3(ctrl_num, ddr, popts, common_dimm, cas_latency, additive_latency); - set_timing_cfg_1(ddr, popts, common_dimm, cas_latency); - set_timing_cfg_2(ddr, popts, common_dimm, - cas_latency, additive_latency); + set_timing_cfg_1(ctrl_num, ddr, popts, common_dimm, cas_latency); + set_timing_cfg_2(ctrl_num, ddr, popts, common_dimm, + cas_latency, additive_latency); set_ddr_cdr1(ddr, popts); set_ddr_cdr2(ddr, popts); @@ -2338,15 +2356,15 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, if ((ip_rev > 0x40700) && (popts->cswl_override != 0)) ddr->debug[18] = popts->cswl_override; - set_ddr_sdram_cfg_2(ddr, popts, unq_mrs_en); - set_ddr_sdram_mode(ddr, popts, common_dimm, - cas_latency, additive_latency, unq_mrs_en); - set_ddr_sdram_mode_2(ddr, popts, common_dimm, unq_mrs_en); + set_ddr_sdram_cfg_2(ctrl_num, ddr, popts, unq_mrs_en); + set_ddr_sdram_mode(ctrl_num, ddr, popts, common_dimm, + cas_latency, additive_latency, unq_mrs_en); + set_ddr_sdram_mode_2(ctrl_num, ddr, popts, common_dimm, unq_mrs_en); #ifdef CONFIG_SYS_FSL_DDR4 set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en); - set_ddr_sdram_mode_10(ddr, popts, common_dimm, unq_mrs_en); + set_ddr_sdram_mode_10(ctrl_num, ddr, popts, common_dimm, unq_mrs_en); #endif - set_ddr_sdram_interval(ddr, popts, common_dimm); + set_ddr_sdram_interval(ctrl_num, ddr, popts, common_dimm); set_ddr_data_init(ddr); set_ddr_sdram_clk_cntl(ddr, popts); set_ddr_init_addr(ddr); @@ -2356,8 +2374,8 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, #ifdef CONFIG_SYS_FSL_DDR4 set_ddr_sdram_cfg_3(ddr, popts); set_timing_cfg_6(ddr); - set_timing_cfg_7(ddr, common_dimm); - set_timing_cfg_8(ddr, popts, common_dimm, cas_latency); + set_timing_cfg_7(ctrl_num, ddr, common_dimm); + set_timing_cfg_8(ctrl_num, ddr, popts, common_dimm, cas_latency); set_timing_cfg_9(ddr); set_ddr_dq_mapping(ddr, dimm_params); #endif diff --git a/drivers/ddr/fsl/ddr1_dimm_params.c b/drivers/ddr/fsl/ddr1_dimm_params.c index 7df27b9..7f1c3af 100644 --- a/drivers/ddr/fsl/ddr1_dimm_params.c +++ b/drivers/ddr/fsl/ddr1_dimm_params.c @@ -228,10 +228,10 @@ compute_derated_DDR1_CAS_latency(unsigned int mclk_ps) * * FIXME: use #define for the retvals */ -unsigned int -ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) +unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, + const ddr1_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) { unsigned int retval; @@ -311,16 +311,16 @@ ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd, & ~(1 << pdimm->caslat_x_minus_1)); /* Compute CAS latencies below that defined by SPD */ - pdimm->caslat_lowest_derated - = compute_derated_DDR1_CAS_latency(get_memory_clk_period_ps()); + pdimm->caslat_lowest_derated = compute_derated_DDR1_CAS_latency( + get_memory_clk_period_ps(ctrl_num)); /* Compute timing parameters */ pdimm->trcd_ps = spd->trcd * 250; pdimm->trp_ps = spd->trp * 250; pdimm->tras_ps = spd->tras * 1000; - pdimm->twr_ps = mclk_to_picos(3); - pdimm->twtr_ps = mclk_to_picos(1); + pdimm->twr_ps = mclk_to_picos(ctrl_num, 3); + pdimm->twtr_ps = mclk_to_picos(ctrl_num, 1); pdimm->trfc_ps = compute_trfc_ps_from_spd(0, spd->trfc); pdimm->trrd_ps = spd->trrd * 250; @@ -335,7 +335,7 @@ ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd, pdimm->tdh_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold); - pdimm->trtp_ps = mclk_to_picos(2); /* By the book. */ + pdimm->trtp_ps = mclk_to_picos(ctrl_num, 2); /* By the book. */ pdimm->tdqsq_max_ps = spd->tdqsq * 10; pdimm->tqhs_ps = spd->tqhs * 10; diff --git a/drivers/ddr/fsl/ddr2_dimm_params.c b/drivers/ddr/fsl/ddr2_dimm_params.c index d865df7..49cc1a0 100644 --- a/drivers/ddr/fsl/ddr2_dimm_params.c +++ b/drivers/ddr/fsl/ddr2_dimm_params.c @@ -211,10 +211,10 @@ compute_derated_DDR2_CAS_latency(unsigned int mclk_ps) * * FIXME: use #define for the retvals */ -unsigned int -ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) +unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, + const ddr2_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) { unsigned int retval; @@ -310,8 +310,8 @@ ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd, & ~(1 << pdimm->caslat_x_minus_1)); /* Compute CAS latencies below that defined by SPD */ - pdimm->caslat_lowest_derated - = compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps()); + pdimm->caslat_lowest_derated = compute_derated_DDR2_CAS_latency( + get_memory_clk_period_ps(ctrl_num)); /* Compute timing parameters */ pdimm->trcd_ps = spd->trcd * 250; diff --git a/drivers/ddr/fsl/ddr3_dimm_params.c b/drivers/ddr/fsl/ddr3_dimm_params.c index a4b8c10..6917715 100644 --- a/drivers/ddr/fsl/ddr3_dimm_params.c +++ b/drivers/ddr/fsl/ddr3_dimm_params.c @@ -83,10 +83,10 @@ compute_ranksize(const ddr3_spd_eeprom_t *spd) * Writes the results to the dimm_params_t structure pointed by pdimm. * */ -unsigned int -ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) +unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, + const ddr3_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) { unsigned int retval; unsigned int mtb_ps; diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index aaddc8f..bbfb4ee 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -119,10 +119,10 @@ compute_ranksize(const struct ddr4_spd_eeprom_s *spd) * Writes the results to the dimm_params_t structure pointed by pdimm. * */ -unsigned int -ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) +unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, + const generic_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) { unsigned int retval; int i; diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 9cca4a0..d9fce7d 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -287,7 +287,7 @@ step2: bus_width = 3 - ((ddr_in32(&ddr->sdram_cfg) & SDRAM_CFG_DBW_MASK) >> SDRAM_CFG_DBW_SHIFT); timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 / - (get_ddr_freq(0) >> 20)) << 2; + (get_ddr_freq(ctrl_num) >> 20)) << 2; total_gb_size_per_controller >>= 4; /* shift down to gb size */ debug("total %d GB\n", total_gb_size_per_controller); debug("Need to wait up to %d * 10ms\n", timeout); diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c index 73db444..b295344 100644 --- a/drivers/ddr/fsl/lc_common_dimm_params.c +++ b/drivers/ddr/fsl/lc_common_dimm_params.c @@ -13,7 +13,8 @@ #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) static unsigned int -compute_cas_latency(const dimm_params_t *dimm_params, +compute_cas_latency(const unsigned int ctrl_num, + const dimm_params_t *dimm_params, common_timing_params_t *outpdimm, unsigned int number_of_dimms) { @@ -22,7 +23,7 @@ compute_cas_latency(const dimm_params_t *dimm_params, unsigned int caslat_actual; unsigned int retry = 16; unsigned int tmp; - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); #ifdef CONFIG_SYS_FSL_DDR3 const unsigned int taamax = 20000; #else @@ -72,12 +73,13 @@ compute_cas_latency(const dimm_params_t *dimm_params, } #else /* for DDR1 and DDR2 */ static unsigned int -compute_cas_latency(const dimm_params_t *dimm_params, +compute_cas_latency(const unsigned int ctrl_num, + const dimm_params_t *dimm_params, common_timing_params_t *outpdimm, unsigned int number_of_dimms) { int i; - const unsigned int mclk_ps = get_memory_clk_period_ps(); + const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); unsigned int lowest_good_caslat; unsigned int not_ok; unsigned int temp1, temp2; @@ -212,7 +214,8 @@ compute_cas_latency(const dimm_params_t *dimm_params, * by dimm_params. */ unsigned int -compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, +compute_lowest_common_dimm_parameters(const unsigned int ctrl_num, + const dimm_params_t *dimm_params, common_timing_params_t *outpdimm, const unsigned int number_of_dimms) { @@ -442,7 +445,8 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, printf("ERROR: Mix different RDIMM detected!\n"); /* calculate cas latency for all DDR types */ - if (compute_cas_latency(dimm_params, outpdimm, number_of_dimms)) + if (compute_cas_latency(ctrl_num, dimm_params, + outpdimm, number_of_dimms)) return 1; /* Determine if all DIMMs ECC capable. */ @@ -518,11 +522,12 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, #if defined(CONFIG_SYS_FSL_DDR2) if ((outpdimm->lowest_common_spd_caslat < 4) && - (picos_to_mclk(trcd_ps) > outpdimm->lowest_common_spd_caslat)) { - additive_latency = picos_to_mclk(trcd_ps) - + (picos_to_mclk(ctrl_num, trcd_ps) > + outpdimm->lowest_common_spd_caslat)) { + additive_latency = picos_to_mclk(ctrl_num, trcd_ps) - outpdimm->lowest_common_spd_caslat; - if (mclk_to_picos(additive_latency) > trcd_ps) { - additive_latency = picos_to_mclk(trcd_ps); + if (mclk_to_picos(ctrl_num, additive_latency) > trcd_ps) { + additive_latency = picos_to_mclk(ctrl_num, trcd_ps); debug("setting additive_latency to %u because it was " " greater than tRCD_ps\n", additive_latency); } @@ -534,7 +539,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, * * AL <= tRCD(min) */ - if (mclk_to_picos(additive_latency) > trcd_ps) { + if (mclk_to_picos(ctrl_num, additive_latency) > trcd_ps) { printf("Error: invalid additive latency exceeds tRCD(min).\n"); return 1; } diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index 6f291eb..f49939b 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -450,7 +450,8 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, &(pinfo->spd_installed_dimms[i][j]); dimm_params_t *pdimm = &(pinfo->dimm_params[i][j]); - retval = compute_dimm_parameters(spd, pdimm, i); + retval = compute_dimm_parameters( + i, spd, pdimm, j); #ifdef CONFIG_SYS_DDR_RAW_TIMING if (!i && !j && retval) { printf("SPD error on controller %d! " @@ -507,10 +508,11 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, for (i = first_ctrl; i <= last_ctrl; i++) { debug("Computing lowest common DIMM" " parameters for memctl=%u\n", i); - compute_lowest_common_dimm_parameters( - pinfo->dimm_params[i], - &timing_params[i], - CONFIG_DIMM_SLOTS_PER_CTLR); + compute_lowest_common_dimm_parameters + (i, + pinfo->dimm_params[i], + &timing_params[i], + CONFIG_DIMM_SLOTS_PER_CTLR); } case STEP_GATHER_OPTS: @@ -562,12 +564,13 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, continue; } - compute_fsl_memctl_config_regs( - &pinfo->memctl_opts[i], - &ddr_reg[i], &timing_params[i], - pinfo->dimm_params[i], - dbw_capacity_adjust[i], - size_only); + compute_fsl_memctl_config_regs + (i, + &pinfo->memctl_opts[i], + &ddr_reg[i], &timing_params[i], + pinfo->dimm_params[i], + dbw_capacity_adjust[i], + size_only); } default: diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c index 8f4d01a..6752d4d 100644 --- a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c +++ b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c @@ -426,7 +426,7 @@ step2: bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK) >> SDRAM_CFG_DBW_SHIFT); timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 / - (get_ddr_freq(0) >> 20)) << 1; + (get_ddr_freq(ctrl_num) >> 20)) << 1; #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 timeout_save = timeout; #endif @@ -538,12 +538,14 @@ step2: case 1: out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds); break; +#if CONFIG_CHIP_SELECTS_PER_CTRL > 2 case 2: out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds); break; case 3: out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds); break; +#endif } clrbits_be32(&ddr->sdram_cfg, 0x2); } diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 6d098d1..5beb11b 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -732,7 +732,7 @@ unsigned int populate_memctl_options(int all_dimms_registered, #endif /* Global Timing Parameters. */ - debug("mclk_ps = %u ps\n", get_memory_clk_period_ps()); + debug("mclk_ps = %u ps\n", get_memory_clk_period_ps(ctrl_num)); /* Pick a caslat override. */ popts->cas_latency_override = 0; @@ -785,7 +785,7 @@ unsigned int populate_memctl_options(int all_dimms_registered, * FIXME: width, was considering looking at pdimm->primary_sdram_width */ #if defined(CONFIG_SYS_FSL_DDR1) - popts->tfaw_window_four_activates_ps = mclk_to_picos(1); + popts->tfaw_window_four_activates_ps = mclk_to_picos(ctrl_num, 1); #elif defined(CONFIG_SYS_FSL_DDR2) /* @@ -1036,7 +1036,7 @@ done: if (pdimm[0].n_ranks == 4) popts->quad_rank_present = 1; - ddr_freq = get_ddr_freq(0) / 1000000; + ddr_freq = get_ddr_freq(ctrl_num) / 1000000; if (popts->registered_dimm_en) { popts->rcw_override = 1; popts->rcw_1 = 0x000a5a00; diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c index 58b519b..ad569de 100644 --- a/drivers/ddr/fsl/util.c +++ b/drivers/ddr/fsl/util.c @@ -43,9 +43,9 @@ u32 fsl_ddr_get_version(void) * propagation, compute a suitably rounded mclk_ps to compute * a working memory controller configuration. */ -unsigned int get_memory_clk_period_ps(void) +unsigned int get_memory_clk_period_ps(const unsigned int ctrl_num) { - unsigned int data_rate = get_ddr_freq(0); + unsigned int data_rate = get_ddr_freq(ctrl_num); unsigned int result; /* Round to nearest 10ps, being careful about 64-bit multiply/divide */ @@ -59,10 +59,10 @@ unsigned int get_memory_clk_period_ps(void) } /* Convert picoseconds into DRAM clock cycles (rounding up if needed). */ -unsigned int picos_to_mclk(unsigned int picos) +unsigned int picos_to_mclk(const unsigned int ctrl_num, unsigned int picos) { unsigned long long clks, clks_rem; - unsigned long data_rate = get_ddr_freq(0); + unsigned long data_rate = get_ddr_freq(ctrl_num); /* Short circuit for zero picos */ if (!picos) @@ -88,9 +88,9 @@ unsigned int picos_to_mclk(unsigned int picos) return (unsigned int) clks; } -unsigned int mclk_to_picos(unsigned int mclk) +unsigned int mclk_to_picos(const unsigned int ctrl_num, unsigned int mclk) { - return get_memory_clk_period_ps() * mclk; + return get_memory_clk_period_ps(ctrl_num) * mclk; } #ifdef CONFIG_PPC -- cgit v1.1 From dc1437afd761e83497d94eae0d6dcc2c2ff4711f Mon Sep 17 00:00:00 2001 From: York Sun Date: Tue, 6 Jan 2015 13:18:52 -0800 Subject: driver/ddr/fsl: Fix a typo in timing_cfg_8 calculation wwt_bg should match rrt_bg. It was a typo in driver. Signed-off-by: York Sun --- drivers/ddr/fsl/ctrl_regs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 713c3ed..690e73d 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -1928,7 +1928,7 @@ static void set_timing_cfg_8(const unsigned int ctrl_num, wwt_bg = tccdl - 4; } else { rrt_bg = tccdl - 2; - wwt_bg = tccdl - 4; + wwt_bg = tccdl - 2; } acttoact_bg = picos_to_mclk(ctrl_num, common_dimm->trrdl_ps); -- cgit v1.1 From e32d59a2fa6446b64167bba31c0dd40eb023e8bb Mon Sep 17 00:00:00 2001 From: York Sun Date: Tue, 6 Jan 2015 13:18:55 -0800 Subject: driver/ddr/fsl: Add sync of refresh Add sync of refresh for multiple DDR controllers. DDRC initialization needs to complete first. Code is re-ordered to keep refresh close. Signed-off-by: York Sun --- drivers/ddr/fsl/main.c | 4 ++++ drivers/ddr/fsl/util.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) (limited to 'drivers') diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index f49939b..b72b242 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -692,6 +692,10 @@ phys_size_t __fsl_ddr_sdram(fsl_ddr_info_t *pinfo) } } +#ifdef CONFIG_FSL_DDR_SYNC_REFRESH + fsl_ddr_sync_memctl_refresh(first_ctrl, last_ctrl); +#endif + #ifdef CONFIG_PPC /* program LAWs */ for (i = first_ctrl; i <= last_ctrl; i++) { diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c index ad569de..664081b 100644 --- a/drivers/ddr/fsl/util.c +++ b/drivers/ddr/fsl/util.c @@ -308,3 +308,58 @@ void board_add_ram_info(int use_default) { detail_board_ddr_info(); } + +#ifdef CONFIG_FSL_DDR_SYNC_REFRESH +#define DDRC_DEBUG20_INIT_DONE 0x80000000 +#define DDRC_DEBUG2_RF 0x00000040 +void fsl_ddr_sync_memctl_refresh(unsigned int first_ctrl, + unsigned int last_ctrl) +{ + unsigned int i; + u32 ddrc_debug20; + u32 ddrc_debug2[CONFIG_NUM_DDR_CONTROLLERS] = {}; + u32 *ddrc_debug2_p[CONFIG_NUM_DDR_CONTROLLERS] = {}; + struct ccsr_ddr __iomem *ddr; + + for (i = first_ctrl; i <= last_ctrl; i++) { + switch (i) { + case 0: + ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + break; +#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) + case 1: + ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) + case 2: + ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) + case 3: + ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; + break; +#endif + default: + printf("%s unexpected ctrl = %u\n", __func__, i); + return; + } + ddrc_debug20 = ddr_in32(&ddr->debug[19]); + ddrc_debug2_p[i] = &ddr->debug[1]; + while (!(ddrc_debug20 & DDRC_DEBUG20_INIT_DONE)) { + /* keep polling until DDRC init is done */ + udelay(100); + ddrc_debug20 = ddr_in32(&ddr->debug[19]); + } + ddrc_debug2[i] = ddr_in32(&ddr->debug[1]) | DDRC_DEBUG2_RF; + } + /* + * Sync refresh + * This is put together to make sure the refresh reqeusts are sent + * closely to each other. + */ + for (i = first_ctrl; i <= last_ctrl; i++) + ddr_out32(ddrc_debug2_p[i], ddrc_debug2[i]); +} +#endif /* CONFIG_FSL_DDR_SYNC_REFRESH */ -- cgit v1.1 From 7b3bd9a7988a8b4c8ba22a52b4927e8e59819b12 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Tue, 6 Jan 2015 13:19:02 -0800 Subject: drivers/mc: Migrated MC Flibs to 0.5.2 Upgrade Manage Complex (MC) flib API to 0.5.2. Rename directory fsl_mc to fsl-mc. Change the fsl-mc node in Linux device tree from "fsl,dprcr" to "fsl-mc". Print MC version info when appropriate. Signed-off-by: J. German Rivera Signed-off-by: Lijun Pan Reviewed-by: York Sun --- drivers/net/Makefile | 2 +- drivers/net/fsl-mc/Makefile | 10 ++ drivers/net/fsl-mc/dpmng.c | 91 +++++++++++ drivers/net/fsl-mc/fsl_dpmng_cmd.h | 49 ++++++ drivers/net/fsl-mc/mc.c | 310 +++++++++++++++++++++++++++++++++++++ drivers/net/fsl-mc/mc_sys.c | 63 ++++++++ drivers/net/fsl_mc/Makefile | 8 - drivers/net/fsl_mc/mc.c | 266 ------------------------------- 8 files changed, 524 insertions(+), 275 deletions(-) create mode 100644 drivers/net/fsl-mc/Makefile create mode 100644 drivers/net/fsl-mc/dpmng.c create mode 100644 drivers/net/fsl-mc/fsl_dpmng_cmd.h create mode 100644 drivers/net/fsl-mc/mc.c create mode 100644 drivers/net/fsl-mc/mc_sys.c delete mode 100644 drivers/net/fsl_mc/Makefile delete mode 100644 drivers/net/fsl_mc/mc.c (limited to 'drivers') diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 46c4ac6..6e1ccdb 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -65,5 +65,5 @@ obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \ xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o -obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/ +obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/ obj-$(CONFIG_VSC9953) += vsc9953.o diff --git a/drivers/net/fsl-mc/Makefile b/drivers/net/fsl-mc/Makefile new file mode 100644 index 0000000..206ac6b --- /dev/null +++ b/drivers/net/fsl-mc/Makefile @@ -0,0 +1,10 @@ +# +# Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Layerscape MC driver +obj-y += mc.o \ + mc_sys.o \ + dpmng.o diff --git a/drivers/net/fsl-mc/dpmng.c b/drivers/net/fsl-mc/dpmng.c new file mode 100644 index 0000000..cc14c7b --- /dev/null +++ b/drivers/net/fsl-mc/dpmng.c @@ -0,0 +1,91 @@ +/* Copyright 2014 Freescale Semiconductor Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include "fsl_dpmng_cmd.h" + +int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, + MC_CMD_PRI_LOW, 0); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPMNG_RSP_GET_VERSION(cmd, mc_ver_info); + + return 0; +} + +int dpmng_reset_aiop(struct fsl_mc_io *mc_io, int container_id, + int aiop_tile_id) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_AIOP, + MC_CMD_PRI_LOW, 0); + DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpmng_load_aiop(struct fsl_mc_io *mc_io, + int container_id, + int aiop_tile_id, + uint64_t img_iova, + uint32_t img_size) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_LOAD_AIOP, + MC_CMD_PRI_LOW, + 0); + DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size, + img_iova); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpmng_run_aiop(struct fsl_mc_io *mc_io, + int container_id, + int aiop_tile_id, + const struct dpmng_aiop_run_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RUN_AIOP, + MC_CMD_PRI_LOW, + 0); + DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpmng_reset_mc_portal(struct fsl_mc_io *mc_io) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_MC_PORTAL, + MC_CMD_PRI_LOW, + 0); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} diff --git a/drivers/net/fsl-mc/fsl_dpmng_cmd.h b/drivers/net/fsl-mc/fsl_dpmng_cmd.h new file mode 100644 index 0000000..c9fe021 --- /dev/null +++ b/drivers/net/fsl-mc/fsl_dpmng_cmd.h @@ -0,0 +1,49 @@ +/* Copyright 2014 Freescale Semiconductor Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef __FSL_DPMNG_CMD_H +#define __FSL_DPMNG_CMD_H + +/* Command IDs */ +#define DPMNG_CMDID_GET_VERSION 0x831 +#define DPMNG_CMDID_RESET_AIOP 0x832 +#define DPMNG_CMDID_LOAD_AIOP 0x833 +#define DPMNG_CMDID_RUN_AIOP 0x834 +#define DPMNG_CMDID_RESET_MC_PORTAL 0x835 + +/* cmd, param, offset, width, type, arg_name */ +#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mc_ver_info->revision); \ + MC_RSP_OP(cmd, 0, 32, 32, uint32_t, mc_ver_info->major); \ + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size, \ + img_iova) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \ + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, img_size); \ + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, img_iova); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \ + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->cores_mask); \ + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \ +} while (0) + +#endif /* __FSL_DPMNG_CMD_H */ diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c new file mode 100644 index 0000000..74b0085 --- /dev/null +++ b/drivers/net/fsl-mc/mc.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; +static int mc_boot_status; + +/** + * Copying MC firmware or DPL image to DDR + */ +static int mc_copy_image(const char *title, + u64 image_addr, u32 image_size, u64 mc_ram_addr) +{ + debug("%s copied to address %p\n", title, (void *)mc_ram_addr); + memcpy((void *)mc_ram_addr, (void *)image_addr, image_size); + return 0; +} + +/** + * MC firmware FIT image parser checks if the image is in FIT + * format, verifies integrity of the image and calculates + * raw image address and size values. + * Returns 0 on success and a negative errno on error. + * task fail. + **/ +int parse_mc_firmware_fit_image(const void **raw_image_addr, + size_t *raw_image_size) +{ + int format; + void *fit_hdr; + int node_offset; + const void *data; + size_t size; + const char *uname = "firmware"; + + /* Check if the image is in NOR flash */ +#ifdef CONFIG_SYS_LS_MC_FW_IN_NOR + fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR; +#else +#error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined" +#endif + + /* Check if Image is in FIT format */ + format = genimg_get_format(fit_hdr); + + if (format != IMAGE_FORMAT_FIT) { + printf("fsl-mc: ERROR: Bad firmware image (not a FIT image)\n"); + return -EINVAL; + } + + if (!fit_check_format(fit_hdr)) { + printf("fsl-mc: ERROR: Bad firmware image (bad FIT header)\n"); + return -EINVAL; + } + + node_offset = fit_image_get_node(fit_hdr, uname); + + if (node_offset < 0) { + printf("fsl-mc: ERROR: Bad firmware image (missing subimage)\n"); + return -ENOENT; + } + + /* Verify MC firmware image */ + if (!(fit_image_verify(fit_hdr, node_offset))) { + printf("fsl-mc: ERROR: Bad firmware image (bad CRC)\n"); + return -EINVAL; + } + + /* Get address and size of raw image */ + fit_image_get_data(fit_hdr, node_offset, &data, &size); + + *raw_image_addr = data; + *raw_image_size = size; + + return 0; +} + +int mc_init(bd_t *bis) +{ + int error = 0; + int timeout = 200000; + struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; + u64 mc_ram_addr; + u64 mc_dpl_offset; + u32 reg_gsr; + u32 mc_fw_boot_status; + void *dpl_fdt_hdr; + int dpl_size; + const void *raw_image_addr; + size_t raw_image_size = 0; + struct fsl_mc_io mc_io; + int portal_id; + struct mc_version mc_ver_info; + + /* + * The MC private DRAM block was already carved at the end of DRAM + * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE: + */ + if (gd->bd->bi_dram[1].start) { + mc_ram_addr = + gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size; + } else { + mc_ram_addr = + gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; + } + + /* + * Management Complex cores should be held at reset out of POR. + * U-boot should be the first software to touch MC. To be safe, + * we reset all cores again by setting GCR1 to 0. It doesn't do + * anything if they are held at reset. After we setup the firmware + * we kick off MC by deasserting the reset bit for core 0, and + * deasserting the reset bits for Command Portal Managers. + * The stop bits are not touched here. They are used to stop the + * cores when they are active. Setting stop bits doesn't stop the + * cores from fetching instructions when they are released from + * reset. + */ + out_le32(&mc_ccsr_regs->reg_gcr1, 0); + dmb(); + + error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size); + if (error != 0) + goto out; + /* + * Load the MC FW at the beginning of the MC private DRAM block: + */ + mc_copy_image("MC Firmware", + (u64)raw_image_addr, raw_image_size, mc_ram_addr); + + /* + * Get address and size of the DPL blob stored in flash: + */ +#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR + dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; +#else +#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" +#endif + + error = fdt_check_header(dpl_fdt_hdr); + if (error != 0) { + printf("fsl-mc: ERROR: Bad DPL image (bad header)\n"); + goto out; + } + + dpl_size = fdt_totalsize(dpl_fdt_hdr); + if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) { + printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n", + dpl_size); + error = -EINVAL; + goto out; + } + + /* + * Calculate offset in the MC private DRAM block at which the MC DPL + * blob is to be placed: + */ +#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET + BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || + CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); + + mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; +#else + mc_dpl_offset = mc_get_dram_block_size() - + roundup(CONFIG_SYS_LS_MC_DPL_MAX_LENGTH, 4096); + + if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) { + printf("%s: Invalid MC DPL offset: %llu\n", + __func__, mc_dpl_offset); + error = -EINVAL; + goto out; + } +#endif + + /* + * Load the MC DPL blob at the far end of the MC private DRAM block: + * + * TODO: Should we place the DPL at a different location to match + * assumptions of MC firmware about its memory layout? + */ + mc_copy_image("MC DPL blob", + (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset); + + debug("mc_ccsr_regs %p\n", mc_ccsr_regs); + + /* + * Tell MC where the MC Firmware image was loaded in DDR: + */ + out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr); + out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32)); + out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK); + + /* + * Tell MC where the DPL blob was loaded in DDR, by indicating + * its offset relative to the beginning of the DDR block + * allocated to the MC firmware. The MC firmware is responsible + * for checking that there is no overlap between the DPL blob + * and the runtime heap and stack of the MC firmware itself. + * + * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of + * the GSR MC CCSR register. So, this offset is assumed to be 4-byte + * aligned. + * Care must be taken not to write 1s into bits 31 and 30 of the GSR in + * this case as the SoC COP or PIC will be signaled. + */ + out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2)); + + printf("\nfsl-mc: Booting Management Complex ...\n"); + + /* + * Deassert reset and release MC core 0 to run + */ + out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); + dmb(); + debug("Polling mc_ccsr_regs->reg_gsr ...\n"); + + for (;;) { + reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); + mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); + if (mc_fw_boot_status & 0x1) + break; + + udelay(1000); /* throttle polling */ + if (timeout-- <= 0) + break; + } + + if (timeout <= 0) { + printf("fsl-mc: timeout booting management complex firmware\n"); + + /* TODO: Get an error status from an MC CCSR register */ + error = -ETIMEDOUT; + goto out; + } + + if (mc_fw_boot_status != 0x1) { + /* + * TODO: Identify critical errors from the GSR register's FS + * field and for those errors, set error to -ENODEV or other + * appropriate errno, so that the status property is set to + * failure in the fsl,dprc device tree node. + */ + printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n", + reg_gsr); + } + + /* + * TODO: need to obtain the portal_id for the root container from the + * DPL + */ + portal_id = 0; + + /* + * Check that the MC firmware is responding portal commands: + */ + mc_io.mmio_regs = SOC_MC_PORTAL_ADDR(portal_id); + debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n", + portal_id, mc_io.mmio_regs); + + error = mc_get_version(&mc_io, &mc_ver_info); + if (error != 0) { + printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n", + error); + goto out; + } + + if (MC_VER_MAJOR != mc_ver_info.major) + printf("fsl-mc: ERROR: Firmware major version mismatch (found: %d, expected: %d)\n", + mc_ver_info.major, MC_VER_MAJOR); + + if (MC_VER_MINOR != mc_ver_info.minor) + printf("fsl-mc: WARNING: Firmware minor version mismatch (found: %d, expected: %d)\n", + mc_ver_info.minor, MC_VER_MINOR); + + printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n", + mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, + mc_fw_boot_status); +out: + if (error != 0) + mc_boot_status = -error; + else + mc_boot_status = 0; + + return error; +} + +int get_mc_boot_status(void) +{ + return mc_boot_status; +} + +/** + * Return the actual size of the MC private DRAM block. + * + * NOTE: For now this function always returns the minimum required size, + * However, in the future, the actual size may be obtained from an environment + * variable. + */ +unsigned long mc_get_dram_block_size(void) +{ + return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; +} diff --git a/drivers/net/fsl-mc/mc_sys.c b/drivers/net/fsl-mc/mc_sys.c new file mode 100644 index 0000000..7c8e003 --- /dev/null +++ b/drivers/net/fsl-mc/mc_sys.c @@ -0,0 +1,63 @@ +/* + * Freescale Layerscape MC I/O wrapper + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#define MC_CMD_HDR_READ_CMDID(_hdr) \ + ((uint16_t)u64_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S)) + +/** + * mc_send_command - Send MC command and wait for response + * + * @mc_io: Pointer to MC I/O object to be used + * @cmd: MC command buffer. On input, it contains the command to send to the MC. + * On output, it contains the response from the MC if any. + * + * Depending on the sharing option specified when creating the MC portal + * wrapper, this function will use a spinlock or mutex to ensure exclusive + * access to the MC portal from the point when the command is sent until a + * response is received from the MC. + */ +int mc_send_command(struct fsl_mc_io *mc_io, + struct mc_command *cmd) +{ + enum mc_cmd_status status; + int timeout = 2000; + + mc_write_command(mc_io->mmio_regs, cmd); + + for ( ; ; ) { + status = mc_read_response(mc_io->mmio_regs, cmd); + if (status != MC_CMD_STATUS_READY) + break; + + if (--timeout == 0) { + printf("Error: Timeout waiting for MC response\n"); + return -ETIMEDOUT; + } + + udelay(500); + } + + if (status != MC_CMD_STATUS_OK) { + printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n", + mc_io->mmio_regs, + (unsigned int)MC_CMD_HDR_READ_AUTHID(cmd->header), + (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header), + (unsigned int)status); + + return -EIO; + } + + return 0; +} diff --git a/drivers/net/fsl_mc/Makefile b/drivers/net/fsl_mc/Makefile deleted file mode 100644 index 4834086..0000000 --- a/drivers/net/fsl_mc/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2014 Freescale Semiconductor, Inc. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -# Layerscape MC driver -obj-y += mc.o diff --git a/drivers/net/fsl_mc/mc.c b/drivers/net/fsl_mc/mc.c deleted file mode 100644 index df84568..0000000 --- a/drivers/net/fsl_mc/mc.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2014 Freescale Semiconductor - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; -static int mc_boot_status; - -/** - * Copying MC firmware or DPL image to DDR - */ -static int mc_copy_image(const char *title, - u64 image_addr, u32 image_size, u64 mc_ram_addr) -{ - debug("%s copied to address %p\n", title, (void *)mc_ram_addr); - memcpy((void *)mc_ram_addr, (void *)image_addr, image_size); - return 0; -} - -/** - * MC firmware FIT image parser checks if the image is in FIT - * format, verifies integrity of the image and calculates - * raw image address and size values. - * Returns 0 if success and 1 if any of the above mentioned - * task fail. - **/ - -int parse_mc_firmware_fit_image(const void **raw_image_addr, - size_t *raw_image_size) -{ - int format; - void *fit_hdr; - int node_offset; - const void *data; - size_t size; - const char *uname = "firmware"; - - /* Check if the image is in NOR flash*/ -#ifdef CONFIG_SYS_LS_MC_FW_IN_NOR - fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR; -#else -#error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined" -#endif - - /* Check if Image is in FIT format */ - format = genimg_get_format(fit_hdr); - - if (format != IMAGE_FORMAT_FIT) { - debug("Not a FIT image\n"); - return 1; - } - - if (!fit_check_format(fit_hdr)) { - debug("Bad FIT image format\n"); - return 1; - } - - node_offset = fit_image_get_node(fit_hdr, uname); - - if (node_offset < 0) { - debug("Can not find %s subimage\n", uname); - return 1; - } - - /* Verify MC firmware image */ - if (!(fit_image_verify(fit_hdr, node_offset))) { - debug("Bad MC firmware hash"); - return 1; - } - - /* Get address and size of raw image */ - fit_image_get_data(fit_hdr, node_offset, &data, &size); - - *raw_image_addr = data; - *raw_image_size = size; - - return 0; -} - -int mc_init(bd_t *bis) -{ - int error = 0; - int timeout = 200000; - struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; - u64 mc_ram_addr; - u64 mc_dpl_offset; - u32 reg_gsr; - u32 mc_fw_boot_status; - void *fdt_hdr; - int dpl_size; - const void *raw_image_addr; - size_t raw_image_size = 0; - - BUILD_BUG_ON(CONFIG_SYS_LS_MC_FW_LENGTH % 4 != 0); - - /* - * The MC private DRAM block was already carved at the end of DRAM - * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE: - */ - if (gd->bd->bi_dram[1].start) { - mc_ram_addr = - gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size; - } else { - mc_ram_addr = - gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; - } - - /* - * Management Complex cores should be held at reset out of POR. - * U-boot should be the first software to touch MC. To be safe, - * we reset all cores again by setting GCR1 to 0. It doesn't do - * anything if they are held at reset. After we setup the firmware - * we kick off MC by deasserting the reset bit for core 0, and - * deasserting the reset bits for Command Portal Managers. - * The stop bits are not touched here. They are used to stop the - * cores when they are active. Setting stop bits doesn't stop the - * cores from fetching instructions when they are released from - * reset. - */ - out_le32(&mc_ccsr_regs->reg_gcr1, 0); - dmb(); - - error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size); - if (error != 0) - goto out; - /* - * Load the MC FW at the beginning of the MC private DRAM block: - */ - mc_copy_image( - "MC Firmware", - (u64)raw_image_addr, - raw_image_size, - mc_ram_addr); - - /* - * Calculate offset in the MC private DRAM block at which the MC DPL - * blob is to be placed: - */ -#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET - BUILD_BUG_ON( - (CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || - CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); - - mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; -#else - mc_dpl_offset = mc_get_dram_block_size() - - roundup(CONFIG_SYS_LS_MC_DPL_LENGTH, 4096); - - if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) { - printf("%s: Invalid MC DPL offset: %llu\n", - __func__, mc_dpl_offset); - error = -EINVAL; - goto out; - } -#endif - - /* Check if DPL image is in NOR flash */ -#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR - fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; -#else -#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" -#endif - - dpl_size = fdt_totalsize(fdt_hdr); - - /* - * Load the MC DPL blob at the far end of the MC private DRAM block: - */ - mc_copy_image( - "MC DPL blob", - (u64)fdt_hdr, - dpl_size, - mc_ram_addr + mc_dpl_offset); - - debug("mc_ccsr_regs %p\n", mc_ccsr_regs); - - /* - * Tell MC where the MC Firmware image was loaded in DDR: - */ - out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr); - out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32)); - out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK); - - /* - * Tell MC where the DPL blob was loaded in DDR, by indicating - * its offset relative to the beginning of the DDR block - * allocated to the MC firmware. The MC firmware is responsible - * for checking that there is no overlap between the DPL blob - * and the runtime heap and stack of the MC firmware itself. - * - * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of - * the GSR MC CCSR register. So, this offset is assumed to be 4-byte - * aligned. - * Care must be taken not to write 1s into bits 31 and 30 of the GSR in - * this case as the SoC COP or PIC will be signaled. - */ - out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2)); - - /* - * Deassert reset and release MC core 0 to run - */ - out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); - dmb(); - debug("Polling mc_ccsr_regs->reg_gsr ...\n"); - - for (;;) { - reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); - mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); - if (mc_fw_boot_status & 0x1) - break; - - udelay(1000); /* throttle polling */ - if (timeout-- <= 0) - break; - } - - if (timeout <= 0) { - printf("%s: timeout booting management complex firmware\n", - __func__); - - /* TODO: Get an error status from an MC CCSR register */ - error = -ETIMEDOUT; - goto out; - } - - printf("Management complex booted (boot status: %#x)\n", - mc_fw_boot_status); - - if (mc_fw_boot_status != 0x1) { - /* - * TODO: Identify critical errors from the GSR register's FS - * field and for those errors, set error to -ENODEV or other - * appropriate errno, so that the status property is set to - * failure in the fsl,dprc device tree node. - */ - } - -out: - if (error != 0) - mc_boot_status = -error; - else - mc_boot_status = 0; - - return error; -} - -int get_mc_boot_status(void) -{ - return mc_boot_status; -} - -/** - * Return the actual size of the MC private DRAM block. - * - * NOTE: For now this function always returns the minimum required size, - * However, in the future, the actual size may be obtained from an environment - * variable. - */ -unsigned long mc_get_dram_block_size(void) -{ - return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; -} -- cgit v1.1 From e4e8cb71384a7572b32509df6aa257809b8dcd5d Mon Sep 17 00:00:00 2001 From: Minghuan Lian Date: Wed, 21 Jan 2015 17:29:20 +0800 Subject: driver/pci: add Layerscape PCIe driver The patch adds Freescale Layerscape PCIe driver and provides up to 4 controllers support. Signed-off-by: Minghuan Lian Reviewed-by: York Sun --- drivers/pci/pcie_layerscape.c | 471 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 291c249..bcad8f2 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -1,5 +1,5 @@ /* - * Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2014-2015 Freescale Semiconductor, Inc. * Layerscape PCIe driver * * SPDX-License-Identifier: GPL-2.0+ @@ -9,8 +9,465 @@ #include #include #include +#include +#include #include +#ifndef CONFIG_SYS_PCI_MEMORY_BUS +#define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE +#endif + +#ifndef CONFIG_SYS_PCI_MEMORY_PHYS +#define CONFIG_SYS_PCI_MEMORY_PHYS CONFIG_SYS_SDRAM_BASE +#endif + +#ifndef CONFIG_SYS_PCI_MEMORY_SIZE +#define CONFIG_SYS_PCI_MEMORY_SIZE (2 * 1024 * 1024 * 1024UL) /* 2G */ +#endif + +/* iATU registers */ +#define PCIE_ATU_VIEWPORT 0x900 +#define PCIE_ATU_REGION_INBOUND (0x1 << 31) +#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) +#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) +#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) +#define PCIE_ATU_REGION_INDEX2 (0x2 << 0) +#define PCIE_ATU_REGION_INDEX3 (0x3 << 0) +#define PCIE_ATU_CR1 0x904 +#define PCIE_ATU_TYPE_MEM (0x0 << 0) +#define PCIE_ATU_TYPE_IO (0x2 << 0) +#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) +#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) +#define PCIE_ATU_CR2 0x908 +#define PCIE_ATU_ENABLE (0x1 << 31) +#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) +#define PCIE_ATU_LOWER_BASE 0x90C +#define PCIE_ATU_UPPER_BASE 0x910 +#define PCIE_ATU_LIMIT 0x914 +#define PCIE_ATU_LOWER_TARGET 0x918 +#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) +#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) +#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) +#define PCIE_ATU_UPPER_TARGET 0x91C + +#define PCIE_LINK_CAP 0x7c +#define PCIE_LINK_SPEED_MASK 0xf +#define PCIE_LINK_STA 0x82 + +#define PCIE_DBI_SIZE (4 * 1024) /* 4K */ + +struct ls_pcie { + int idx; + void __iomem *dbi; + void __iomem *va_cfg0; + void __iomem *va_cfg1; + struct pci_controller hose; +}; + +struct ls_pcie_info { + unsigned long regs; + int pci_num; + u64 cfg0_phys; + u64 cfg0_size; + u64 cfg1_phys; + u64 cfg1_size; + u64 mem_bus; + u64 mem_phys; + u64 mem_size; + u64 io_bus; + u64 io_phys; + u64 io_size; +}; + +#define SET_LS_PCIE_INFO(x, num) \ +{ \ + x.regs = CONFIG_SYS_PCIE##num##_ADDR; \ + x.cfg0_phys = CONFIG_SYS_PCIE_CFG0_PHYS_OFF + \ + CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ + x.cfg0_size = CONFIG_SYS_PCIE_CFG0_SIZE; \ + x.cfg1_phys = CONFIG_SYS_PCIE_CFG1_PHYS_OFF + \ + CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ + x.cfg1_size = CONFIG_SYS_PCIE_CFG1_SIZE; \ + x.mem_bus = CONFIG_SYS_PCIE_MEM_BUS; \ + x.mem_phys = CONFIG_SYS_PCIE_MEM_PHYS_OFF + \ + CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ + x.mem_size = CONFIG_SYS_PCIE_MEM_SIZE; \ + x.io_bus = CONFIG_SYS_PCIE_IO_BUS; \ + x.io_phys = CONFIG_SYS_PCIE_IO_PHYS_OFF + \ + CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ + x.io_size = CONFIG_SYS_PCIE_IO_SIZE; \ + x.pci_num = num; \ +} + +#ifdef CONFIG_LS102XA +#include + +/* PEX1/2 Misc Ports Status Register */ +#define LTSSM_STATE_SHIFT 20 +#define LTSSM_STATE_MASK 0x3f +#define LTSSM_PCIE_L0 0x11 /* L0 state */ + +static int ls_pcie_link_state(struct ls_pcie *pcie) +{ + u32 state; + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + + state = in_be32(&scfg->pexmscportsr[pcie->idx]); + state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; + if (state < LTSSM_PCIE_L0) { + debug("....PCIe link error. LTSSM=0x%02x.\n", state); + return 0; + } + + return 1; +} +#else +#define PCIE_LDBG 0x7FC + +static int ls_pcie_link_state(struct ls_pcie *pcie) +{ + u32 state; + + state = readl(pcie->dbi + PCIE_LDBG); + if (state) + return 1; + + debug("....PCIe link error.\n"); + return 0; +} +#endif + +static int ls_pcie_link_up(struct ls_pcie *pcie) +{ + int state; + u32 cap; + + state = ls_pcie_link_state(pcie); + if (state) + return state; + + /* Try to download speed to gen1 */ + cap = readl(pcie->dbi + PCIE_LINK_CAP); + writel((cap & (~PCIE_LINK_SPEED_MASK)) | 1, pcie->dbi + PCIE_LINK_CAP); + udelay(2000); + state = ls_pcie_link_state(pcie); + if (state) + return state; + + writel(cap, pcie->dbi + PCIE_LINK_CAP); + + return 0; +} + +static void ls_pcie_cfg0_set_busdev(struct ls_pcie *pcie, u32 busdev) +{ + writel(PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, + pcie->dbi + PCIE_ATU_VIEWPORT); + writel(busdev, pcie->dbi + PCIE_ATU_LOWER_TARGET); +} + +static void ls_pcie_cfg1_set_busdev(struct ls_pcie *pcie, u32 busdev) +{ + writel(PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, + pcie->dbi + PCIE_ATU_VIEWPORT); + writel(busdev, pcie->dbi + PCIE_ATU_LOWER_TARGET); +} + +static void ls_pcie_iatu_outbound_set(struct ls_pcie *pcie, int idx, int type, + u64 phys, u64 bus_addr, pci_size_t size) +{ + writel(PCIE_ATU_REGION_OUTBOUND | idx, pcie->dbi + PCIE_ATU_VIEWPORT); + writel((u32)phys, pcie->dbi + PCIE_ATU_LOWER_BASE); + writel(phys >> 32, pcie->dbi + PCIE_ATU_UPPER_BASE); + writel(phys + size - 1, pcie->dbi + PCIE_ATU_LIMIT); + writel((u32)bus_addr, pcie->dbi + PCIE_ATU_LOWER_TARGET); + writel(bus_addr >> 32, pcie->dbi + PCIE_ATU_UPPER_TARGET); + writel(type, pcie->dbi + PCIE_ATU_CR1); + writel(PCIE_ATU_ENABLE, pcie->dbi + PCIE_ATU_CR2); +} + +static void ls_pcie_setup_atu(struct ls_pcie *pcie, struct ls_pcie_info *info) +{ +#ifdef DEBUG + int i; +#endif + + /* ATU 0 : OUTBOUND : CFG0 */ + ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_CFG0, + info->cfg0_phys, + 0, + info->cfg0_size); + /* ATU 1 : OUTBOUND : CFG1 */ + ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX1, + PCIE_ATU_TYPE_CFG1, + info->cfg1_phys, + 0, + info->cfg1_size); + /* ATU 2 : OUTBOUND : MEM */ + ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX2, + PCIE_ATU_TYPE_MEM, + info->mem_phys, + info->mem_bus, + info->mem_size); + /* ATU 3 : OUTBOUND : IO */ + ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX3, + PCIE_ATU_TYPE_IO, + info->io_phys, + info->io_bus, + info->io_size); + +#ifdef DEBUG + for (i = 0; i <= PCIE_ATU_REGION_INDEX3; i++) { + writel(PCIE_ATU_REGION_OUTBOUND | i, + pcie->dbi + PCIE_ATU_VIEWPORT); + debug("iATU%d:\n", i); + debug("\tLOWER PHYS 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_LOWER_BASE)); + debug("\tUPPER PHYS 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_UPPER_BASE)); + debug("\tLOWER BUS 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_LOWER_TARGET)); + debug("\tUPPER BUS 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_UPPER_TARGET)); + debug("\tLIMIT 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_LIMIT)); + debug("\tCR1 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_CR1)); + debug("\tCR2 0x%08x\n", + readl(pcie->dbi + PCIE_ATU_CR2)); + } +#endif +} + +int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) +{ + /* Do not skip controller */ + return 0; +} + +static int ls_pcie_addr_valid(struct pci_controller *hose, pci_dev_t d) +{ + if (PCI_DEV(d) > 0) + return -EINVAL; + + return 0; +} + +static int ls_pcie_read_config(struct pci_controller *hose, pci_dev_t d, + int where, u32 *val) +{ + struct ls_pcie *pcie = hose->priv_data; + u32 busdev, *addr; + + if (ls_pcie_addr_valid(hose, d)) { + *val = 0xffffffff; + return -EINVAL; + } + + if (PCI_BUS(d) == hose->first_busno) { + addr = pcie->dbi + (where & ~0x3); + } else { + busdev = PCIE_ATU_BUS(PCI_BUS(d)) | + PCIE_ATU_DEV(PCI_DEV(d)) | + PCIE_ATU_FUNC(PCI_FUNC(d)); + + if (PCI_BUS(d) == hose->first_busno + 1) { + ls_pcie_cfg0_set_busdev(pcie, busdev); + addr = pcie->va_cfg0 + (where & ~0x3); + } else { + ls_pcie_cfg1_set_busdev(pcie, busdev); + addr = pcie->va_cfg1 + (where & ~0x3); + } + } + + *val = readl(addr); + + return 0; +} + +static int ls_pcie_write_config(struct pci_controller *hose, pci_dev_t d, + int where, u32 val) +{ + struct ls_pcie *pcie = hose->priv_data; + u32 busdev, *addr; + + if (ls_pcie_addr_valid(hose, d)) + return -EINVAL; + + if (PCI_BUS(d) == hose->first_busno) { + addr = pcie->dbi + (where & ~0x3); + } else { + busdev = PCIE_ATU_BUS(PCI_BUS(d)) | + PCIE_ATU_DEV(PCI_DEV(d)) | + PCIE_ATU_FUNC(PCI_FUNC(d)); + + if (PCI_BUS(d) == hose->first_busno + 1) { + ls_pcie_cfg0_set_busdev(pcie, busdev); + addr = pcie->va_cfg0 + (where & ~0x3); + } else { + ls_pcie_cfg1_set_busdev(pcie, busdev); + addr = pcie->va_cfg1 + (where & ~0x3); + } + } + + writel(val, addr); + + return 0; +} + +static void ls_pcie_setup_ctrl(struct ls_pcie *pcie, + struct ls_pcie_info *info) +{ + struct pci_controller *hose = &pcie->hose; + pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); + + ls_pcie_setup_atu(pcie, info); + + pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0); + + /* program correct class for RC */ + pci_hose_write_config_word(hose, dev, PCI_CLASS_DEVICE, + PCI_CLASS_BRIDGE_PCI); +} + +int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) +{ + struct ls_pcie *pcie; + struct pci_controller *hose; + int num = dev - PCIE1; + pci_dev_t pdev = PCI_BDF(busno, 0, 0); + int i, linkup, ep_mode; + u8 header_type; + u16 temp16; + + if (!is_serdes_configured(dev)) { + printf("PCIe%d: disabled\n", num + 1); + return busno; + } + + pcie = malloc(sizeof(*pcie)); + if (!pcie) + return busno; + memset(pcie, 0, sizeof(*pcie)); + + hose = &pcie->hose; + hose->priv_data = pcie; + hose->first_busno = busno; + pcie->idx = num; + pcie->dbi = map_physmem(info->regs, PCIE_DBI_SIZE, MAP_NOCACHE); + pcie->va_cfg0 = map_physmem(info->cfg0_phys, + info->cfg0_size, + MAP_NOCACHE); + pcie->va_cfg1 = map_physmem(info->cfg1_phys, + info->cfg1_size, + MAP_NOCACHE); + + /* outbound memory */ + pci_set_region(&hose->regions[0], + (pci_size_t)info->mem_bus, + (phys_size_t)info->mem_phys, + (pci_size_t)info->mem_size, + PCI_REGION_MEM); + + /* outbound io */ + pci_set_region(&hose->regions[1], + (pci_size_t)info->io_bus, + (phys_size_t)info->io_phys, + (pci_size_t)info->io_size, + PCI_REGION_IO); + + /* System memory space */ + pci_set_region(&hose->regions[2], + CONFIG_SYS_PCI_MEMORY_BUS, + CONFIG_SYS_PCI_MEMORY_PHYS, + CONFIG_SYS_PCI_MEMORY_SIZE, + PCI_REGION_SYS_MEMORY); + + hose->region_count = 3; + + for (i = 0; i < hose->region_count; i++) + debug("PCI reg:%d %016llx:%016llx %016llx %08lx\n", + i, + (u64)hose->regions[i].phys_start, + (u64)hose->regions[i].bus_start, + (u64)hose->regions[i].size, + hose->regions[i].flags); + + pci_set_ops(hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + ls_pcie_read_config, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + ls_pcie_write_config); + + pci_hose_read_config_byte(hose, pdev, PCI_HEADER_TYPE, &header_type); + ep_mode = (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL; + printf("PCIe%u: %s ", info->pci_num, + ep_mode ? "Endpoint" : "Root Complex"); + + linkup = ls_pcie_link_up(pcie); + + if (!linkup) { + /* Let the user know there's no PCIe link */ + printf("no link, regs @ 0x%lx\n", info->regs); + hose->last_busno = hose->first_busno; + return busno; + } + + /* Print the negotiated PCIe link width */ + pci_hose_read_config_word(hose, dev, PCIE_LINK_STA, &temp16); + printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4, + (temp16 & 0xf), info->regs); + + if (ep_mode) + return busno; + + ls_pcie_setup_ctrl(pcie, info); + + pci_register_hose(hose); + + hose->last_busno = pci_hose_scan(hose); + + printf("PCIe%x: Bus %02x - %02x\n", + info->pci_num, hose->first_busno, hose->last_busno); + + return hose->last_busno + 1; +} + +int ls_pcie_init_board(int busno) +{ + struct ls_pcie_info info; + +#ifdef CONFIG_PCIE1 + SET_LS_PCIE_INFO(info, 1); + busno = ls_pcie_init_ctrl(busno, PCIE1, &info); +#endif + +#ifdef CONFIG_PCIE2 + SET_LS_PCIE_INFO(info, 2); + busno = ls_pcie_init_ctrl(busno, PCIE2, &info); +#endif + +#ifdef CONFIG_PCIE3 + SET_LS_PCIE_INFO(info, 3); + busno = ls_pcie_init_ctrl(busno, PCIE3, &info); +#endif + +#ifdef CONFIG_PCIE4 + SET_LS_PCIE_INFO(info, 4); + busno = ls_pcie_init_ctrl(busno, PCIE4, &info); +#endif + + return busno; +} + +void pci_init_board(void) +{ + ls_pcie_init_board(0); +} + #ifdef CONFIG_OF_BOARD_SETUP #include #include @@ -38,6 +495,14 @@ void ft_pcie_setup(void *blob, bd_t *bd) #ifdef CONFIG_PCIE2 ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE2_ADDR, PCIE2); #endif + + #ifdef CONFIG_PCIE3 + ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE3_ADDR, PCIE3); + #endif + + #ifdef CONFIG_PCIE4 + ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE4_ADDR, PCIE4); + #endif } #else @@ -45,7 +510,3 @@ void ft_pcie_setup(void *blob, bd_t *bd) { } #endif - -void pci_init_board(void) -{ -} -- cgit v1.1 From 0e1bf614d5045b060db8e1bf9e7f69afdf1c592f Mon Sep 17 00:00:00 2001 From: Volodymyr Riazantsev Date: Tue, 20 Jan 2015 10:16:44 -0500 Subject: mmc: fsl_esdhc: Add support for DDR mode Add support of the DDR mode for eSDHC driver. Enable it for i.MX6 SoC family only. Signed-off-by: Volodymyr Riazantsev Reviewed-by: York Sun --- drivers/mmc/fsl_esdhc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index c55eb28..f5d2ccb 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -319,7 +319,8 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) esdhc_write32(®s->cmdarg, cmd->cmdarg); #if defined(CONFIG_FSL_USDHC) esdhc_write32(®s->mixctrl, - (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F)); + (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F) + | (mmc->ddr_mode ? XFERTYP_DDREN : 0)); esdhc_write32(®s->xfertyp, xfertyp & 0xFFFF0000); #else esdhc_write32(®s->xfertyp, xfertyp); @@ -442,7 +443,7 @@ static void set_sysctl(struct mmc *mmc, uint clock) if ((sdhc_clk / (div * pre_div)) <= clock) break; - pre_div >>= 1; + pre_div >>= mmc->ddr_mode ? 2 : 1; div -= 1; clk = (pre_div << 8) | (div << 4); @@ -601,6 +602,9 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) } cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; +#ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE + cfg->cfg.host_caps |= MMC_MODE_DDR_52MHz; +#endif if (cfg->max_bus_width > 0) { if (cfg->max_bus_width < 8) -- cgit v1.1 From e02ee2548afe22f7d197b89df2ae7bd72f1df630 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 Feb 2015 22:26:20 +0900 Subject: kconfig: switch to single .config configuration When Kconfig for U-boot was examined, one of the biggest issues was how to support multiple images (Normal, SPL, TPL). There were actually two options, "single .config" and "multiple .config". After some discussions and thought experiments, I chose the latter, i.e. to create ".config", "spl/.config", "tpl/.config" for Normal, SPL, TPL, respectively. It is true that the "multiple .config" strategy provided us the maximum flexibility and helped to avoid duplicating CONFIGs among Normal, SPL, TPL, but I have noticed some fatal problems: [1] It is impossible to share CONFIG options across the images. If you change the configuration of Main image, you often have to adjust some SPL configurations correspondingly. Currently, we cannot handle the dependencies between them. It means one of the biggest advantages of Kconfig is lost. [2] It is too painful to change both ".config" and "spl/.config". Sunxi guys started to work around this problem by creating a new configuration target. Commit cbdd9a9737cc (sunxi: kconfig: Add %_felconfig rule to enable FEL build of sunxi platforms.) added "make *_felconfig" to enable CONFIG_SPL_FEL on both images. Changing the configuration of multiple images in one command is a generic demand. The current implementation cannot propose any good solution about this. [3] Kconfig files are getting ugly and difficult to understand. Commit b724bd7d6349 (dm: Kconfig: Move CONFIG_SYS_MALLOC_F_LEN to Kconfig) has sprinkled "if !SPL_BUILD" over the Kconfig files. [4] The build system got more complicated than it should be. To adjust Linux-originated Kconfig to U-Boot, the helper script "scripts/multiconfig.sh" was introduced. Writing a complicated text processor is a shell script sometimes caused problems. Now I believe the "single .config" will serve us better. With it, all the problems above would go away. Instead, we will have to add some CONFIG_SPL_* (and CONFIG_TPL_*) options such as CONFIG_SPL_DM, but we will not have much. Anyway, this is what we do now in scripts/Makefile.spl. I admit my mistake with my apology and this commit switches to the single .config configuration. It is not so difficult to do that: - Remove unnecessary processings from scripts/multiconfig.sh This file will remain for a while to support the current defconfig format. It will be removed after more cleanups are done. - Adjust some makefiles and Kconfigs - Add some entries to include/config_uncmd_spl.h and the new file scripts/Makefile.uncmd_spl. Some CONFIG options that are not supported on SPL must be disabled because one .config is shared between SPL and U-Boot proper going forward. I know this is not a beautiful solution and I think we can do better, but let's see how much we will have to describe them. - update doc/README.kconfig More cleaning up patches will follow this. Signed-off-by: Masahiro Yamada Reviewed-by: Simon Glass --- drivers/mtd/nand/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c242214..ccd8211 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -36,7 +36,7 @@ config NAND_DENALI_SPARE_AREA_SKIP_BYTES endif -if SPL_BUILD +if SPL config SPL_NAND_DENALI bool "Support Denali NAND controller for SPL" -- cgit v1.1 From d648964fc2495f1184af5782a0b7fc670ba5826e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 Feb 2015 22:26:21 +0900 Subject: kconfig: remove unneeded dependency on !SPL_BUILD Now CONFIG_SPL_BUILD is not defined in Kconfig, so "!depends on SPL_BUILD" and "if !SPL_BUILD" are redundant. Signed-off-by: Masahiro Yamada --- drivers/core/Kconfig | 16 ++++++---------- drivers/mtd/nand/Kconfig | 4 ---- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index f0d6110..75d182d 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -1,6 +1,5 @@ config DM bool "Enable Driver Model" - depends on !SPL_BUILD help This config option enables Driver Model. This brings in the core support, including scanning of platform data on start-up. If @@ -22,31 +21,28 @@ config SPL_DM config DM_WARN bool "Enable warnings in driver model" + depends on DM + default y help The dm_warn() function can use up quite a bit of space for its strings. By default this is disabled for SPL builds to save space. This will cause dm_warn() to be compiled out - it will do nothing when called. - depends on DM - default y if !SPL_BUILD - default n if SPL_BUILD config DM_DEVICE_REMOVE bool "Support device removal" + depends on DM + default y help We can save some code space by dropping support for removing a device. This is not normally required in SPL, so by default this option is disabled for SPL. - depends on DM - default y if !SPL_BUILD - default n if SPL_BUILD config DM_STDIO bool "Support stdio registration" + depends on DM + default y help Normally serial drivers register with stdio so that they can be used as normal output devices. In SPL we don't normally use stdio, so we can omit this feature. - depends on DM - default y if !SPL_BUILD - default n if SPL_BUILD diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index ccd8211..72825c3 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -6,8 +6,6 @@ config SYS_NAND_SELF_INIT This option, if enabled, provides more flexible and linux-like NAND initialization process. -if !SPL_BUILD - config NAND_DENALI bool "Support Denali NAND controller" select SYS_NAND_SELF_INIT @@ -34,8 +32,6 @@ config NAND_DENALI_SPARE_AREA_SKIP_BYTES of OOB area before last ECC sector data starts. This is potentially used to preserve the bad block marker in the OOB area. -endif - if SPL config SPL_NAND_DENALI -- cgit v1.1 From 41fbbbbc71161e0c0479d7c6c5598e760d70f624 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 Feb 2015 11:45:05 +0900 Subject: ARM: remove jadecpu board support This is still a non-generic board. Signed-off-by: Masahiro Yamada Cc: Matthias Weisser Acked-by: Marek Vasut --- drivers/video/Makefile | 1 - drivers/video/mb86r0xgdc.c | 168 --------------------------------------------- 2 files changed, 169 deletions(-) delete mode 100644 drivers/video/mb86r0xgdc.c (limited to 'drivers') diff --git a/drivers/video/Makefile b/drivers/video/Makefile index af2d47b..22a316b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_VIDEO_IMX25LCDC) += imx25lcdc.o videomodes.o obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o -obj-$(CONFIG_VIDEO_MB86R0xGDC) += mb86r0xgdc.o videomodes.o obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o obj-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o obj-$(CONFIG_VIDEO_MXS) += mxsfb.o videomodes.o diff --git a/drivers/video/mb86r0xgdc.c b/drivers/video/mb86r0xgdc.c deleted file mode 100644 index bb7a749..0000000 --- a/drivers/video/mb86r0xgdc.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * (C) Copyright 2010 - * Matthias Weisser - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * mb86r0xgdc.c - Graphic interface for Fujitsu MB86R0x integrated graphic - * controller. - */ - -#include - -#include -#include -#include -#include -#include "videomodes.h" - -/* - * 4MB (at the end of system RAM) - */ -#define VIDEO_MEM_SIZE 0x400000 - -#define FB_SYNC_CLK_INV (1<<16) /* pixel clock inverted */ - -/* - * Graphic Device - */ -static GraphicDevice mb86r0x; - -static void dsp_init(struct mb86r0x_gdc_dsp *dsp, char *modestr, - u32 *videomem) -{ - struct ctfb_res_modes var_mode; - u32 dcm1, dcm2, dcm3; - u16 htp, hdp, hdb, hsp, vtr, vsp, vdp; - u8 hsw, vsw; - u32 l2m, l2em, l2oa0, l2da0, l2oa1, l2da1; - u16 l2dx, l2dy, l2wx, l2wy, l2ww, l2wh; - unsigned long div; - int bpp; - - bpp = video_get_params(&var_mode, modestr); - - if (bpp == 0) { - var_mode.xres = 640; - var_mode.yres = 480; - var_mode.pixclock = 39721; /* 25MHz */ - var_mode.left_margin = 48; - var_mode.right_margin = 16; - var_mode.upper_margin = 33; - var_mode.lower_margin = 10; - var_mode.hsync_len = 96; - var_mode.vsync_len = 2; - var_mode.sync = 0; - var_mode.vmode = 0; - bpp = 15; - } - - /* Fill memory with white */ - memset(videomem, 0xFF, var_mode.xres * var_mode.yres * 2); - - mb86r0x.winSizeX = var_mode.xres; - mb86r0x.winSizeY = var_mode.yres; - - /* LCD base clock is ~ 660MHZ. We do calculations in kHz */ - div = 660000 / (1000000000L / var_mode.pixclock); - if (div > 64) - div = 64; - if (0 == div) - div = 1; - - dcm1 = (div - 1) << 8; - dcm2 = 0x00000000; - if (var_mode.sync & FB_SYNC_CLK_INV) - dcm3 = 0x00000100; - else - dcm3 = 0x00000000; - - htp = var_mode.left_margin + var_mode.xres + - var_mode.hsync_len + var_mode.right_margin; - hdp = var_mode.xres; - hdb = var_mode.xres; - hsp = var_mode.xres + var_mode.right_margin; - hsw = var_mode.hsync_len; - - vsw = var_mode.vsync_len; - vtr = var_mode.upper_margin + var_mode.yres + - var_mode.vsync_len + var_mode.lower_margin; - vsp = var_mode.yres + var_mode.lower_margin; - vdp = var_mode.yres; - - l2m = ((var_mode.yres - 1) << (0)) | - (((var_mode.xres * 2) / 64) << (16)) | - ((1) << (31)); - - l2em = (1 << 0) | (1 << 1); - - l2oa0 = mb86r0x.frameAdrs; - l2da0 = mb86r0x.frameAdrs; - l2oa1 = mb86r0x.frameAdrs; - l2da1 = mb86r0x.frameAdrs; - l2dx = 0; - l2dy = 0; - l2wx = 0; - l2wy = 0; - l2ww = var_mode.xres; - l2wh = var_mode.yres - 1; - - writel(dcm1, &dsp->dcm1); - writel(dcm2, &dsp->dcm2); - writel(dcm3, &dsp->dcm3); - - writew(htp, &dsp->htp); - writew(hdp, &dsp->hdp); - writew(hdb, &dsp->hdb); - writew(hsp, &dsp->hsp); - writeb(hsw, &dsp->hsw); - - writeb(vsw, &dsp->vsw); - writew(vtr, &dsp->vtr); - writew(vsp, &dsp->vsp); - writew(vdp, &dsp->vdp); - - writel(l2m, &dsp->l2m); - writel(l2em, &dsp->l2em); - writel(l2oa0, &dsp->l2oa0); - writel(l2da0, &dsp->l2da0); - writel(l2oa1, &dsp->l2oa1); - writel(l2da1, &dsp->l2da1); - writew(l2dx, &dsp->l2dx); - writew(l2dy, &dsp->l2dy); - writew(l2wx, &dsp->l2wx); - writew(l2wy, &dsp->l2wy); - writew(l2ww, &dsp->l2ww); - writew(l2wh, &dsp->l2wh); - - writel(dcm1 | (1 << 18) | (1 << 31), &dsp->dcm1); -} - -void *video_hw_init(void) -{ - struct mb86r0x_gdc *gdc = (struct mb86r0x_gdc *) MB86R0x_GDC_BASE; - GraphicDevice *pGD = &mb86r0x; - char *s; - u32 *vid; - - memset(pGD, 0, sizeof(GraphicDevice)); - - pGD->gdfIndex = GDF_15BIT_555RGB; - pGD->gdfBytesPP = 2; - pGD->memSize = VIDEO_MEM_SIZE; - pGD->frameAdrs = PHYS_SDRAM + PHYS_SDRAM_SIZE - VIDEO_MEM_SIZE; - - vid = (u32 *)pGD->frameAdrs; - - s = getenv("videomode"); - if (s != NULL) - dsp_init(&gdc->dsp0, s, vid); - - s = getenv("videomode1"); - if (s != NULL) - dsp_init(&gdc->dsp1, s, vid); - - return pGD; -} -- cgit v1.1 From a2f39e830e509cb63aad2c752573d1c871a1d4bf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 Feb 2015 11:45:07 +0900 Subject: ARM: remove cm4008 and cm41xx board support These are still non-generic boards. Signed-off-by: Masahiro Yamada Cc: Greg Ungerer Acked-by: Marek Vasut --- drivers/net/Makefile | 1 - drivers/net/ks8695eth.c | 229 ----------------------------------------- drivers/serial/Makefile | 1 - drivers/serial/serial.c | 2 - drivers/serial/serial_ks8695.c | 121 ---------------------- 5 files changed, 354 deletions(-) delete mode 100644 drivers/net/ks8695eth.c delete mode 100644 drivers/serial/serial_ks8695.c (limited to 'drivers') diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 46c4ac6..da5e2bc 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_FTMAC110) += ftmac110.o obj-$(CONFIG_FTMAC100) += ftmac100.o obj-$(CONFIG_GRETH) += greth.o obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o -obj-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o obj-$(CONFIG_LAN91C96) += lan91c96.o obj-$(CONFIG_MACB) += macb.o diff --git a/drivers/net/ks8695eth.c b/drivers/net/ks8695eth.c deleted file mode 100644 index b4822e9..0000000 --- a/drivers/net/ks8695eth.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * ks8695eth.c -- KS8695 ethernet driver - * - * (C) Copyright 2004-2005, Greg Ungerer - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/****************************************************************************/ - -#include -#include -#include -#include -#include - -/****************************************************************************/ - -/* - * Hardware register access to the KS8695 LAN ethernet port - * (well, it is the 4 port switch really). - */ -#define ks8695_read(a) *((volatile unsigned long *) (KS8695_IO_BASE + (a))) -#define ks8695_write(a,v) *((volatile unsigned long *) (KS8695_IO_BASE + (a))) = (v) - -/****************************************************************************/ - -/* - * Define the descriptor in-memory data structures. - */ -struct ks8695_txdesc { - uint32_t owner; - uint32_t ctrl; - uint32_t addr; - uint32_t next; -}; - -struct ks8695_rxdesc { - uint32_t status; - uint32_t ctrl; - uint32_t addr; - uint32_t next; -}; - -/****************************************************************************/ - -/* - * Allocate local data structures to use for receiving and sending - * packets. Just to keep it all nice and simple. - */ - -#define TXDESCS 4 -#define RXDESCS 4 -#define BUFSIZE 2048 - -volatile struct ks8695_txdesc ks8695_tx[TXDESCS] __attribute__((aligned(256))); -volatile struct ks8695_rxdesc ks8695_rx[RXDESCS] __attribute__((aligned(256))); -volatile uint8_t ks8695_bufs[BUFSIZE*(TXDESCS+RXDESCS)] __attribute__((aligned(2048)));; - -/****************************************************************************/ - -/* - * Ideally we want to use the MAC address stored in flash. - * But we do some sanity checks in case they are not present - * first. - */ -unsigned char eth_mac[] = { - 0x00, 0x13, 0xc6, 0x00, 0x00, 0x00 -}; - -void ks8695_getmac(void) -{ - unsigned char *fp; - int i; - - /* Check if flash MAC is valid */ - fp = (unsigned char *) 0x0201c000; - for (i = 0; (i < 6); i++) { - if ((fp[i] != 0) && (fp[i] != 0xff)) - break; - } - - /* If we found a valid looking MAC address then use it */ - if (i < 6) - memcpy(ð_mac[0], fp, 6); -} - -/****************************************************************************/ - -static int ks8695_eth_init(struct eth_device *dev, bd_t *bd) -{ - int i; - - debug ("%s(%d): eth_reset()\n", __FILE__, __LINE__); - - /* Reset the ethernet engines first */ - ks8695_write(KS8695_LAN_DMA_TX, 0x80000000); - ks8695_write(KS8695_LAN_DMA_RX, 0x80000000); - - ks8695_getmac(); - - /* Set MAC address */ - ks8695_write(KS8695_LAN_MAC_LOW, (eth_mac[5] | (eth_mac[4] << 8) | - (eth_mac[3] << 16) | (eth_mac[2] << 24))); - ks8695_write(KS8695_LAN_MAC_HIGH, (eth_mac[1] | (eth_mac[0] << 8))); - - /* Turn the 4 port switch on */ - i = ks8695_read(KS8695_SWITCH_CTRL0); - ks8695_write(KS8695_SWITCH_CTRL0, (i | 0x1)); - /* ks8695_write(KS8695_WAN_CONTROL, 0x3f000066); */ - - /* Initialize descriptor rings */ - for (i = 0; (i < TXDESCS); i++) { - ks8695_tx[i].owner = 0; - ks8695_tx[i].ctrl = 0; - ks8695_tx[i].addr = (uint32_t) &ks8695_bufs[i*BUFSIZE]; - ks8695_tx[i].next = (uint32_t) &ks8695_tx[i+1]; - } - ks8695_tx[TXDESCS-1].ctrl = 0x02000000; - ks8695_tx[TXDESCS-1].next = (uint32_t) &ks8695_tx[0]; - - for (i = 0; (i < RXDESCS); i++) { - ks8695_rx[i].status = 0x80000000; - ks8695_rx[i].ctrl = BUFSIZE - 4; - ks8695_rx[i].addr = (uint32_t) &ks8695_bufs[(i+TXDESCS)*BUFSIZE]; - ks8695_rx[i].next = (uint32_t) &ks8695_rx[i+1]; - } - ks8695_rx[RXDESCS-1].ctrl |= 0x00080000; - ks8695_rx[RXDESCS-1].next = (uint32_t) &ks8695_rx[0]; - - /* The KS8695 is pretty slow reseting the ethernets... */ - udelay(2000000); - - /* Enable the ethernet engine */ - ks8695_write(KS8695_LAN_TX_LIST, (uint32_t) &ks8695_tx[0]); - ks8695_write(KS8695_LAN_RX_LIST, (uint32_t) &ks8695_rx[0]); - ks8695_write(KS8695_LAN_DMA_TX, 0x3); - ks8695_write(KS8695_LAN_DMA_RX, 0x71); - ks8695_write(KS8695_LAN_DMA_RX_START, 0x1); - - printf("KS8695 ETHERNET: %pM\n", eth_mac); - return 0; -} - -/****************************************************************************/ - -static void ks8695_eth_halt(struct eth_device *dev) -{ - debug ("%s(%d): eth_halt()\n", __FILE__, __LINE__); - - /* Reset the ethernet engines */ - ks8695_write(KS8695_LAN_DMA_TX, 0x80000000); - ks8695_write(KS8695_LAN_DMA_RX, 0x80000000); -} - -/****************************************************************************/ - -static int ks8695_eth_recv(struct eth_device *dev) -{ - volatile struct ks8695_rxdesc *dp; - int i, len = 0; - - debug ("%s(%d): eth_rx()\n", __FILE__, __LINE__); - - for (i = 0; (i < RXDESCS); i++) { - dp= &ks8695_rx[i]; - if ((dp->status & 0x80000000) == 0) { - len = (dp->status & 0x7ff) - 4; - NetReceive((void *) dp->addr, len); - dp->status = 0x80000000; - ks8695_write(KS8695_LAN_DMA_RX_START, 0x1); - break; - } - } - - return len; -} - -/****************************************************************************/ - -static int ks8695_eth_send(struct eth_device *dev, void *packet, int len) -{ - volatile struct ks8695_txdesc *dp; - static int next = 0; - - debug ("%s(%d): eth_send(packet=%p,len=%d)\n", __FILE__, __LINE__, - packet, len); - - dp = &ks8695_tx[next]; - memcpy((void *) dp->addr, (void *) packet, len); - - if (len < 64) { - memset((void *) (dp->addr + len), 0, 64-len); - len = 64; - } - - dp->ctrl = len | 0xe0000000; - dp->owner = 0x80000000; - - ks8695_write(KS8695_LAN_DMA_TX, 0x3); - ks8695_write(KS8695_LAN_DMA_TX_START, 0x1); - - if (++next >= TXDESCS) - next = 0; - - return 0; -} - -/****************************************************************************/ - -int ks8695_eth_initialize(void) -{ - struct eth_device *dev; - - dev = malloc(sizeof(*dev)); - if (dev == NULL) - return -1; - memset(dev, 0, sizeof(*dev)); - - dev->iobase = KS8695_IO_BASE + KS8695_LAN_DMA_TX; - dev->init = ks8695_eth_init; - dev->halt = ks8695_eth_halt; - dev->send = ks8695_eth_send; - dev->recv = ks8695_eth_recv; - strcpy(dev->name, "ks8695eth"); - - eth_register(dev); - return 0; -} diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 63b0cbf..b385852 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o obj-$(CONFIG_SYS_NS16550) += ns16550.o obj-$(CONFIG_S5P) += serial_s5p.o obj-$(CONFIG_IMX_SERIAL) += serial_imx.o -obj-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o obj-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o obj-$(CONFIG_MXC_UART) += serial_mxc.o obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 95c992a..9f78492 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -127,7 +127,6 @@ serial_initfunc(evb64260_serial_initialize); serial_initfunc(imx_serial_initialize); serial_initfunc(iop480_serial_initialize); serial_initfunc(jz_serial_initialize); -serial_initfunc(ks8695_serial_initialize); serial_initfunc(leon2_serial_initialize); serial_initfunc(leon3_serial_initialize); serial_initfunc(lh7a40x_serial_initialize); @@ -220,7 +219,6 @@ void serial_initialize(void) imx_serial_initialize(); iop480_serial_initialize(); jz_serial_initialize(); - ks8695_serial_initialize(); leon2_serial_initialize(); leon3_serial_initialize(); lh7a40x_serial_initialize(); diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c deleted file mode 100644 index 13adabd..0000000 --- a/drivers/serial/serial_ks8695.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * serial.c -- KS8695 serial driver - * - * (C) Copyright 2004, Greg Ungerer - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -#ifndef CONFIG_SERIAL1 -#error "Bad: you didn't configure serial ..." -#endif - -DECLARE_GLOBAL_DATA_PTR; - -/* - * Define the UART hardware register access structure. - */ -struct ks8695uart { - unsigned int RX; /* 0x00 - Receive data (r) */ - unsigned int TX; /* 0x04 - Transmit data (w) */ - unsigned int FCR; /* 0x08 - Fifo Control (r/w) */ - unsigned int LCR; /* 0x0c - Line Control (r/w) */ - unsigned int MCR; /* 0x10 - Modem Control (r/w) */ - unsigned int LSR; /* 0x14 - Line Status (r/w) */ - unsigned int MSR; /* 0x18 - Modem Status (r/w) */ - unsigned int BD; /* 0x1c - Baud Rate (r/w) */ - unsigned int SR; /* 0x20 - Status (r/w) */ -}; - -#define KS8695_UART_ADDR ((void *) (KS8695_IO_BASE + KS8695_UART_RX_BUFFER)) -#define KS8695_UART_CLK 25000000 - - -/* - * Under some circumstances we want to be "quiet" and not issue any - * serial output - though we want u-boot to otherwise work and behave - * the same. By default be noisy. - */ -int serial_console = 1; - - -static void ks8695_serial_setbrg(void) -{ - volatile struct ks8695uart *uartp = KS8695_UART_ADDR; - - /* Set to global baud rate and 8 data bits, no parity, 1 stop bit*/ - uartp->BD = KS8695_UART_CLK / gd->baudrate; - uartp->LCR = KS8695_UART_LINEC_WLEN8; -} - -static int ks8695_serial_init(void) -{ - serial_console = 1; - serial_setbrg(); - return 0; -} - -static void ks8695_serial_raw_putc(const char c) -{ - volatile struct ks8695uart *uartp = KS8695_UART_ADDR; - int i; - - for (i = 0; (i < 0x100000); i++) { - if (uartp->LSR & KS8695_UART_LINES_TXFE) - break; - } - - uartp->TX = c; -} - -static void ks8695_serial_putc(const char c) -{ - if (serial_console) { - ks8695_serial_raw_putc(c); - if (c == '\n') - ks8695_serial_raw_putc('\r'); - } -} - -static int ks8695_serial_tstc(void) -{ - volatile struct ks8695uart *uartp = KS8695_UART_ADDR; - if (serial_console) - return ((uartp->LSR & KS8695_UART_LINES_RXFE) ? 1 : 0); - return 0; -} - -static int ks8695_serial_getc(void) -{ - volatile struct ks8695uart *uartp = KS8695_UART_ADDR; - - while ((uartp->LSR & KS8695_UART_LINES_RXFE) == 0) - ; - return (uartp->RX); -} - -static struct serial_device ks8695_serial_drv = { - .name = "ks8695_serial", - .start = ks8695_serial_init, - .stop = NULL, - .setbrg = ks8695_serial_setbrg, - .putc = ks8695_serial_putc, - .puts = default_serial_puts, - .getc = ks8695_serial_getc, - .tstc = ks8695_serial_tstc, -}; - -void ks8695_serial_initialize(void) -{ - serial_register(&ks8695_serial_drv); -} - -__weak struct serial_device *default_serial_console(void) -{ - return &ks8695_serial_drv; -} -- cgit v1.1 From 50b82c4b702c59599c567fa82decb20d60f5110d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 Feb 2015 11:45:09 +0900 Subject: ARM: remove tnetv107x board support This is still a non-generic board. Signed-off-by: Masahiro Yamada Cc: Chan-Taek Park Acked-by: Marek Vasut --- drivers/watchdog/Makefile | 1 - drivers/watchdog/tnetv107x_wdt.c | 165 --------------------------------------- 2 files changed, 166 deletions(-) delete mode 100644 drivers/watchdog/tnetv107x_wdt.c (limited to 'drivers') diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 1dc0f5a..482a4bd 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o ifneq (,$(filter $(SOC), mx31 mx35 mx5 mx6 vf610 ls102xa)) obj-y += imx_watchdog.o endif -obj-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o obj-$(CONFIG_S5P) += s5p_wdt.o obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o obj-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o diff --git a/drivers/watchdog/tnetv107x_wdt.c b/drivers/watchdog/tnetv107x_wdt.c deleted file mode 100644 index 3d3f366..0000000 --- a/drivers/watchdog/tnetv107x_wdt.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * TNETV107X: Watchdog timer implementation (for reset) - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#define MAX_DIV 0xFFFE0001 - -struct wdt_regs { - u32 kick_lock; -#define KICK_LOCK_1 0x5555 -#define KICK_LOCK_2 0xaaaa - u32 kick; - - u32 change_lock; -#define CHANGE_LOCK_1 0x6666 -#define CHANGE_LOCK_2 0xbbbb - u32 change; - - u32 disable_lock; -#define DISABLE_LOCK_1 0x7777 -#define DISABLE_LOCK_2 0xcccc -#define DISABLE_LOCK_3 0xdddd - u32 disable; - - u32 prescale_lock; -#define PRESCALE_LOCK_1 0x5a5a -#define PRESCALE_LOCK_2 0xa5a5 - u32 prescale; -}; - -static struct wdt_regs* regs = (struct wdt_regs *)TNETV107X_WDT0_ARM_BASE; - -#define wdt_reg_read(reg) __raw_readl(®s->reg) -#define wdt_reg_write(reg, val) __raw_writel((val), ®s->reg) - -static int write_prescale_reg(unsigned long prescale_value) -{ - wdt_reg_write(prescale_lock, PRESCALE_LOCK_1); - if ((wdt_reg_read(prescale_lock) & 0x3) != 0x1) - return -1; - - wdt_reg_write(prescale_lock, PRESCALE_LOCK_2); - if ((wdt_reg_read(prescale_lock) & 0x3) != 0x3) - return -1; - - wdt_reg_write(prescale, prescale_value); - - return 0; -} - -static int write_change_reg(unsigned long initial_timer_value) -{ - wdt_reg_write(change_lock, CHANGE_LOCK_1); - if ((wdt_reg_read(change_lock) & 0x3) != 0x1) - return -1; - - wdt_reg_write(change_lock, CHANGE_LOCK_2); - if ((wdt_reg_read(change_lock) & 0x3) != 0x3) - return -1; - - wdt_reg_write(change, initial_timer_value); - - return 0; -} - -static int wdt_control(unsigned long disable_value) -{ - wdt_reg_write(disable_lock, DISABLE_LOCK_1); - if ((wdt_reg_read(disable_lock) & 0x3) != 0x1) - return -1; - - wdt_reg_write(disable_lock, DISABLE_LOCK_2); - if ((wdt_reg_read(disable_lock) & 0x3) != 0x2) - return -1; - - wdt_reg_write(disable_lock, DISABLE_LOCK_3); - if ((wdt_reg_read(disable_lock) & 0x3) != 0x3) - return -1; - - wdt_reg_write(disable, disable_value); - return 0; -} - -static int wdt_set_period(unsigned long msec) -{ - unsigned long change_value, count_value; - unsigned long prescale_value = 1; - unsigned long refclk_khz, maxdiv; - int ret; - - refclk_khz = clk_get_rate(TNETV107X_LPSC_WDT_ARM); - maxdiv = (MAX_DIV / refclk_khz); - - if ((!msec) || (msec > maxdiv)) - return -1; - - count_value = refclk_khz * msec; - if (count_value > 0xffff) { - change_value = count_value / 0xffff + 1; - prescale_value = count_value / change_value; - } else { - change_value = count_value; - } - - ret = write_prescale_reg(prescale_value - 1); - if (ret) - return ret; - - ret = write_change_reg(change_value); - if (ret) - return ret; - - return 0; -} - -unsigned long last_wdt = -1; - -int wdt_start(unsigned long msecs) -{ - int ret; - ret = wdt_control(0); - if (ret) - return ret; - ret = wdt_set_period(msecs); - if (ret) - return ret; - ret = wdt_control(1); - if (ret) - return ret; - ret = wdt_kick(); - last_wdt = msecs; - return ret; -} - -int wdt_stop(void) -{ - last_wdt = -1; - return wdt_control(0); -} - -int wdt_kick(void) -{ - wdt_reg_write(kick_lock, KICK_LOCK_1); - if ((wdt_reg_read(kick_lock) & 0x3) != 0x1) - return -1; - - wdt_reg_write(kick_lock, KICK_LOCK_2); - if ((wdt_reg_read(kick_lock) & 0x3) != 0x3) - return -1; - - wdt_reg_write(kick, 1); - return 0; -} - -void reset_cpu(ulong addr) -{ - clk_enable(TNETV107X_LPSC_WDT_ARM); - wdt_start(1); - wdt_kick(); -} -- cgit v1.1 From 7ee8c4795d0ab0f1cd25496bfbcdedb184ef5a8d Mon Sep 17 00:00:00 2001 From: gaurav rana Date: Wed, 25 Feb 2015 09:37:09 +0530 Subject: crypto/fsl: Make function names consistent for blob encapsulation/decapsulation. This patch does the following: 1. The function names for encapsulation and decapsulation were inconsitent in freescale's implementation and cmd_blob file. This patch corrects the issues. 2. The function protopye is also modified to change the length parameter from u8 to u32 to allow encapsulation and decapsulation of larger images. 3. Modified the description of km paramter in the command usage for better readability. Signed-off-by: Gaurav Rana Reviewed-by: Ruchika Gupta Reviewed-by: York Sun --- drivers/crypto/fsl/fsl_blob.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c index bc01075..9923bcb 100644 --- a/drivers/crypto/fsl/fsl_blob.c +++ b/drivers/crypto/fsl/fsl_blob.c @@ -11,7 +11,7 @@ #include "desc.h" #include "jr.h" -int blob_decrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len) +int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len) { int ret, i = 0; u32 *desc; @@ -36,7 +36,7 @@ int blob_decrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len) return ret; } -int blob_encrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len) +int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len) { int ret, i = 0; u32 *desc; -- cgit v1.1 From 94e3c8c4fd7bfe395fa467973cd647551d6d98c7 Mon Sep 17 00:00:00 2001 From: gaurav rana Date: Fri, 20 Feb 2015 12:51:46 +0530 Subject: crypto/fsl - Add progressive hashing support using hardware acceleration. Currently only normal hashing is supported using hardware acceleration. Added support for progressive hashing using hardware. Signed-off-by: Ruchika Gupta Signed-off-by: Gaurav Rana CC: Simon Glass Reviewed-by: Simon Glass Reviewed-by: York Sun --- drivers/crypto/fsl/fsl_hash.c | 138 +++++++++++++++++++++++++++++++++++++++++- drivers/crypto/fsl/fsl_hash.h | 34 +++++++++++ 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 drivers/crypto/fsl/fsl_hash.h (limited to 'drivers') diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c index d77f257..c298404 100644 --- a/drivers/crypto/fsl/fsl_hash.c +++ b/drivers/crypto/fsl/fsl_hash.c @@ -10,6 +10,9 @@ #include "jobdesc.h" #include "desc.h" #include "jr.h" +#include "fsl_hash.h" +#include +#include #define CRYPTO_MAX_ALG_NAME 80 #define SHA1_DIGEST_SIZE 20 @@ -39,6 +42,122 @@ static struct caam_hash_template driver_hash[] = { }, }; +static enum caam_hash_algos get_hash_type(struct hash_algo *algo) +{ + if (!strcmp(algo->name, driver_hash[SHA1].name)) + return SHA1; + else + return SHA256; +} + +/* Create the context for progressive hashing using h/w acceleration. + * + * @ctxp: Pointer to the pointer of the context for hashing + * @caam_algo: Enum for SHA1 or SHA256 + * @return 0 if ok, -ENOMEM on error + */ +static int caam_hash_init(void **ctxp, enum caam_hash_algos caam_algo) +{ + *ctxp = calloc(1, sizeof(struct sha_ctx)); + if (*ctxp == NULL) { + debug("Cannot allocate memory for context\n"); + return -ENOMEM; + } + return 0; +} + +/* + * Update sg table for progressive hashing using h/w acceleration + * + * The context is freed by this function if an error occurs. + * We support at most 32 Scatter/Gather Entries. + * + * @hash_ctx: Pointer to the context for hashing + * @buf: Pointer to the buffer being hashed + * @size: Size of the buffer being hashed + * @is_last: 1 if this is the last update; 0 otherwise + * @caam_algo: Enum for SHA1 or SHA256 + * @return 0 if ok, -EINVAL on error + */ +static int caam_hash_update(void *hash_ctx, const void *buf, + unsigned int size, int is_last, + enum caam_hash_algos caam_algo) +{ + uint32_t final = 0; + dma_addr_t addr = virt_to_phys((void *)buf); + struct sha_ctx *ctx = hash_ctx; + + if (ctx->sg_num >= MAX_SG_32) { + free(ctx); + return -EINVAL; + } + +#ifdef CONFIG_PHYS_64BIT + ctx->sg_tbl[ctx->sg_num].addr_hi = addr >> 32; +#else + ctx->sg_tbl[ctx->sg_num].addr_hi = 0x0; +#endif + ctx->sg_tbl[ctx->sg_num].addr_lo = addr; + + sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, + (size & SG_ENTRY_LENGTH_MASK)); + + ctx->sg_num++; + + if (is_last) { + final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | + SG_ENTRY_FINAL_BIT; + sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); + } + + return 0; +} + +/* + * Perform progressive hashing on the given buffer and copy hash at + * destination buffer + * + * The context is freed after completion of hash operation. + * + * @hash_ctx: Pointer to the context for hashing + * @dest_buf: Pointer to the destination buffer where hash is to be copied + * @size: Size of the buffer being hashed + * @caam_algo: Enum for SHA1 or SHA256 + * @return 0 if ok, -EINVAL on error + */ +static int caam_hash_finish(void *hash_ctx, void *dest_buf, + int size, enum caam_hash_algos caam_algo) +{ + uint32_t len = 0; + struct sha_ctx *ctx = hash_ctx; + int i = 0, ret = 0; + + if (size < driver_hash[caam_algo].digestsize) { + free(ctx); + return -EINVAL; + } + + for (i = 0; i < ctx->sg_num; i++) + len += (sec_in32(&ctx->sg_tbl[i].len_flag) & + SG_ENTRY_LENGTH_MASK); + + inline_cnstr_jobdesc_hash(ctx->sha_desc, (uint8_t *)ctx->sg_tbl, len, + ctx->hash, + driver_hash[caam_algo].alg_type, + driver_hash[caam_algo].digestsize, + 1); + + ret = run_descriptor_jr(ctx->sha_desc); + + if (ret) + debug("Error %x\n", ret); + else + memcpy(dest_buf, ctx->hash, sizeof(ctx->hash)); + + free(ctx); + return ret; +} + int caam_hash(const unsigned char *pbuf, unsigned int buf_len, unsigned char *pout, enum caam_hash_algos algo) { @@ -48,7 +167,7 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len, desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE); if (!desc) { debug("Not enough memory for descriptor allocation\n"); - return -1; + return -ENOMEM; } inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, @@ -75,3 +194,20 @@ void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, if (caam_hash(pbuf, buf_len, pout, SHA1)) printf("CAAM was not setup properly or it is faulty\n"); } + +int hw_sha_init(struct hash_algo *algo, void **ctxp) +{ + return caam_hash_init(ctxp, get_hash_type(algo)); +} + +int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, + unsigned int size, int is_last) +{ + return caam_hash_update(ctx, buf, size, is_last, get_hash_type(algo)); +} + +int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, + int size) +{ + return caam_hash_finish(ctx, dest_buf, size, get_hash_type(algo)); +} diff --git a/drivers/crypto/fsl/fsl_hash.h b/drivers/crypto/fsl/fsl_hash.h new file mode 100644 index 0000000..f5be651 --- /dev/null +++ b/drivers/crypto/fsl/fsl_hash.h @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#ifndef _SHA_H +#define _SHA_H + +#include +#include +#include "jr.h" + +/* We support at most 32 Scatter/Gather Entries.*/ +#define MAX_SG_32 32 + +/* + * Hash context contains the following fields + * @sha_desc: Sha Descriptor + * @sg_num: number of entries in sg table + * @len: total length of buffer + * @sg_tbl: sg entry table + * @hash: index to the hash calculated + */ +struct sha_ctx { + uint32_t sha_desc[64]; + uint32_t sg_num; + uint32_t len; + struct sg_entry sg_tbl[MAX_SG_32]; + u8 hash[HASH_MAX_DIGEST_SIZE]; +}; + +#endif -- cgit v1.1