summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTom Rini <trini@ti.com>2014-10-22 13:51:45 -0400
committerTom Rini <trini@ti.com>2014-10-22 13:51:45 -0400
commit68e80fdda1336068f40915388bbdacfd2b75233a (patch)
treedeb28e65fdd601e47bf5564f67da3035a840e284 /include
parent35d4fed320d577a4446531d7b9350ce40065c4b0 (diff)
parent8a9cd5ad6f89ab721a352cbb9264bea5ede68789 (diff)
downloadblackbird-obmc-uboot-68e80fdda1336068f40915388bbdacfd2b75233a.tar.gz
blackbird-obmc-uboot-68e80fdda1336068f40915388bbdacfd2b75233a.zip
Merge git://git.denx.de/u-boot-dm
Diffstat (limited to 'include')
-rw-r--r--include/configs/cm_fx6.h11
-rw-r--r--include/configs/exynos-common.h7
-rw-r--r--include/configs/peach-pit.h1
-rw-r--r--include/configs/rpi_b.h5
-rw-r--r--include/configs/s5p_goni.h8
-rw-r--r--include/configs/s5pc210_universal.h12
-rw-r--r--include/configs/sacsng.h1
-rw-r--r--include/configs/sandbox.h5
-rw-r--r--include/configs/smdkc100.h6
-rw-r--r--include/configs/tegra-common-post.h2
-rw-r--r--include/configs/tegra-common.h2
-rw-r--r--include/configs/zipitz2.h1
-rw-r--r--include/cros_ec.h27
-rw-r--r--include/dm/device-internal.h13
-rw-r--r--include/dm/device.h31
-rw-r--r--include/dm/lists.h4
-rw-r--r--include/dm/platdata.h8
-rw-r--r--include/dm/uclass-id.h6
-rw-r--r--include/dm/uclass.h1
-rw-r--r--include/dm/util.h1
-rw-r--r--include/linker_lists.h23
-rw-r--r--include/serial_mxc.h14
-rw-r--r--include/serial_pl01x.h27
-rw-r--r--include/spi.h299
-rw-r--r--include/spi_flash.h127
25 files changed, 566 insertions, 76 deletions
diff --git a/include/configs/cm_fx6.h b/include/configs/cm_fx6.h
index 7cf241e31d..a20c373321 100644
--- a/include/configs/cm_fx6.h
+++ b/include/configs/cm_fx6.h
@@ -21,6 +21,17 @@
#define CONFIG_MACH_TYPE 4273
#define CONFIG_SYS_HZ 1000
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+
+#define CONFIG_DM_GPIO
+#define CONFIG_CMD_GPIO
+
+#define CONFIG_DM_SERIAL
+#define CONFIG_SYS_MALLOC_F_LEN (1 << 10)
+#endif
+
/* Display information on boot */
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_DISPLAY_BOARDINFO
diff --git a/include/configs/exynos-common.h b/include/configs/exynos-common.h
index 371f32d840..6ba9bb7a1b 100644
--- a/include/configs/exynos-common.h
+++ b/include/configs/exynos-common.h
@@ -17,6 +17,13 @@
#include <linux/sizes.h>
#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
+
#define CONFIG_ARCH_CPU_INIT
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_DISPLAY_BOARDINFO
diff --git a/include/configs/peach-pit.h b/include/configs/peach-pit.h
index ab8ac60df2..91bd37d6bc 100644
--- a/include/configs/peach-pit.h
+++ b/include/configs/peach-pit.h
@@ -38,6 +38,7 @@
#define CONFIG_POWER_TPS65090_EC
#define CONFIG_CROS_EC_SPI /* Support CROS_EC over SPI */
+#define CONFIG_DM_CROS_EC
#define CONFIG_USB_XHCI
#define CONFIG_USB_XHCI_EXYNOS
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index 2d69809480..d9475e950b 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -31,6 +31,11 @@
*/
#define CONFIG_MACH_TYPE MACH_TYPE_BCM2708
+/* Enable driver model */
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+
/* Memory layout */
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_SYS_SDRAM_BASE 0x00000000
diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h
index 0c6e9c7878..3633a355bd 100644
--- a/include/configs/s5p_goni.h
+++ b/include/configs/s5p_goni.h
@@ -276,6 +276,8 @@
#define CONFIG_SYS_I2C_SOFT_SPEED 50000
#define CONFIG_SYS_I2C_SOFT_SLAVE 0x7F
#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_SYS_I2C_INIT_BOARD
+
#define CONFIG_SYS_MAX_I2C_BUS 7
#define CONFIG_USB_GADGET
#define CONFIG_USB_GADGET_S3C_UDC_OTG
@@ -286,4 +288,10 @@
#define CONFIG_OF_LIBFDT
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+
#endif /* __CONFIG_H */
diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h
index 27f3d0af47..4b30d148c3 100644
--- a/include/configs/s5pc210_universal.h
+++ b/include/configs/s5pc210_universal.h
@@ -187,17 +187,7 @@
* SPI Settings
*/
#define CONFIG_SOFT_SPI
-#define CONFIG_SOFT_SPI_MODE SPI_MODE_3
-#define CONFIG_SOFT_SPI_GPIO_SCLK EXYNOS4_GPIO_Y31
-#define CONFIG_SOFT_SPI_GPIO_MOSI EXYNOS4_GPIO_Y33
-#define CONFIG_SOFT_SPI_GPIO_MISO EXYNOS4_GPIO_Y30
-#define CONFIG_SOFT_SPI_GPIO_CS EXYNOS4_GPIO_Y43
-
-#define SPI_DELAY udelay(1)
-#undef SPI_INIT
-#define SPI_SCL(bit) universal_spi_scl(bit)
-#define SPI_SDA(bit) universal_spi_sda(bit)
-#define SPI_READ universal_spi_read()
+
#ifndef __ASSEMBLY__
void universal_spi_scl(int bit);
void universal_spi_sda(int bit);
diff --git a/include/configs/sacsng.h b/include/configs/sacsng.h
index b5064ab37c..2dee315f91 100644
--- a/include/configs/sacsng.h
+++ b/include/configs/sacsng.h
@@ -259,7 +259,6 @@
#define I2C_MOSI 0x00004000 /* PD 17: Master Out, Slave In */
#define I2C_MISO 0x00008000 /* PD 16: Master In, Slave Out */
-#undef SPI_INIT /* no port initialization needed */
#define SPI_READ ((immr->im_ioport.iop_pdatd & I2C_MISO) != 0)
#define SPI_SDA(bit) do { \
if(bit) immr->im_ioport.iop_pdatd |= I2C_MOSI; \
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 022629f522..ee4b24473c 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -32,6 +32,7 @@
#define CONFIG_DM_GPIO
#define CONFIG_DM_TEST
#define CONFIG_DM_SERIAL
+#define CONFIG_DM_CROS_EC
#define CONFIG_SYS_STDIO_DEREGISTER
@@ -97,8 +98,8 @@
#define CONFIG_CMD_SF_TEST
#define CONFIG_CMD_SPI
#define CONFIG_SPI_FLASH
-#define CONFIG_OF_SPI
-#define CONFIG_OF_SPI_FLASH
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
#define CONFIG_SPI_FLASH_ATMEL
#define CONFIG_SPI_FLASH_EON
#define CONFIG_SPI_FLASH_GIGADEVICE
diff --git a/include/configs/smdkc100.h b/include/configs/smdkc100.h
index 22835ffd64..982d0dcea3 100644
--- a/include/configs/smdkc100.h
+++ b/include/configs/smdkc100.h
@@ -223,4 +223,10 @@
#define CONFIG_OF_LIBFDT
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+
#endif /* __CONFIG_H */
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index 23e3c8af31..a258699af7 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -59,7 +59,7 @@
BOARD_EXTRA_ENV_SETTINGS
#if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK) || defined(CONFIG_TEGRA114_SPI)
-#define CONFIG_FDT_SPI
+#define CONFIG_TEGRA_SPI
#endif
/* overrides for SPL build here */
diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index 834b3d5686..4719ee10ae 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -24,6 +24,8 @@
#ifndef CONFIG_SPL_BUILD
#define CONFIG_DM_SERIAL
#endif
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
#define CONFIG_SYS_TIMER_RATE 1000000
#define CONFIG_SYS_TIMER_COUNTER NV_PA_TMRUS_BASE
diff --git a/include/configs/zipitz2.h b/include/configs/zipitz2.h
index 41a7c99edc..fe331bc082 100644
--- a/include/configs/zipitz2.h
+++ b/include/configs/zipitz2.h
@@ -99,7 +99,6 @@
#define CONFIG_VIDEO_BMP_GZIP
#define CONFIG_VIDEO_BMP_RLE8
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (2 << 20)
-#undef SPI_INIT
#define SPI_DELAY udelay(10)
#define SPI_SDA(val) zipitz2_spi_sda(val)
diff --git a/include/cros_ec.h b/include/cros_ec.h
index 1e4d8db96b..9e13146ecb 100644
--- a/include/cros_ec.h
+++ b/include/cros_ec.h
@@ -14,6 +14,7 @@
#include <fdtdec.h>
#include <cros_ec_message.h>
+#ifndef CONFIG_DM_CROS_EC
/* Which interface is the device on? */
enum cros_ec_interface_t {
CROS_EC_IF_NONE,
@@ -22,9 +23,13 @@ enum cros_ec_interface_t {
CROS_EC_IF_LPC, /* Intel Low Pin Count interface */
CROS_EC_IF_SANDBOX,
};
+#endif
/* Our configuration information */
struct cros_ec_dev {
+#ifdef CONFIG_DM_CROS_EC
+ struct udevice *dev; /* Transport device */
+#else
enum cros_ec_interface_t interface;
struct spi_slave *spi; /* Our SPI slave, if using SPI */
int node; /* Our node */
@@ -33,6 +38,7 @@ struct cros_ec_dev {
unsigned int addr; /* Device address (for I2C) */
unsigned int bus_num; /* Bus number (for I2C) */
unsigned int max_frequency; /* Maximum interface frequency */
+#endif
struct fdt_gpio_state ec_int; /* GPIO used as EC interrupt line */
int protocol_version; /* Protocol version to use */
int optimise_flash_write; /* Don't write erased flash blocks */
@@ -233,6 +239,22 @@ int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
*/
struct cros_ec_dev *board_get_cros_ec_dev(void);
+#ifdef CONFIG_DM_CROS_EC
+
+struct dm_cros_ec_ops {
+ int (*check_version)(struct udevice *dev);
+ int (*command)(struct udevice *dev, uint8_t cmd, int cmd_version,
+ const uint8_t *dout, int dout_len,
+ uint8_t **dinp, int din_len);
+ int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
+};
+
+#define dm_cros_ec_get_ops(dev) \
+ ((struct dm_cros_ec_ops *)(dev)->driver->ops)
+
+int cros_ec_register(struct udevice *dev);
+
+#else /* !CONFIG_DM_CROS_EC */
/* Internal interfaces */
int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob);
@@ -336,6 +358,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes);
int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
int in_bytes);
+#endif
/**
* Dump a block of data for a command.
@@ -489,9 +512,11 @@ int cros_ec_get_error(void);
* Returns information from the FDT about the Chrome EC flash
*
* @param blob FDT blob to use
+ * @param node Node offset to read from
* @param config Structure to use to return information
*/
-int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config);
+int cros_ec_decode_ec_flash(const void *blob, int node,
+ struct fdt_cros_ec *config);
/**
* Check the current keyboard state, in case recovery mode is requested.
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 7005d03d08..44cb7ef93b 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -66,6 +66,19 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
int device_probe(struct udevice *dev);
/**
+ * device_probe() - Probe a child device, activating it
+ *
+ * Activate a device so that it is ready for use. All its parents are probed
+ * first. The child is provided with parent data if parent_priv is not NULL.
+ *
+ * @dev: Pointer to device to probe
+ * @parent_priv: Pointer to parent data. If non-NULL then this is provided to
+ * the child.
+ * @return 0 if OK, -ve on error
+ */
+int device_probe_child(struct udevice *dev, void *parent_priv);
+
+/**
* device_remove() - Remove a device, de-activating it
*
* De-activate a device so that it is no longer ready for use. All its
diff --git a/include/dm/device.h b/include/dm/device.h
index c8a4072bcf..9ce95a834e 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -57,7 +57,8 @@ struct driver_info;
* @sibling_node: Next device in list of all devices
* @flags: Flags for this device DM_FLAG_...
* @req_seq: Requested sequence number for this device (-1 = any)
- * @seq: Allocated sequence number for this device (-1 = none)
+ * @seq: Allocated sequence number for this device (-1 = none). This is set up
+ * when the device is probed and will be unique within the device's uclass.
*/
struct udevice {
struct driver *driver;
@@ -96,6 +97,12 @@ struct udevice_id {
ulong data;
};
+#ifdef CONFIG_OF_CONTROL
+#define of_match_ptr(_ptr) (_ptr)
+#else
+#define of_match_ptr(_ptr) NULL
+#endif /* CONFIG_OF_CONTROL */
+
/**
* struct driver - A driver for a feature or peripheral
*
@@ -133,6 +140,10 @@ struct udevice_id {
* @per_child_auto_alloc_size: Each device can hold private data owned by
* its parent. If required this will be automatically allocated if this
* value is non-zero.
+ * TODO(sjg@chromium.org): I'm considering dropping this, and just having
+ * device_probe_child() pass it in. So far the use case for allocating it
+ * is SPI, but I found that unsatisfactory. Since it is here I will leave it
+ * until things are clearer.
* @ops: Driver-specific operations. This is typically a list of function
* pointers defined by the driver, to implement driver functions required by
* the uclass.
@@ -274,4 +285,22 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
int device_get_child_by_of_offset(struct udevice *parent, int seq,
struct udevice **devp);
+/**
+ * device_find_first_child() - Find the first child of a device
+ *
+ * @parent: Parent device to search
+ * @devp: Returns first child device, or NULL if none
+ * @return 0
+ */
+int device_find_first_child(struct udevice *parent, struct udevice **devp);
+
+/**
+ * device_find_first_child() - Find the first child of a device
+ *
+ * @devp: Pointer to previous child device on entry. Returns pointer to next
+ * child device, or NULL if none
+ * @return 0
+ */
+int device_find_next_child(struct udevice **devp);
+
#endif
diff --git a/include/dm/lists.h b/include/dm/lists.h
index 2356895246..704e33e37f 100644
--- a/include/dm/lists.h
+++ b/include/dm/lists.h
@@ -38,7 +38,7 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id);
* This searches the U_BOOT_DEVICE() structures and creates new devices for
* each one. The devices will have @parent as their parent.
*
- * @parent: parent driver (root)
+ * @parent: parent device (root)
* @early_only: If true, bind only drivers with the DM_INIT_F flag. If false
* bind all drivers.
*/
@@ -50,7 +50,7 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only);
* This creates a new device bound to the given device tree node, with
* @parent as its parent.
*
- * @parent: parent driver (root)
+ * @parent: parent device (root)
* @blob: device tree blob
* @offset: offset of this device tree node
* @devp: if non-NULL, returns a pointer to the bound device
diff --git a/include/dm/platdata.h b/include/dm/platdata.h
index 2bc8b147ed..fbc8a6b3ad 100644
--- a/include/dm/platdata.h
+++ b/include/dm/platdata.h
@@ -11,10 +11,12 @@
#ifndef _DM_PLATDATA_H
#define _DM_PLATDATA_H
+#include <linker_lists.h>
+
/**
* struct driver_info - Information required to instantiate a device
*
- * @name: Device name
+ * @name: Driver name
* @platdata: Driver-specific platform data
*/
struct driver_info {
@@ -25,4 +27,8 @@ struct driver_info {
#define U_BOOT_DEVICE(__name) \
ll_entry_declare(struct driver_info, __name, driver_info)
+/* Declare a list of devices. The argument is a driver_info[] array */
+#define U_BOOT_DEVICES(__name) \
+ ll_entry_declare_list(struct driver_info, __name, driver_info)
+
#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 7f0e37b7b7..a8944c97d0 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -18,10 +18,16 @@ enum uclass_id {
UCLASS_TEST,
UCLASS_TEST_FDT,
UCLASS_TEST_BUS,
+ UCLASS_SPI_EMUL, /* sandbox SPI device emulator */
+ UCLASS_SIMPLE_BUS,
/* U-Boot uclasses start here */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
UCLASS_SERIAL, /* Serial UART */
+ UCLASS_SPI, /* SPI bus */
+ UCLASS_SPI_GENERIC, /* Generic SPI flash target */
+ UCLASS_SPI_FLASH, /* SPI flash */
+ UCLASS_CROS_EC, /* Chrome OS EC */
UCLASS_COUNT,
UCLASS_INVALID = -1,
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 8d09ecff7b..f6ec6d7e9f 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -11,6 +11,7 @@
#define _DM_UCLASS_H
#include <dm/uclass-id.h>
+#include <linker_lists.h>
#include <linux/list.h>
/**
diff --git a/include/dm/util.h b/include/dm/util.h
index 8be64a921d..6ac3a38ef0 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -5,6 +5,7 @@
*/
#ifndef __DM_UTIL_H
+#define __DM_UTIL_H
void dm_warn(const char *fmt, ...);
diff --git a/include/linker_lists.h b/include/linker_lists.h
index 507d61ba9a..d37fba44dc 100644
--- a/include/linker_lists.h
+++ b/include/linker_lists.h
@@ -11,6 +11,8 @@
#ifndef __LINKER_LISTS_H__
#define __LINKER_LISTS_H__
+#include <linux/compiler.h>
+
/*
* There is no use in including this from ASM files, but that happens
* anyway, e.g. PPC kgdb.S includes command.h which incluse us.
@@ -141,6 +143,27 @@
section(".u_boot_list_2_"#_list"_2_"#_name)))
/**
+ * ll_entry_declare_list() - Declare a list of link-generated array entries
+ * @_type: Data type of each entry
+ * @_name: Name of the entry
+ * @_list: name of the list. Should contain only characters allowed
+ * in a C variable name!
+ *
+ * This is like ll_entry_declare() but creates multiple entries. It should
+ * be assigned to an array.
+ *
+ * ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = {
+ * { .x = 3, .y = 4 },
+ * { .x = 8, .y = 2 },
+ * { .x = 1, .y = 7 }
+ * };
+ */
+#define ll_entry_declare_list(_type, _name, _list) \
+ _type _u_boot_list_2_##_list##_2_##_name[] __aligned(4) \
+ __attribute__((unused, \
+ section(".u_boot_list_2_"#_list"_2_"#_name)))
+
+/**
* We need a 0-byte-size type for iterator symbols, and the compiler
* does not allow defining objects of C type 'void'. Using an empty
* struct is allowed by the compiler, but causes gcc versions 4.4 and
diff --git a/include/serial_mxc.h b/include/serial_mxc.h
new file mode 100644
index 0000000000..7d3ace2f9e
--- /dev/null
+++ b/include/serial_mxc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __serial_mxc_h
+#define __serial_mxc_h
+
+/* Information about a serial port */
+struct mxc_serial_platdata {
+ struct mxc_uart *reg; /* address of registers in physical memory */
+};
+
+#endif
diff --git a/include/serial_pl01x.h b/include/serial_pl01x.h
new file mode 100644
index 0000000000..5e068f390b
--- /dev/null
+++ b/include/serial_pl01x.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __serial_pl01x_h
+#define __serial_pl01x_h
+
+enum pl01x_type {
+ TYPE_PL010,
+ TYPE_PL011,
+};
+
+/*
+ *Information about a serial port
+ *
+ * @base: Register base address
+ * @type: Port type
+ * @clock: Input clock rate, used for calculating the baud rate divisor
+ */
+struct pl01x_serial_platdata {
+ unsigned long base;
+ enum pl01x_type type;
+ unsigned int clock;
+};
+
+#endif
diff --git a/include/spi.h b/include/spi.h
index b673be270c..aa0a48ea62 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -54,12 +54,31 @@
#define SPI_DEFAULT_WORDLEN 8
+#ifdef CONFIG_DM_SPI
+struct dm_spi_bus {
+ uint max_hz;
+};
+
+#endif /* CONFIG_DM_SPI */
+
/**
* struct spi_slave - Representation of a SPI slave
*
- * Drivers are expected to extend this with controller-specific data.
+ * For driver model this is the per-child data used by the SPI bus. It can
+ * be accessed using dev_get_parentdata() on the slave device. Each SPI
+ * driver should define this child data in its U_BOOT_DRIVER() definition:
+ *
+ * .per_child_auto_alloc_size = sizeof(struct spi_slave),
*
- * @bus: ID of the bus that the slave is attached to.
+ * If not using driver model, drivers are expected to extend this with
+ * controller-specific data.
+ *
+ * @dev: SPI slave device
+ * @max_hz: Maximum speed for this slave
+ * @mode: SPI mode to use for this slave (see SPI mode flags)
+ * @bus: ID of the bus that the slave is attached to. For
+ * driver model this is the sequence number of the SPI
+ * bus (bus->seq) so does not need to be stored
* @cs: ID of the chip select connected to the slave.
* @op_mode_rx: SPI RX operation mode.
* @op_mode_tx: SPI TX operation mode.
@@ -71,7 +90,13 @@
* @flags: Indication of SPI flags.
*/
struct spi_slave {
+#ifdef CONFIG_DM_SPI
+ struct udevice *dev; /* struct spi_slave is dev->parentdata */
+ uint max_hz;
+ uint mode;
+#else
unsigned int bus;
+#endif
unsigned int cs;
u8 op_mode_rx;
u8 op_mode_tx;
@@ -228,8 +253,9 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
* Returns: 1 if bus:cs identifies a valid chip on this board, 0
* otherwise.
*/
-int spi_cs_is_valid(unsigned int bus, unsigned int cs);
+int spi_cs_is_valid(unsigned int bus, unsigned int cs);
+#ifndef CONFIG_DM_SPI
/**
* Activate a SPI chipselect.
* This function is provided by the board code when using a driver
@@ -255,6 +281,7 @@ void spi_cs_deactivate(struct spi_slave *slave);
* @hz: The transfer speed
*/
void spi_set_speed(struct spi_slave *slave, uint hz);
+#endif
/**
* Write 8 bits, then read 8 bits.
@@ -305,4 +332,270 @@ struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
int node);
+#ifdef CONFIG_DM_SPI
+
+/**
+ * struct spi_cs_info - Information about a bus chip select
+ *
+ * @dev: Connected device, or NULL if none
+ */
+struct spi_cs_info {
+ struct udevice *dev;
+};
+
+/**
+ * struct struct dm_spi_ops - Driver model SPI operations
+ *
+ * The uclass interface is implemented by all SPI devices which use
+ * driver model.
+ */
+struct dm_spi_ops {
+ /**
+ * Claim the bus and prepare it for communication.
+ *
+ * The device provided is the slave device. It's parent controller
+ * will be used to provide the communication.
+ *
+ * This must be called before doing any transfers with a SPI slave. It
+ * will enable and initialize any SPI hardware as necessary, and make
+ * sure that the SCK line is in the correct idle state. It is not
+ * allowed to claim the same bus for several slaves without releasing
+ * the bus in between.
+ *
+ * @bus: The SPI slave
+ *
+ * Returns: 0 if the bus was claimed successfully, or a negative value
+ * if it wasn't.
+ */
+ int (*claim_bus)(struct udevice *bus);
+
+ /**
+ * Release the SPI bus
+ *
+ * This must be called once for every call to spi_claim_bus() after
+ * all transfers have finished. It may disable any SPI hardware as
+ * appropriate.
+ *
+ * @bus: The SPI slave
+ */
+ int (*release_bus)(struct udevice *bus);
+
+ /**
+ * Set the word length for SPI transactions
+ *
+ * Set the word length (number of bits per word) for SPI transactions.
+ *
+ * @bus: The SPI slave
+ * @wordlen: The number of bits in a word
+ *
+ * Returns: 0 on success, -ve on failure.
+ */
+ int (*set_wordlen)(struct udevice *bus, unsigned int wordlen);
+
+ /**
+ * SPI transfer
+ *
+ * This writes "bitlen" bits out the SPI MOSI port and simultaneously
+ * clocks "bitlen" bits in the SPI MISO port. That's just the way SPI
+ * works.
+ *
+ * The source of the outgoing bits is the "dout" parameter and the
+ * destination of the input bits is the "din" parameter. Note that
+ * "dout" and "din" can point to the same memory location, in which
+ * case the input data overwrites the output data (since both are
+ * buffered by temporary variables, this is OK).
+ *
+ * spi_xfer() interface:
+ * @dev: The slave device to communicate with
+ * @bitlen: How many bits to write and read.
+ * @dout: Pointer to a string of bits to send out. The bits are
+ * held in a byte array and are sent MSB first.
+ * @din: Pointer to a string of bits that will be filled in.
+ * @flags: A bitwise combination of SPI_XFER_* flags.
+ *
+ * Returns: 0 on success, not -1 on failure
+ */
+ int (*xfer)(struct udevice *dev, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags);
+
+ /**
+ * Set transfer speed.
+ * This sets a new speed to be applied for next spi_xfer().
+ * @bus: The SPI bus
+ * @hz: The transfer speed
+ * @return 0 if OK, -ve on error
+ */
+ int (*set_speed)(struct udevice *bus, uint hz);
+
+ /**
+ * Set the SPI mode/flags
+ *
+ * It is unclear if we want to set speed and mode together instead
+ * of separately.
+ *
+ * @bus: The SPI bus
+ * @mode: Requested SPI mode (SPI_... flags)
+ * @return 0 if OK, -ve on error
+ */
+ int (*set_mode)(struct udevice *bus, uint mode);
+
+ /**
+ * Get information on a chip select
+ *
+ * This is only called when the SPI uclass does not know about a
+ * chip select, i.e. it has no attached device. It gives the driver
+ * a chance to allow activity on that chip select even so.
+ *
+ * @bus: The SPI bus
+ * @cs: The chip select (0..n-1)
+ * @info: Returns information about the chip select, if valid.
+ * On entry info->dev is NULL
+ * @return 0 if OK (and @info is set up), -ENODEV if the chip select
+ * is invalid, other -ve value on error
+ */
+ int (*cs_info)(struct udevice *bus, uint cs, struct spi_cs_info *info);
+};
+
+struct dm_spi_emul_ops {
+ /**
+ * SPI transfer
+ *
+ * This writes "bitlen" bits out the SPI MOSI port and simultaneously
+ * clocks "bitlen" bits in the SPI MISO port. That's just the way SPI
+ * works. Here the device is a slave.
+ *
+ * The source of the outgoing bits is the "dout" parameter and the
+ * destination of the input bits is the "din" parameter. Note that
+ * "dout" and "din" can point to the same memory location, in which
+ * case the input data overwrites the output data (since both are
+ * buffered by temporary variables, this is OK).
+ *
+ * spi_xfer() interface:
+ * @slave: The SPI slave which will be sending/receiving the data.
+ * @bitlen: How many bits to write and read.
+ * @dout: Pointer to a string of bits sent to the device. The
+ * bits are held in a byte array and are sent MSB first.
+ * @din: Pointer to a string of bits that will be sent back to
+ * the master.
+ * @flags: A bitwise combination of SPI_XFER_* flags.
+ *
+ * Returns: 0 on success, not -1 on failure
+ */
+ int (*xfer)(struct udevice *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags);
+};
+
+/**
+ * spi_find_bus_and_cs() - Find bus and slave devices by number
+ *
+ * Given a bus number and chip select, this finds the corresponding bus
+ * device and slave device. Neither device is activated by this function,
+ * although they may have been activated previously.
+ *
+ * @busnum: SPI bus number
+ * @cs: Chip select to look for
+ * @busp: Returns bus device
+ * @devp: Return slave device
+ * @return 0 if found, -ENODEV on error
+ */
+int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
+ struct udevice **devp);
+
+/**
+ * spi_get_bus_and_cs() - Find and activate bus and slave devices by number
+ *
+ * Given a bus number and chip select, this finds the corresponding bus
+ * device and slave device.
+ *
+ * If no such slave exists, and drv_name is not NULL, then a new slave device
+ * is automatically bound on this chip select.
+ *
+ * Ths new slave device is probed ready for use with the given speed and mode.
+ *
+ * @busnum: SPI bus number
+ * @cs: Chip select to look for
+ * @speed: SPI speed to use for this slave
+ * @mode: SPI mode to use for this slave
+ * @drv_name: Name of driver to attach to this chip select
+ * @dev_name: Name of the new device thus created
+ * @busp: Returns bus device
+ * @devp: Return slave device
+ * @return 0 if found, -ve on error
+ */
+int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
+ const char *drv_name, const char *dev_name,
+ struct udevice **busp, struct spi_slave **devp);
+
+/**
+ * spi_chip_select() - Get the chip select for a slave
+ *
+ * @return the chip select this slave is attached to
+ */
+int spi_chip_select(struct udevice *slave);
+
+/**
+ * spi_bind_device() - bind a device to a bus's chip select
+ *
+ * This binds a new device to an given chip select (which must be unused).
+ *
+ * @bus: SPI bus to search
+ * @cs: Chip select to attach to
+ * @drv_name: Name of driver to attach to this chip select
+ * @dev_name: Name of the new device thus created
+ * @devp: Returns the newly bound device
+ */
+int spi_bind_device(struct udevice *bus, int cs, const char *drv_name,
+ const char *dev_name, struct udevice **devp);
+
+/**
+ * spi_ofdata_to_platdata() - decode standard SPI platform data
+ *
+ * This decodes the speed and mode from a device tree node and puts it into
+ * the spi_slave structure.
+ *
+ * @blob: Device tree blob
+ * @node: Node offset to read from
+ * @spi: Place to put the decoded information
+ */
+int spi_ofdata_to_platdata(const void *blob, int node, struct spi_slave *spi);
+
+/**
+ * spi_cs_info() - Check information on a chip select
+ *
+ * This checks a particular chip select on a bus to see if it has a device
+ * attached, or is even valid.
+ *
+ * @bus: The SPI bus
+ * @cs: The chip select (0..n-1)
+ * @info: Returns information about the chip select, if valid
+ * @return 0 if OK (and @info is set up), -ENODEV if the chip select
+ * is invalid, other -ve value on error
+ */
+int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info);
+
+struct sandbox_state;
+
+/**
+ * sandbox_spi_get_emul() - get an emulator for a SPI slave
+ *
+ * This provides a way to attach an emulated SPI device to a particular SPI
+ * slave, so that xfer() operations on the slave will be handled by the
+ * emulator. If a emulator already exists on that chip select it is returned.
+ * Otherwise one is created.
+ *
+ * @state: Sandbox state
+ * @bus: SPI bus requesting the emulator
+ * @slave: SPI slave device requesting the emulator
+ * @emuip: Returns pointer to emulator
+ * @return 0 if OK, -ve on error
+ */
+int sandbox_spi_get_emul(struct sandbox_state *state,
+ struct udevice *bus, struct udevice *slave,
+ struct udevice **emulp);
+
+/* Access the serial operations for a device */
+#define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops)
+#define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops)
+#endif /* CONFIG_DM_SPI */
+
#endif /* _SPI_H_ */
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 408a5b401c..5913b39e26 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -15,9 +15,8 @@
#ifndef _SPI_FLASH_H_
#define _SPI_FLASH_H_
-#include <spi.h>
+#include <dm.h> /* Because we dereference struct udevice here */
#include <linux/types.h>
-#include <linux/compiler.h>
#ifndef CONFIG_SF_DEFAULT_SPEED
# define CONFIG_SF_DEFAULT_SPEED 1000000
@@ -32,64 +31,19 @@
# define CONFIG_SF_DEFAULT_BUS 0
#endif
-/* sf param flags */
-#define SECT_4K 1 << 1
-#define SECT_32K 1 << 2
-#define E_FSR 1 << 3
-#define WR_QPP 1 << 4
-
-/* Enum list - Full read commands */
-enum spi_read_cmds {
- ARRAY_SLOW = 1 << 0,
- DUAL_OUTPUT_FAST = 1 << 1,
- DUAL_IO_FAST = 1 << 2,
- QUAD_OUTPUT_FAST = 1 << 3,
- QUAD_IO_FAST = 1 << 4,
-};
-#define RD_EXTN ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST
-#define RD_FULL RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST
-
-/* Dual SPI flash memories */
-enum spi_dual_flash {
- SF_SINGLE_FLASH = 0,
- SF_DUAL_STACKED_FLASH = 1 << 0,
- SF_DUAL_PARALLEL_FLASH = 1 << 1,
-};
-
-/**
- * struct spi_flash_params - SPI/QSPI flash device params structure
- *
- * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
- * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
- * @ext_jedec: Device ext_jedec ID
- * @sector_size: Sector size of this device
- * @nr_sectors: No.of sectors on this device
- * @e_rd_cmd: Enum list for read commands
- * @flags: Important param, for flash specific behaviour
- */
-struct spi_flash_params {
- const char *name;
- u32 jedec;
- u16 ext_jedec;
- u32 sector_size;
- u32 nr_sectors;
- u8 e_rd_cmd;
- u16 flags;
-};
-
-extern const struct spi_flash_params spi_flash_params_table[];
+struct spi_slave;
/**
* struct spi_flash - SPI flash structure
*
* @spi: SPI slave
* @name: Name of SPI flash
- * @dual_flash: Indicates dual flash memories - dual stacked, parallel
+ * @dual_flash: Indicates dual flash memories - dual stacked, parallel
* @shift: Flash shift useful in dual parallel
* @size: Total flash size
* @page_size: Write (page) size
* @sector_size: Sector size
- * @erase_size: Erase size
+ * @erase_size: Erase size
* @bank_read_cmd: Bank read cmd
* @bank_write_cmd: Bank write cmd
* @bank_curr: Current flash bank
@@ -97,8 +51,8 @@ extern const struct spi_flash_params spi_flash_params_table[];
* @erase_cmd: Erase cmd 4K, 32K, 64K
* @read_cmd: Read cmd - Array Fast, Extn read and quad read.
* @write_cmd: Write cmd - page and quad program.
- * @dummy_byte: Dummy cycles for read operation.
- * @memory_map: Address of read-only SPI flash access
+ * @dummy_byte: Dummy cycles for read operation.
+ * @memory_map: Address of read-only SPI flash access
* @read: Flash read ops: Read len bytes at offset into buf
* Supported cmds: Fast Array Read
* @write: Flash write ops: Write len bytes from buf into offset
@@ -108,7 +62,12 @@ extern const struct spi_flash_params spi_flash_params_table[];
* return 0 - Success, 1 - Failure
*/
struct spi_flash {
+#ifdef CONFIG_DM_SPI_FLASH
+ struct spi_slave *spi;
+ struct udevice *dev;
+#else
struct spi_slave *spi;
+#endif
const char *name;
u8 dual_flash;
u8 shift;
@@ -129,12 +88,75 @@ struct spi_flash {
u8 dummy_byte;
void *memory_map;
+#ifndef CONFIG_DM_SPI_FLASH
+ /*
+ * These are not strictly needed for driver model, but keep them here
+ * whilt the transition is in progress.
+ *
+ * Normally each driver would provide its own operations, but for
+ * SPI flash most chips use the same algorithms. One approach is
+ * to create a 'common' SPI flash device which knows how to talk
+ * to most devices, and then allow other drivers to be used instead
+ * if requird, perhaps with a way of scanning through the list to
+ * find the driver that matches the device.
+ */
int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
int (*write)(struct spi_flash *flash, u32 offset, size_t len,
const void *buf);
int (*erase)(struct spi_flash *flash, u32 offset, size_t len);
+#endif
};
+struct dm_spi_flash_ops {
+ int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf);
+ int (*write)(struct udevice *dev, u32 offset, size_t len,
+ const void *buf);
+ int (*erase)(struct udevice *dev, u32 offset, size_t len);
+};
+
+/* Access the serial operations for a device */
+#define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops)
+
+#ifdef CONFIG_DM_SPI_FLASH
+int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
+ unsigned int max_hz, unsigned int spi_mode,
+ struct udevice **devp);
+
+/* Compatibility function - this is the old U-Boot API */
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int spi_mode);
+
+/* Compatibility function - this is the old U-Boot API */
+void spi_flash_free(struct spi_flash *flash);
+
+int spi_flash_remove(struct udevice *flash);
+
+static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
+ size_t len, void *buf)
+{
+ return sf_get_ops(flash->dev)->read(flash->dev, offset, len, buf);
+}
+
+static inline int spi_flash_write(struct spi_flash *flash, u32 offset,
+ size_t len, const void *buf)
+{
+ return sf_get_ops(flash->dev)->write(flash->dev, offset, len, buf);
+}
+
+static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
+ size_t len)
+{
+ return sf_get_ops(flash->dev)->erase(flash->dev, offset, len);
+}
+
+struct sandbox_state;
+
+int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
+ struct udevice *bus, int of_offset, const char *spec);
+
+void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs);
+
+#else
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int spi_mode);
@@ -169,6 +191,7 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
{
return flash->erase(flash, offset, len);
}
+#endif
void spi_boot(void) __noreturn;
void spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst);
OpenPOWER on IntegriCloud