Commit 1739564e authored by Tom Rini's avatar Tom Rini
Browse files

Merge git://git.denx.de/u-boot-dm



Conflicts:
	drivers/serial/serial-uclass.c
Signed-off-by: default avatarTom Rini <trini@ti.com>
parents 746667f1 17b28edb
......@@ -623,6 +623,120 @@ The following options need to be configured:
exists, unlike the similar options in the Linux kernel. Do not
set these options unless they apply!
- Driver Model
Driver model is a new framework for devices in U-Boot
introduced in early 2014. U-Boot is being progressively
moved over to this. It offers a consistent device structure,
supports grouping devices into classes and has built-in
handling of platform data and device tree.
To enable transition to driver model in a relatively
painful fashion, each subsystem can be independently
switched between the legacy/ad-hoc approach and the new
driver model using the options below. Also, many uclass
interfaces include compatibility features which may be
removed once the conversion of that subsystem is complete.
As a result, the API provided by the subsystem may in fact
not change with driver model.
See doc/driver-model/README.txt for more information.
CONFIG_DM
Enable 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.
CONFIG_CMD_DM
Enable driver model test commands. These allow you to print
out the driver model tree and the uclasses.
CONFIG_DM_DEMO
Enable some demo devices and the 'demo' command. These are
really only useful for playing around while trying to
understand driver model in sandbox.
CONFIG_SPL_DM
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_SERIAL
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_DM_GPIO
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.
CONFIG_DM_SPI
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.
CONFIG_DM_SPI_FLASH
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).
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
conversion is not yet possible.
** Code size options: The following options are enabled by
default except in SPL. Enable them explicitly to get these
features in SPL.
CONFIG_DM_WARN
Enable the dm_warn() function. This can use up quite a bit
of space for its strings.
CONFIG_DM_STDIO
Enable registering a serial device with the stdio library.
CONFIG_DM_DEVICE_REMOVE
Enable removing of devices.
- Linux Kernel Interface:
CONFIG_CLOCKS_IN_MHZ
......@@ -3870,6 +3984,11 @@ Configuration Settings:
Pre-relocation malloc() is only supported on ARM and sandbox
at present but is fairly easy to enable for other archs.
- CONFIG_SYS_MALLOC_SIMPLE
Provides a simple and small malloc() and calloc() for those
boards which do not use the full malloc in SPL (which is
enabled with CONFIG_SYS_SPL_MALLOC_START).
- CONFIG_SYS_BOOTM_LEN:
Normally compressed uImages are limited to an
uncompressed size of 8 MBytes. If this is not enough,
......
......@@ -7,6 +7,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/io.h>
#include <asm/arch/at91sam9260_matrix.h>
#include <asm/arch/at91_common.h>
......@@ -229,3 +230,16 @@ void at91_sdram_hw_init(void)
at91_set_a_periph(AT91_PIO_PORTC, 30, 0);
at91_set_a_periph(AT91_PIO_PORTC, 31, 0);
}
/* Platform data for the GPIOs */
static const struct at91_port_platdata at91sam9260_plat[] = {
{ ATMEL_BASE_PIOA, "PA" },
{ ATMEL_BASE_PIOB, "PB" },
{ ATMEL_BASE_PIOC, "PC" },
};
U_BOOT_DEVICES(at91sam9260_gpios) = {
{ "gpio_at91", &at91sam9260_plat[0] },
{ "gpio_at91", &at91sam9260_plat[1] },
{ "gpio_at91", &at91sam9260_plat[2] },
};
......@@ -34,6 +34,13 @@ SECTIONS
. = ALIGN(4);
. = .;
#ifdef CONFIG_SPL_DM
.u_boot_list : {
KEEP(*(SORT(.u_boot_list_*_driver_*)));
KEEP(*(SORT(.u_boot_list_*_uclass_*)));
}
#endif
. = ALIGN(4);
__image_copy_end = .;
......
......@@ -136,9 +136,11 @@
/*
* Other misc defines
*/
#ifndef CONFIG_DM_GPIO
#define ATMEL_PIO_PORTS 3 /* these SoCs have 3 PIO */
#define ATMEL_PMC_UHP AT91SAM926x_PMC_UHP
#define ATMEL_BASE_PIO ATMEL_BASE_PIOA
#endif
#define ATMEL_PMC_UHP AT91SAM926x_PMC_UHP
/*
* SoC specific defines
......
/*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _ATMEL_SERIAL_H
#define _ATMEL_SERIAL_H
/* Information about a serial port */
struct atmel_serial_platdata {
uint32_t base_addr;
};
#endif
......@@ -253,4 +253,10 @@ static inline unsigned at91_gpio_to_pin(unsigned gpio)
return gpio % 32;
}
/* Platform data for each GPIO port */
struct at91_port_platdata {
uint32_t base_addr;
const char *bank_name;
};
#endif /* __ASM_ARCH_AT91_GPIO_H */
......@@ -78,7 +78,7 @@ clr_gd:
strlo r0, [r1] /* clear 32-bit GD word */
addlo r1, r1, #4 /* move to next */
blo clr_gd
#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)
#if defined(CONFIG_SYS_MALLOC_F_LEN)
sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN
str sp, [r9, #GD_MALLOC_BASE]
#endif
......
SNAPPER9260 BOARD
M: Ryan Mallon <ryan@bluewatersys.com>
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/bluewater/snapper9260/
F: include/configs/snapper9260.h
......
......@@ -9,12 +9,15 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/arch/at91sam9260_matrix.h>
#include <asm/arch/at91sam9_smc.h>
#include <asm/arch/at91_common.h>
#include <asm/arch/at91_pmc.h>
#include <asm/arch/gpio.h>
#include <asm/arch/atmel_serial.h>
#include <net.h>
#include <netdev.h>
#include <i2c.h>
......@@ -95,10 +98,12 @@ static void nand_hw_init(void)
&smc->cs[3].mode);
/* Configure RDY/BSY */
at91_set_gpio_input(CONFIG_SYS_NAND_READY_PIN, 1);
gpio_request(CONFIG_SYS_NAND_READY_PIN, "nand_rdy");
gpio_direction_input(CONFIG_SYS_NAND_READY_PIN);
/* Enable NandFlash */
at91_set_gpio_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
gpio_request(CONFIG_SYS_NAND_ENABLE_PIN, "nand_ce");
gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
}
int board_init(void)
......@@ -140,3 +145,12 @@ int dram_init(void)
void reset_phy(void)
{
}
static struct atmel_serial_platdata at91sam9260_serial_plat = {
.base_addr = ATMEL_BASE_DBGU,
};
U_BOOT_DEVICE(at91sam9260_serial) = {
.name = "serial_atmel",
.platdata = &at91sam9260_serial_plat,
};
......@@ -6,6 +6,7 @@
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#include <linux/compiler.h>
#include <asm/io.h>
......@@ -43,6 +44,13 @@
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_SPL_BUILD
/* TODO(sjg@chromium.org): Remove once SPL supports device tree */
U_BOOT_DEVICE(tegra_gpios) = {
"gpio_tegra"
};
#endif
const struct tegra_sysinfo sysinfo = {
CONFIG_TEGRA_BOARD_STRING
};
......
......@@ -252,6 +252,9 @@ obj-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
obj-y += console.o
obj-$(CONFIG_CROS_EC) += cros_ec.o
obj-y += dlmalloc.o
ifdef CONFIG_SYS_MALLOC_F_LEN
obj-y += malloc_simple.o
endif
obj-y += image.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
......
......@@ -99,7 +99,8 @@ static int initr_trace(void)
static int initr_reloc(void)
{
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
/* tell others: relocation done */
gd->flags |= GD_FLG_RELOC | GD_FLG_FULL_MALLOC_INIT;
bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
return 0;
......
......@@ -198,6 +198,19 @@ static uint get_alen(char *arg)
return alen;
}
enum i2c_err_op {
I2C_ERR_READ,
I2C_ERR_WRITE,
};
static int i2c_report_err(int ret, enum i2c_err_op op)
{
printf("Error %s the chip: %d\n",
op == I2C_ERR_READ ? "reading" : "writing", ret);
return CMD_RET_FAILURE;
}
/**
* do_i2c_read() - Handle the "i2c read" command-line command
* @cmdtp: Command data struct pointer
......@@ -245,7 +258,7 @@ static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16);
if (i2c_read(chip, devaddr, alen, memaddr, length) != 0) {
puts ("Error reading the chip.\n");
i2c_report_err(-1, I2C_ERR_READ);
return 1;
}
return 0;
......@@ -286,8 +299,7 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
while (length-- > 0) {
if (i2c_write(chip, devaddr++, alen, memaddr++, 1) != 0) {
puts("Error writing to the chip.\n");
return 1;
return i2c_report_err(-1, I2C_ERR_WRITE);
}
/*
* No write delay with FRAM devices.
......@@ -370,7 +382,7 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
puts ("Error reading the chip.\n");
i2c_report_err(-1, I2C_ERR_READ);
else {
printf("%04x:", addr);
cp = linebuf;
......@@ -452,7 +464,7 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
while (count-- > 0) {
if (i2c_write(chip, addr++, alen, &byte, 1) != 0)
puts ("Error writing the chip.\n");
i2c_report_err(-1, I2C_ERR_WRITE);
/*
* Wait for the write to complete. The write can take
* up to 10mSec (we allow a little more time).
......@@ -528,7 +540,7 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
addr++;
}
if (err > 0)
puts ("Error reading the chip,\n");
i2c_report_err(-1, I2C_ERR_READ);
else
printf ("%08lx\n", crc);
......@@ -601,7 +613,7 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
do {
printf("%08lx:", addr);
if (i2c_read(chip, addr, alen, (uchar *)&data, size) != 0)
puts ("\nError reading the chip,\n");
i2c_report_err(-1, I2C_ERR_READ);
else {
data = cpu_to_be32(data);
if (size == 1)
......@@ -644,7 +656,7 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
*/
bootretry_reset_cmd_timeout();
if (i2c_write(chip, addr, alen, (uchar *)&data, size) != 0)
puts ("Error writing the chip.\n");
i2c_report_err(-1, I2C_ERR_WRITE);
#ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
#endif
......@@ -783,7 +795,7 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
*/
while (1) {
if (i2c_read(chip, addr, alen, bytes, length) != 0)
puts ("Error reading the chip.\n");
i2c_report_err(-1, I2C_ERR_READ);
udelay(delay);
}
......@@ -1341,7 +1353,7 @@ int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
chip = simple_strtoul(argv[1], NULL, 16);
if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
puts("Error reading EDID content.\n");
i2c_report_err(-1, I2C_ERR_READ);
return 1;
}
......
......@@ -2184,17 +2184,8 @@ Void_t* mALLOc(bytes) size_t bytes;
INTERNAL_SIZE_T nb;
#ifdef CONFIG_SYS_MALLOC_F_LEN
if (gd && !(gd->flags & GD_FLG_RELOC)) {
ulong new_ptr;
void *ptr;
new_ptr = gd->malloc_ptr + bytes;
if (new_ptr > gd->malloc_limit)
panic("Out of pre-reloc memory");
ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
return ptr;
}
if (gd && !(gd->flags & GD_FLG_FULL_MALLOC_INIT))
return malloc_simple(bytes);
#endif
/* check if mem_malloc_init() was run */
......@@ -2462,7 +2453,7 @@ void fREe(mem) Void_t* mem;
#ifdef CONFIG_SYS_MALLOC_F_LEN
/* free() is a no-op - all the memory will be freed on relocation */
if (!(gd->flags & GD_FLG_RELOC))
if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT))
return;
#endif
......@@ -2618,7 +2609,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
if (oldmem == NULL) return mALLOc(bytes);
#ifdef CONFIG_SYS_MALLOC_F_LEN
if (!(gd->flags & GD_FLG_RELOC)) {
if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
/* This is harder to support and should not be needed */
panic("pre-reloc realloc() is not supported");
}
......@@ -2970,7 +2961,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
else
{
#ifdef CONFIG_SYS_MALLOC_F_LEN
if (!(gd->flags & GD_FLG_RELOC)) {
if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
MALLOC_ZERO(mem, sz);
return mem;
}
......
/*
* Simple malloc implementation
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <malloc.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
void *malloc_simple(size_t bytes)
{
ulong new_ptr;
void *ptr;
new_ptr = gd->malloc_ptr + bytes;
if (new_ptr > gd->malloc_limit)
panic("Out of pre-reloc memory");
ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
return ptr;
}
#ifdef CONFIG_SYS_MALLOC_SIMPLE
void *calloc(size_t nmemb, size_t elem_size)
{
size_t size = nmemb * elem_size;
void *ptr;
ptr = malloc(size);
memset(ptr, '\0', size);
return ptr;
}
#endif
......@@ -7,6 +7,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <spl.h>
#include <asm/u-boot.h>
#include <nand.h>
......@@ -15,6 +16,7 @@
#include <i2c.h>
#include <image.h>
#include <malloc.h>
#include <dm/root.h>
#include <linux/compiler.h>
DECLARE_GLOBAL_DATA_PTR;
......@@ -139,9 +141,16 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
u32 boot_device;
debug(">>spl:board_init_r()\n");
#ifdef CONFIG_SYS_SPL_MALLOC_START
#if defined(CONFIG_SYS_SPL_MALLOC_START)
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
CONFIG_SYS_SPL_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
#elif defined(CONFIG_SYS_MALLOC_F_LEN)
gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_ptr = 0;
#endif
#ifdef CONFIG_SPL_DM
dm_init_and_scan(true);
#endif
#ifndef CONFIG_PPC
......@@ -240,6 +249,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
default:
debug("Unsupported OS image.. Jumping nevertheless..\n");
}
#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE)
debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr,
gd->malloc_ptr / 1024);
#endif
jump_to_image_no_args(&spl_image);
}
......
......@@ -750,19 +750,43 @@ device pointers, but this is not currently implemented (the root device
pointer is saved but not made available through the driver model API).
Things to punt for later
------------------------
SPL Support
-----------
Driver model can operate in SPL. Its efficient implementation and small code
size provide for a small overhead which is acceptable for all but the most
constrained systems.
To enable driver model in SPL, define CONFIG_SPL_DM. You might want to
consider the following option also. See the main README for more details.
- CONFIG_SYS_MALLOC_SIMPLE
- CONFIG_DM_WARN
- CONFIG_DM_DEVICE_REMOVE
- CONFIG_DM_STDIO
- SPL support - this will have to be present before many drivers can be
converted, but it seems like we can add it once we are happy with the
core implementation.
That is not to say that no thinking has gone into this - in fact there
is quite a lot there. However, getting these right is non-trivial and
there is a high cost associated with going down the wrong path.
Enabling Driver Model
---------------------
For SPL, it may be possible to fit in a simplified driver model with only
bind and probe methods, to reduce size.
Driver model is being brought into U-Boot gradually. As each subsystems gets
support, a uclass is created and a CONFIG to enable use of driver model for
that subsystem.
For example CONFIG_DM_SERIAL enables driver model for serial. With that
defined, the old serial support is not enabled, and your serial driver must
conform to driver model. With that undefined, the old serial support is
enabled and driver model is not available for serial. This means that when
you convert a driver, you must either convert all its boards, or provide for
the driver to be compiled both with and without driver model (generally this
is not very hard).
See the main README for full details of the available driver model CONFIG
options.
Things to punt for later
------------------------
Uclasses are statically numbered at compile time. It would be possible to
change this to dynamic numbering, but then we would require some sort of
......
......@@ -4,5 +4,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y := device.o lists.o root.o uclass.o util.o
obj-$(CONFIG_DM) += device.o lists.o root.o uclass.o util.o
obj-$(CONFIG_OF_CONTROL) += simple-bus.o
obj-$(CONFIG_DM_DEVICE_REMOVE) += device-remove.o
/*
* Device manager
*
* Copyright (c) 2014 Google, Inc
*
* (C) Copyright 2012
* Pavel Herrmann <morpheus.ibis@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>