Skip to contentSkip to conversation

Introduce driver model support for SPI, SPI flash, cros_ec

PATCH New Simon Glass 3 participants 67 messages Oct 14, 2014 – Nov 1, 2014

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

v4 cover Introduce driver model support for SPI, SPI flash, cros_ec

Up until now driver model has not been used for any type of bus. Buses have some unique properties and needs, so we cannot claim that driver model can cover all the common cases unless we have converted a bus over to driver model.

SPI is a reasonable choice for this next step. It has a fairly simple API and not too many dependencies. The main one is SPI flash so we may as well convert that also. Since the boards I test with have cros_ec I have also included that, for SPI only.

The technique used is make use of driver model's supported data structures to hold information currently kept by each subsystem in a private data structure. Since 'struct spi_slave' relates to the slave device on the bus it is stored in the 'parent' data with each child device of the bus. Since 'struct spi_flash' is a standard interface used for each SPI flash driver, it is stored in the SPI FLash uclass's private data for each device.

New defines are created to enable driver model for each subsystem. These are:

CONFIG_DM_SPI
CONFIG_DM_SPI_FLASH
CONFIG_DM_CROS_EC

This allows us to move some boards and drivers to driver model, while leaving others behind. A 'big bang' conversion of everything to driver model, even at a subsystem level, is never going to work.

There is some cost in changing the uclass interface after it is created, so if you have limited time, please spend it reviewing the uclass interfaces in spi.h and spi_flash.h. These need to be supported by each driver, so changing them later may involve changing multiple drivers.

To assist with the conversion of other SPI drivers, a README file is added to walk through the process.

So far, sandbox, exynos and tegra drivers are converted over.

As always, driver model patches are available at u-boot-dm.git branch 'working'. There is a branch for just this series called 'spi-working'.

Changes in v4:
- Drop the incorrect compulab hunk from this patch
- Remove a extra tab character (oops)

Changes in v3:
- Add a cs_info() method to the driver model SPI API
- Add a debug() in the probe method
- Add a few more debug() statements
- Add a function comment for sandbox_spi_get_emul()
- Add a missing tab character
- Add a uclass for a generic SPI device (for use with the 'sspi' command)
- Add implementation/comment for the cs_info() method
- Add missing comments to spi.h
- Add new functions to iterate through device children
- Add new patch to add a clarifying comment on struct udevice's seq member
- Add new patch to add aliases for spi on tegra30 boards
- Add new patch to allow parents to pass data to children during probe
- Add new patch to convert Tegra SPI to driver model
- Add spi.h header to 3 sh boards
- Correct typo where 'slave' should say 'bus'
- Expand SPI tests to cover compatibility functions
- Fix two comment typos
- Make sure the old device is both removed and unbound in 'sf probe'
- Minor renames for clarity
- Put the cs member back into spi_slave
- Rebase to master
- Remove the child_pre_probe() method which is no longer needed
- Update for the new cs_info() method
- Use a generic SPI device for the 'sspi command'
- Use an explicit chip select value instead of reusing device sequence number
- Word-wrap the first paragraph of the binding

Changes in v2:
- Add additional debug() statements
- Add missing comments for struct spi_slave
- Add spi.h header to dfu_sf.c
- Adjust binding to avoid Linux-specific mentions
- Adjust xfer() method for new API
- Correct sandbox's xfer() method signature
- Create a 'spi.bin' file for the SPI tests
- Fix a typo in the commit message
- Fix code nits from Daniel Schwierzeck
- Fix comment on 'slave' parameter to match the parameter name
- Fix typos reported by Jagannadha Sutradharudu Teki
- Update for changes to exynos driver
- Use 'bus' instead of 'dev' to distinguish bus from slave
- Use 'bus' instead of 'dev' to make the API clearer

Simon Glass (29):
sandbox: dts: Add a SPI device and cros_ec device
dm: core: Add functions for iterating through device children
dm: core: Allow parents to pass data to children during probe
dm: core: Add a clarifying comment on struct udevice's seq member
dm: spi: Add a uclass for SPI
dm: sandbox: Add a SPI emulation uclass
dm: Remove spi_init() from board_r.c when using driver model
dm: Add spi.h header to a few files
dm: spi: Adjust cmd_spi to work with driver model
dm: sandbox: spi: Move to driver model
dm: spi: Rename soft_spi.c to soft_spi_legacy.c
dm: spi: Remove SPI_INIT feature
dm: spi: Add soft_spi implementation
dm: exynos: Convert SPI to driver model
dm: spi: Add documentation on how to convert over SPI drivers
exynos: universal_c210: Move to driver model soft_spi
sf: Tidy up public and private header files
spi: Use error return value in sf_ops
dm: sf: Add a uclass for SPI flash
dm: Convert spi_flash_probe() and 'sf probe' to use driver model
dm: sf: sandbox: Convert SPI flash driver to driver model
dm: exynos: config: Use driver model for SPI flash
dm: spi: Add tests
dm: sf: Add tests for SPI flash
dm: tegra: dts: Add aliases for spi on tegra30 boards
dm: tegra: spi: Convert to driver model
dm: cros_ec: Add support for driver model
dm: sandbox: cros_ec: Move sandbox cros_ec to driver module
dm: exynos: cros_ec: Move cros_ec_spi to driver model

 arch/arm/dts/exynos4210-universal_c210.dts         |  13 +
 arch/arm/dts/exynos5250-snow.dts                   |   8 +
 arch/arm/dts/exynos5420-peach-pit.dts              |   1 +
 arch/arm/dts/tegra20-trimslice.dts                 |   1 +
 arch/arm/dts/tegra30-beaver.dts                    |   1 +
 arch/arm/dts/tegra30-cardhu.dts                    |   1 +
 arch/arm/dts/tegra30-colibri.dts                   |   1 +
 arch/arm/include/asm/arch-tegra114/tegra114_spi.h  |  41 --
 arch/arm/include/asm/arch-tegra20/tegra20_sflash.h |  41 --
 arch/arm/include/asm/arch-tegra20/tegra20_slink.h  |  41 --
 arch/sandbox/dts/sandbox.dts                       |  26 +
 arch/sandbox/include/asm/spi.h                     |  13 -
 arch/sandbox/include/asm/state.h                   |   2 +-
 board/buffalo/lsxl/lsxl.c                          |   3 +-
 board/nvidia/common/board.c                        |   3 +-
 board/renesas/sh7752evb/sh7752evb.c                |   1 +
 board/renesas/sh7753evb/sh7753evb.c                |   1 +
 board/renesas/sh7757lcr/sh7757lcr.c                |   1 +
 board/samsung/common/board.c                       |   3 -
 board/samsung/universal_c210/universal.c           |  52 --
 common/board_r.c                                   |   2 +-
 common/cmd_sf.c                                    |  26 +
 common/cmd_spi.c                                   |  39 +-
 common/cros_ec.c                                   |  30 ++
 common/env_sf.c                                    |   1 +
 common/exports.c                                   |   4 +-
 doc/device-tree-bindings/mtd/spi/spi-flash.txt     |  25 +
 doc/device-tree-bindings/spi/soft-spi.txt          |  34 ++
 doc/driver-model/README.txt                        |   7 +-
 doc/driver-model/spi-howto.txt                     | 594 +++++++++++++++++++++
 drivers/core/device.c                              |  36 +-
 drivers/dfu/dfu_sf.c                               |   1 +
 drivers/misc/cros_ec.c                             | 122 ++++-
 drivers/misc/cros_ec_sandbox.c                     |  99 +++-
 drivers/misc/cros_ec_spi.c                         |  68 ++-
 drivers/mtd/spi/Makefile                           |   7 +-
 drivers/mtd/spi/ramtron.c                          |   1 +
 drivers/mtd/spi/sandbox.c                          | 338 ++++++++++--
 drivers/mtd/spi/sf-uclass.c                        |  63 +++
 drivers/mtd/spi/sf_internal.h                      |  67 ++-
 drivers/mtd/spi/sf_params.c                        |   1 +
 drivers/mtd/spi/sf_probe.c                         | 154 ++++--
 drivers/mtd/spi/spi_spl_load.c                     |   1 +
 drivers/spi/Makefile                               |   9 +-
 drivers/spi/exynos_spi.c                           | 513 +++++++-----------
 drivers/spi/fdt_spi.c                              | 186 -------
 drivers/spi/sandbox_spi.c                          | 200 +++----
 drivers/spi/soft_spi.c                             | 227 +++++---
 drivers/spi/soft_spi_legacy.c                      | 176 ++++++
 drivers/spi/spi-emul-uclass.c                      |  15 +
 drivers/spi/spi-uclass.c                           | 390 ++++++++++++++
 drivers/spi/tegra114_spi.c                         | 254 ++++-----
 drivers/spi/tegra20_sflash.c                       | 238 +++++----
 drivers/spi/tegra20_slink.c                        | 235 ++++----
 drivers/spi/tegra_spi.h                            |  12 +
 include/configs/exynos-common.h                    |   2 +
 include/configs/peach-pit.h                        |   1 +
 include/configs/s5pc210_universal.h                |  12 +-
 include/configs/sacsng.h                           |   1 -
 include/configs/sandbox.h                          |   5 +-
 include/configs/tegra-common-post.h                |   2 +-
 include/configs/tegra-common.h                     |   2 +
 include/configs/zipitz2.h                          |   1 -
 include/cros_ec.h                                  |  27 +-
 include/dm/device-internal.h                       |  13 +
 include/dm/device.h                                |  25 +-
 include/dm/uclass-id.h                             |   5 +
 include/spi.h                                      | 299 ++++++++++-
 include/spi_flash.h                                | 127 +++--
 test/dm/Makefile                                   |   2 +
 test/dm/bus.c                                      |  31 ++
 test/dm/sf.c                                       |  43 ++
 test/dm/spi.c                                      | 127 +++++
 test/dm/test-dm.sh                                 |   2 +
 test/dm/test.dts                                   |  17 +-
 75 files changed, 3702 insertions(+), 1471 deletions(-)
 delete mode 100644 arch/arm/include/asm/arch-tegra114/tegra114_spi.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_sflash.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_slink.h
 create mode 100644 doc/device-tree-bindings/mtd/spi/spi-flash.txt
 create mode 100644 doc/device-tree-bindings/spi/soft-spi.txt
 create mode 100644 doc/driver-model/spi-howto.txt
 create mode 100644 drivers/mtd/spi/sf-uclass.c
 delete mode 100644 drivers/spi/fdt_spi.c
 create mode 100644 drivers/spi/soft_spi_legacy.c
 create mode 100644 drivers/spi/spi-emul-uclass.c
 create mode 100644 drivers/spi/spi-uclass.c
 create mode 100644 drivers/spi/tegra_spi.h
 create mode 100644 test/dm/sf.c
 create mode 100644 test/dm/spi.c
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#1 lore raw

PATCH v4 1/29 sandbox: dts: Add a SPI device and cros_ec device

Add a SPI device which can be used for testing SPI flash features in sandbox.

Also add a cros_ec device since with driver model the Chrome OS EC emulation will not otherwise be available.

---

Changes in v4: None
Changes in v3: None
Changes in v2:
- Adjust binding to avoid Linux-specific mentions

 arch/sandbox/dts/sandbox.dts                   | 26 ++++++++++++++++++++++++++
 doc/device-tree-bindings/mtd/spi/spi-flash.txt | 25 +++++++++++++++++++++++++
 2 files changed, 51 insertions(+)
 create mode 100644 doc/device-tree-bindings/mtd/spi/spi-flash.txt
arch/sandbox/dts/sandbox.dts +26 -0
index 797478a..7614715 100644
@@ -1,6 +1,9 @@
 /dts-v1/;
 
 / {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
 	chosen {
 		stdout-path = "/serial";
 	};
@@ -131,4 +134,27 @@
 		num-gpios = <20>;
 	};
 
+	spi at 0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0>;
+		compatible = "sandbox,spi";
+		cs-gpios = <0>, <&gpio_a 0>;
+		flash at 0 {
+			reg = <0>;
+			compatible = "spansion,m25p16", "sandbox,spi-flash";
+			spi-max-frequency = <40000000>;
+			sandbox,filename = "spi.bin";
+		};
+	};
+
+	cros-ec at 0 {
+		compatible = "google,cros-ec";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		firmware_storage_spi: flash at 0 {
+			reg = <0 0x400000>;
+		};
+	};
+
 };
doc/device-tree-bindings/mtd/spi/spi-flash.txt new file +25 -0
new file mode 100644
index 0000000..85522d8
@@ -0,0 +1,25 @@
+* MTD SPI driver for serial flash chips
+
+Required properties:
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+  representing partitions.
+- compatible : Should be the manufacturer and the name of the chip. Bear in
+               mind that the DT binding is not U-Boot-only, but in case of
+               U-Boot, see spi_flash_params_table table in
+               drivers/mtd/spi/sf_params.c for the list of supported chips.
+- reg : Chip-Select number
+- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
+
+Optional properties:
+ - memory-map : Address and size of the flash, if memory mapped. This may
+                apply to Intel chipsets, which tend to memory-map flash.
+
+Example:
+
+	flash: m25p80 at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,m25p80";
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+	};
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#2 lore raw

PATCH v4 1/29 sandbox: dts: Add a SPI device and cros_ec device

Quoted 10 lines · Simon Glass

Add a SPI device which can be used for testing SPI flash features in sandbox.

Also add a cros_ec device since with driver model the Chrome OS EC emulation will not otherwise be available.

---

Quoted 8 lines

Changes in v4: None
Changes in v3: None
Changes in v2:
- Adjust binding to avoid Linux-specific mentions

 arch/sandbox/dts/sandbox.dts                   | 26 ++++++++++++++++++++++++++
 doc/device-tree-bindings/mtd/spi/spi-flash.txt | 25 +++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

Applied to u-boot-dm/master.

#3 lore raw

PATCH v4 2/29 dm: core: Add functions for iterating through device children

In reply to Simon Glass

Buses need to iterate through their children in some situations. Add a few functions to make this easy.

---

Changes in v4: None
Changes in v3:
- Add new functions to iterate through device children

Changes in v2: None

 doc/driver-model/README.txt |  3 ++-
 drivers/core/device.c       | 27 +++++++++++++++++++++++++++
 include/dm/device.h         | 18 ++++++++++++++++++
 test/dm/bus.c               | 31 +++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 1 deletion(-)
doc/driver-model/README.txt +2 -1
index f9b68be..c435cdc 100644
@@ -95,7 +95,7 @@ are provided in test/dm. To run them, try:
 You should see something like this:
 
     <...U-Boot banner...>
-    Running 21 driver model tests
+    Running 22 driver model tests
     Test: dm_test_autobind
     Test: dm_test_autoprobe
     Test: dm_test_bus_children
@@ -103,6 +103,7 @@ You should see something like this:
     Device 'c-test at 0': seq 0 is in use by 'a-test'
     Device 'c-test at 1': seq 1 is in use by 'd-test'
     Test: dm_test_bus_children_funcs
+    Test: dm_test_bus_children_iterators
     Test: dm_test_bus_parent_data
     Test: dm_test_bus_parent_ops
     Test: dm_test_children
drivers/core/device.c +27 -0
index 32e80e8..9538874 100644
@@ -514,3 +514,30 @@ int device_get_child_by_of_offset(struct udevice *parent, int seq,
 	ret = device_find_child_by_of_offset(parent, seq, &dev);
 	return device_get_device_tail(dev, ret, devp);
 }
+
+int device_find_first_child(struct udevice *parent, struct udevice **devp)
+{
+	if (list_empty(&parent->child_head)) {
+		*devp = NULL;
+	} else {
+		*devp = list_first_entry(&parent->child_head, struct udevice,
+					 sibling_node);
+	}
+
+	return 0;
+}
+
+int device_find_next_child(struct udevice **devp)
+{
+	struct udevice *dev = *devp;
+	struct udevice *parent = dev->parent;
+
+	if (list_is_last(&dev->sibling_node, &parent->child_head)) {
+		*devp = NULL;
+	} else {
+		*devp = list_entry(dev->sibling_node.next, struct udevice,
+				   sibling_node);
+	}
+
+	return 0;
+}
include/dm/device.h +18 -0
index c8a4072..4d277db 100644
@@ -274,4 +274,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
test/dm/bus.c +31 -0
index 873d64e..abbaccf 100644
@@ -140,6 +140,37 @@ static int dm_test_bus_children_funcs(struct dm_test_state *dms)
 }
 DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* Test that we can iterate through children */
+static int dm_test_bus_children_iterators(struct dm_test_state *dms)
+{
+	struct udevice *bus, *dev, *child;
+
+	/* Walk through the children one by one */
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+	ut_assertok(device_find_first_child(bus, &dev));
+	ut_asserteq_str("c-test at 5", dev->name);
+	ut_assertok(device_find_next_child(&dev));
+	ut_asserteq_str("c-test at 0", dev->name);
+	ut_assertok(device_find_next_child(&dev));
+	ut_asserteq_str("c-test at 1", dev->name);
+	ut_assertok(device_find_next_child(&dev));
+	ut_asserteq_ptr(dev, NULL);
+
+	/* Move to the next child without using device_find_first_child() */
+	ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
+	ut_asserteq_str("c-test at 5", dev->name);
+	ut_assertok(device_find_next_child(&dev));
+	ut_asserteq_str("c-test at 0", dev->name);
+
+	/* Try a device with no children */
+	ut_assertok(device_find_first_child(dev, &child));
+	ut_asserteq_ptr(child, NULL);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_children_iterators,
+	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test that the bus can store data about each child */
 static int dm_test_bus_parent_data(struct dm_test_state *dms)
 {
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#4 lore raw

PATCH v4 2/29 dm: core: Add functions for iterating through device children

Quoted 11 lines · Simon Glass

Buses need to iterate through their children in some situations. Add a few functions to make this easy.

---

Changes in v4: None
Changes in v3:
- Add new functions to iterate through device children

Quoted 7 lines

Changes in v2: None

 doc/driver-model/README.txt |  3 ++-
 drivers/core/device.c       | 27 +++++++++++++++++++++++++++
 include/dm/device.h         | 18 ++++++++++++++++++
 test/dm/bus.c               | 31 +++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 1 deletion(-)

Applied to u-boot-dm/master.

#5 lore raw

PATCH v4 3/29 dm: core: Allow parents to pass data to children during probe

In reply to Simon Glass

Buses sometimes want to pass data to their children when they are probed. For example, a SPI bus may want to tell the slave device about the chip select it is connected to.

Add a new function to permit the parent data to be supplied to the child.

---

Changes in v4: None
Changes in v3:
- Add new patch to allow parents to pass data to children during probe

Changes in v2: None

 drivers/core/device.c        |  9 ++++++++-
 include/dm/device-internal.h | 13 +++++++++++++
 include/dm/device.h          |  4 ++++
 3 files changed, 25 insertions(+), 1 deletion(-)
drivers/core/device.c +8 -1
index 9538874..49faa29 100644
@@ -232,7 +232,7 @@ static void device_free(struct udevice *dev)
 	}
 }
 
-int device_probe(struct udevice *dev)
+int device_probe_child(struct udevice *dev, void *parent_priv)
 {
 	struct driver *drv;
 	int size = 0;
@@ -282,6 +282,8 @@ int device_probe(struct udevice *dev)
 				ret = -ENOMEM;
 				goto fail;
 			}
+			if (parent_priv)
+				memcpy(dev->parent_priv, parent_priv, size);
 		}
 
 		ret = device_probe(dev->parent);
@@ -335,6 +337,11 @@ fail:
 	return ret;
 }
 
+int device_probe(struct udevice *dev)
+{
+	return device_probe_child(dev, NULL);
+}
+
 int device_remove(struct udevice *dev)
 {
 	struct driver *drv;
include/dm/device-internal.h +13 -0
index 7005d03..44cb7ef 100644
@@ -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
include/dm/device.h +4 -0
index 4d277db..c24707e 100644
@@ -133,6 +133,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 at 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.
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#6 lore raw

PATCH v4 3/29 dm: core: Allow parents to pass data to children during probe

Quoted 14 lines · Simon Glass

Buses sometimes want to pass data to their children when they are probed. For example, a SPI bus may want to tell the slave device about the chip select it is connected to.

Add a new function to permit the parent data to be supplied to the child.

---

Changes in v4: None
Changes in v3:
- Add new patch to allow parents to pass data to children during probe

Quoted 7 lines

Changes in v2: None

 drivers/core/device.c        |  9 ++++++++-
 include/dm/device-internal.h | 13 +++++++++++++
 include/dm/device.h          |  4 ++++
 3 files changed, 25 insertions(+), 1 deletion(-)

Applied to u-boot-dm/master.

#7 lore raw

PATCH v4 4/29 dm: core: Add a clarifying comment on struct udevice's seq member

In reply to Simon Glass

The sequence number is unique within the uclass, so state this clearly.

---

Changes in v4: None
Changes in v3:
- Add new patch to add a clarifying comment on struct udevice's seq member

Changes in v2: None

 doc/driver-model/README.txt | 4 +++-
 include/dm/device.h         | 3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)
doc/driver-model/README.txt +3 -1
index c435cdc..8dfcf75 100644
@@ -359,7 +359,9 @@ Device Sequence Numbers
 U-Boot numbers devices from 0 in many situations, such as in the command
 line for I2C and SPI buses, and the device names for serial ports (serial0,
 serial1, ...). Driver model supports this numbering and permits devices
-to be locating by their 'sequence'.
+to be locating by their 'sequence'. This numbering unique identifies a
+device in its uclass, so no two devices within a particular uclass can have
+the same sequence number.
 
 Sequence numbers start from 0 but gaps are permitted. For example, a board
 may have I2C buses 0, 1, 4, 5 but no 2 or 3. The choice of how devices are
include/dm/device.h +2 -1
index c24707e..b8d4e7a 100644
@@ -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;
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#8 lore raw

PATCH v4 4/29 dm: core: Add a clarifying comment on struct udevice's seq member

Quoted 10 lines · Simon Glass

The sequence number is unique within the uclass, so state this clearly.

---

Changes in v4: None
Changes in v3:
- Add new patch to add a clarifying comment on struct udevice's seq member

Quoted 6 lines

Changes in v2: None

 doc/driver-model/README.txt | 4 +++-
 include/dm/device.h         | 3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)

Applied to u-boot-dm/master.

#9 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

In reply to Simon Glass

Add a uclass which provides access to SPI buses and includes operations required by SPI.

For a time driver model will need to co-exist with the legacy SPI interface so some parts of the header file are changed depending on which is in use. The exports are adjusted also since some functions are not available with driver model.

Boards must define CONFIG_DM_SPI to use driver model for SPI.

(Discussed some follow-up comments which will address in future add-ons)

---

Changes in v4: None
Changes in v3:
- Add a cs_info() method to the driver model SPI API
- Add a uclass for a generic SPI device (for use with the 'sspi' command)
- Add missing comments to spi.h
- Correct typo where 'slave' should say 'bus'
- Fix two comment typos
- Put the cs member back into spi_slave
- Use an explicit chip select value instead of reusing device sequence number

Changes in v2:
- Add missing comments for struct spi_slave
- Fix code nits from Daniel Schwierzeck
- Use 'bus' instead of 'dev' to make the API clearer

 common/exports.c         |   4 +-
 drivers/spi/Makefile     |   4 +
 drivers/spi/spi-uclass.c | 390 +++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |   2 +
 include/spi.h            | 254 +++++++++++++++++++++++++++++-
 5 files changed, 650 insertions(+), 4 deletions(-)
 create mode 100644 drivers/spi/spi-uclass.c
common/exports.c +3 -1
index b97ca48..88fcfc8 100644
@@ -27,10 +27,12 @@ unsigned long get_version(void)
 # define i2c_write         dummy
 # define i2c_read          dummy
 #endif
-#ifndef CONFIG_CMD_SPI
+#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
 # define spi_init          dummy
 # define spi_setup_slave   dummy
 # define spi_free_slave    dummy
+#endif
+#ifndef CONFIG_CMD_SPI
 # define spi_claim_bus     dummy
 # define spi_release_bus   dummy
 # define spi_xfer          dummy
drivers/spi/Makefile +4 -0
index f02c35a..d1f1dd0 100644
@@ -6,7 +6,11 @@
 #
 
 # There are many options which enable SPI, so make this library available
+ifdef CONFIG_DM_SPI
+obj-y += spi-uclass.o
+else
 obj-y += spi.o
+endif
 
 obj-$(CONFIG_EP93XX_SPI) += ep93xx_spi.o
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
drivers/spi/spi-uclass.c new file +390 -0

390 lines not on this page · raw message

include/dm/uclass-id.h +2 -0
index 7f0e37b..0afdc75 100644
@@ -22,6 +22,8 @@ enum uclass_id {
 	/* 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_COUNT,
 	UCLASS_INVALID = -1,
include/spi.h +251 -3

288 lines not on this page · raw message

Signature · 1 line
2.1.0.rc2.206.gedb03e5
#10 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Quoted 31 lines · Simon Glass

Add a uclass which provides access to SPI buses and includes operations required by SPI.

For a time driver model will need to co-exist with the legacy SPI interface so some parts of the header file are changed depending on which is in use. The exports are adjusted also since some functions are not available with driver model.

Boards must define CONFIG_DM_SPI to use driver model for SPI.

(Discussed some follow-up comments which will address in future add-ons)

---

Changes in v4: None
Changes in v3:
- Add a cs_info() method to the driver model SPI API
- Add a uclass for a generic SPI device (for use with the 'sspi' command)
- Add missing comments to spi.h
- Correct typo where 'slave' should say 'bus'
- Fix two comment typos
- Put the cs member back into spi_slave
- Use an explicit chip select value instead of reusing device sequence number

Changes in v2:
- Add missing comments for struct spi_slave
- Fix code nits from Daniel Schwierzeck
- Use 'bus' instead of 'dev' to make the API clearer

Quoted 8 lines
 common/exports.c         |   4 +-
 drivers/spi/Makefile     |   4 +
 drivers/spi/spi-uclass.c | 390 +++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |   2 +
 include/spi.h            | 254 +++++++++++++++++++++++++++++-
 5 files changed, 650 insertions(+), 4 deletions(-)
 create mode 100644 drivers/spi/spi-uclass.c

Applied to u-boot-dm/master.

#11 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

In reply to Simon Glass

Hi Simon!

Quoted 9 lines · Simon Glass

Add a uclass which provides access to SPI buses and includes operations required by SPI.

For a time driver model will need to co-exist with the legacy SPI interface so some parts of the header file are changed depending on which is in use. The exports are adjusted also since some functions are not available with driver model.

Boards must define CONFIG_DM_SPI to use driver model for SPI.

I'm starting to use DM now. Finally! ;)

In my case I'm implementing the Designware master SPI driver for the SoCFPGA. And since its a new driver it really makes sense to use DM directly. I'm starting to get an overview now. One thing though that I noticed is, that the SPI DM implementation seems to be a bit FDT centric. Please see below.

<snip>

Quoted 1 line
drivers/spi/spi-uclass.c +0 -0

<snip>

drivers/spi/spi-uclass.c line 99

Quoted 5 lines
drivers/spi/spi-uclass.c +5 -0
+int spi_post_bind(struct udevice *dev)
+{
+	/* Scan the bus for devices */
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}

SoCFPGA currently does not support CONFIG_OF_CONTROL (no dtb supplied). So I'm planning to use platform_data to instantiate the device. Something like this in the board file:

static const struct dw_spi_platdata spi_platdata = {
.base = SOCFPGA_SPIM0_ADDRESS,
};

U_BOOT_DEVICE(dw_spi) = {
	.name = "dw_spi",
	.platdata = &spi_platdata,
};

What would the non-fdt method have to be to bind the device in spi_post_bind() above?

Thanks,
Stefan

#12 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Hi Stefan,

Quoted 45 lines · Stefan Roese

Hi Simon!

Quoted 11 lines · Simon Glass

Add a uclass which provides access to SPI buses and includes operations required by SPI.

For a time driver model will need to co-exist with the legacy SPI interface
so some parts of the header file are changed depending on which is in use. The exports are adjusted also since some functions are not available with driver model.

Boards must define CONFIG_DM_SPI to use driver model for SPI.

I'm starting to use DM now. Finally! ;)

In my case I'm implementing the Designware master SPI driver for the SoCFPGA. And since its a new driver it really makes sense to use DM directly. I'm starting to get an overview now. One thing though that I noticed is, that the SPI DM implementation seems to be a bit FDT centric. Please see below.

<snip>

Quoted 1 line
drivers/spi/spi-uclass.c +0 -0

<snip>

drivers/spi/spi-uclass.c line 99

Quoted 5 lines
drivers/spi/spi-uclass.c +5 -0
+int spi_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}

SoCFPGA currently does not support CONFIG_OF_CONTROL (no dtb supplied). So I'm planning to use platform_data to instantiate the device. Something like this in the board file:

static const struct dw_spi_platdata spi_platdata = {
.base = SOCFPGA_SPIM0_ADDRESS,
};

Quoted 7 lines

U_BOOT_DEVICE(dw_spi) = {
.name = "dw_spi",
.platdata = &spi_platdata,
};

What would the non-fdt method have to be to bind the device in spi_post_bind() above?

At present dm-spi support mostly devicetree driven - Will update you soon for non-devicetree base.

thanks!

Signature · 1 line
Jagan.
#13 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Hi Jagan!

Quoted 24 lines · Jagan Teki
Quoted 24 lines
Quoted 1 line
drivers/spi/spi-uclass.c +0 -0

<snip>

drivers/spi/spi-uclass.c line 99

Quoted 5 lines
drivers/spi/spi-uclass.c +5 -0
+int spi_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}

SoCFPGA currently does not support CONFIG_OF_CONTROL (no dtb supplied). So I'm planning to use platform_data to instantiate the device. Something like this in the board file:

static const struct dw_spi_platdata spi_platdata = {
.base = SOCFPGA_SPIM0_ADDRESS,
};

U_BOOT_DEVICE(dw_spi) = {
.name = "dw_spi",
.platdata = &spi_platdata,
};

Quoted 4 lines
Quoted 2 lines

What would the non-fdt method have to be to bind the device in spi_post_bind() above?

At present dm-spi support mostly devicetree driven

Yes, I noticed this.

Quoted 1 line

Will update you soon for non-devicetree base.

So you are working on this too? Do you have a schedule when you have something ready for testing? If this is soon I might wait for you here. If not, I'll have to dig deeper here myself.

Just checking.

Thanks,
Stefan

#14 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

In reply to Stefan Roese

Hi Stefan,

Quoted 13 lines · Stefan Roese

Hi Simon!

Quoted 10 lines · Simon Glass

Add a uclass which provides access to SPI buses and includes operations required by SPI.

For a time driver model will need to co-exist with the legacy SPI interface
so some parts of the header file are changed depending on which is in use. The exports are adjusted also since some functions are not available with driver model.

Quoted 4 lines
Quoted 1 line

Boards must define CONFIG_DM_SPI to use driver model for SPI.

I'm starting to use DM now. Finally! ;)

Great!

Quoted 13 lines

In my case I'm implementing the Designware master SPI driver for the SoCFPGA. And since its a new driver it really makes sense to use DM directly. I'm starting to get an overview now. One thing though that I noticed is, that the SPI DM implementation seems to be a bit FDT centric. Please see below.

<snip>

Quoted 1 line
drivers/spi/spi-uclass.c +0 -0

<snip>

Quoted 8 lines

drivers/spi/spi-uclass.c line 99

Quoted 5 lines
drivers/spi/spi-uclass.c +5 -0
+int spi_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}

SoCFPGA currently does not support CONFIG_OF_CONTROL (no dtb supplied). So

In the kernel I see these files - are you sure it is not supported?

arch/arm/boot/dts/socfpga_arria5.dtsi
arch/arm/boot/dts/socfpga_arria5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5.dtsi
arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_vt.dts

Quoted 7 lines

I'm planning to use platform_data to instantiate the device. Something like this in the board file:

static const struct dw_spi_platdata spi_platdata = {
.base = SOCFPGA_SPIM0_ADDRESS,
};

Quoted 7 lines

U_BOOT_DEVICE(dw_spi) = {
.name = "dw_spi",
.platdata = &spi_platdata,
};

What would the non-fdt method have to be to bind the device in spi_post_bind() above?

We would have to create a new platform data structure that holds the bus number, CS number and any other information. Then it will need to cause spi_get_bus_and_cs() to locate it and do the right.

But first let's make sure that you really do have the platform that doesn't use device tree... If it is ARM my understanding is that it should.

Also see the SPI driver spi-howto.txt.

Regards,
Simon

#15 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Hi Simon,

Quoted 23 lines · Simon Glass
Quoted 12 lines

In my case I'm implementing the Designware master SPI driver for the SoCFPGA. And since its a new driver it really makes sense to use DM directly. I'm starting to get an overview now. One thing though that I noticed is, that the SPI DM implementation seems to be a bit FDT centric. Please see below.

<snip>

Quoted 1 line
drivers/spi/spi-uclass.c +0 -0

<snip>

Quoted 8 lines

drivers/spi/spi-uclass.c line 99

Quoted 5 lines
drivers/spi/spi-uclass.c +5 -0
+int spi_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}

SoCFPGA currently does not support CONFIG_OF_CONTROL (no dtb supplied). So

In the kernel I see these files - are you sure it is not supported?

Quoted 8 lines

arch/arm/boot/dts/socfpga_arria5.dtsi
arch/arm/boot/dts/socfpga_arria5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5.dtsi
arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_vt.dts

Sure. In the kernel dts is supported. Only U-Boot for SoCFPGA has no DT support (right now).

Quoted 15 lines
Quoted 7 lines

I'm planning to use platform_data to instantiate the device. Something like this in the board file:

static const struct dw_spi_platdata spi_platdata = {
.base = SOCFPGA_SPIM0_ADDRESS,
};

Quoted 7 lines

U_BOOT_DEVICE(dw_spi) = {
.name = "dw_spi",
.platdata = &spi_platdata,
};

What would the non-fdt method have to be to bind the device in spi_post_bind() above?

Quoted 7 lines

We would have to create a new platform data structure that holds the bus number, CS number and any other information. Then it will need to cause spi_get_bus_and_cs() to locate it and do the right.

But first let's make sure that you really do have the platform that doesn't use device tree... If it is ARM my understanding is that it should.

It does. In the kernel. I think I'll dive into adding DT support for SoCFPGA for a few hours. Perhaps thats even easier than adding platform-data support to the SPI DM. Lets see how this goes...

Quoted 1 line

Also see the SPI driver spi-howto.txt.

Thanks,
Stefan

#16 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Hi Stefan,

Quoted 66 lines · Stefan Roese

Hi Simon,

Quoted 29 lines · Simon Glass
Quoted 14 lines

In my case I'm implementing the Designware master SPI driver for the SoCFPGA. And since its a new driver it really makes sense to use DM directly. I'm starting to get an overview now. One thing though that I noticed is, that the SPI DM implementation seems to be a bit FDT centric. Please see below.

<snip>

Quoted 1 line
drivers/spi/spi-uclass.c +0 -0

<snip>

Quoted 11 lines
Quoted 6 lines
drivers/spi/spi-uclass.c +4 -0
+int spi_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,

false);
+}

SoCFPGA currently does not support CONFIG_OF_CONTROL (no dtb supplied). So

In the kernel I see these files - are you sure it is not supported?

Quoted 8 lines

arch/arm/boot/dts/socfpga_arria5.dtsi
arch/arm/boot/dts/socfpga_arria5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5.dtsi
arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_vt.dts

Sure. In the kernel dts is supported. Only U-Boot for SoCFPGA has no DT support (right now).

Quoted 21 lines
Quoted 8 lines

I'm planning to use platform_data to instantiate the device. Something like
this in the board file:

static const struct dw_spi_platdata spi_platdata = {
.base = SOCFPGA_SPIM0_ADDRESS,
};

Quoted 7 lines

U_BOOT_DEVICE(dw_spi) = {
.name = "dw_spi",
.platdata = &spi_platdata,
};

What would the non-fdt method have to be to bind the device in spi_post_bind() above?

We would have to create a new platform data structure that holds the bus number, CS number and any other information. Then it will need to cause spi_get_bus_and_cs() to locate it and do the right.

Quoted 8 lines
Quoted 3 lines

But first let's make sure that you really do have the platform that doesn't use device tree... If it is ARM my understanding is that it should.

It does. In the kernel. I think I'll dive into adding DT support for SoCFPGA for a few hours. Perhaps thats even easier than adding platform-data support to the SPI DM. Lets see how this goes...

Good luck. If you use CONFIG_OF_SEPARATE you will get u-boot-dtb.bin and hopefully it will just work. For CONFIG_OF_EMBED I see a bug was introduced so I need to do a patch for that.

Quoted 7 lines
Quoted 2 lines

Also see the SPI driver spi-howto.txt.

Thanks,
Stefan

Regards,
Simon

#17 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Hi Simon,

Quoted 5 lines · Simon Glass
Quoted 5 lines
Quoted 3 lines

But first let's make sure that you really do have the platform that doesn't use device tree... If it is ARM my understanding is that it should.

Quoted 7 lines
Quoted 3 lines

It does. In the kernel. I think I'll dive into adding DT support for SoCFPGA for a few hours. Perhaps thats even easier than adding platform-data support to the SPI DM. Lets see how this goes...

Good luck. If you use CONFIG_OF_SEPARATE you will get u-boot-dtb.bin and hopefully it will just work. For CONFIG_OF_EMBED I see a bug was introduced so I need to do a patch for that.

I didn't add any of those defines above. Just CONFIG_OF_CONTROL seems to be needed.

I already posted a patch for DT support for SoCFPGA yesterday. And with the addition of the aliases for the spi DT nodes I'm now able use and test the driver...

Thanks,
Stefan

#18 lore raw

PATCH v4 5/29 dm: spi: Add a uclass for SPI

Hi Stefan,

Quoted 22 lines · Stefan Roese

Hi Simon,

Quoted 14 lines · Simon Glass
Quoted 7 lines
Quoted 4 lines

But first let's make sure that you really do have the platform that doesn't use device tree... If it is ARM my understanding is that it should.

Quoted 5 lines

It does. In the kernel. I think I'll dive into adding DT support for SoCFPGA
for a few hours. Perhaps thats even easier than adding platform-data support
to the SPI DM. Lets see how this goes...

Quoted 3 lines

Good luck. If you use CONFIG_OF_SEPARATE you will get u-boot-dtb.bin and hopefully it will just work. For CONFIG_OF_EMBED I see a bug was introduced so I need to do a patch for that.

Quoted 6 lines

I didn't add any of those defines above. Just CONFIG_OF_CONTROL seems to be needed.

I already posted a patch for DT support for SoCFPGA yesterday. And with the addition of the aliases for the spi DT nodes I'm now able use and test the driver...

Ah great. I'm pleased it went so smoothly for you!

Regards,
Simon

#19 lore raw

PATCH v4 6/29 dm: sandbox: Add a SPI emulation uclass

In reply to Simon Glass

U-Boot includes a SPI emulation driver already but it is not explicit, and is hidden in the SPI flash code.

Conceptually with sandbox's SPI implementation we have a layer which creates SPI bus transitions and a layer which interprets them, currently only for SPI flash. The latter is actually an emulation, and it should be possible to add more than one emulation - not just SPI flash.

Add a SPI emulation uclass so that other emulations can be plugged in to support different types of emulated devices on difference buses/chip selects.

---

Changes in v4: None
Changes in v3:
- Add a function comment for sandbox_spi_get_emul()

Changes in v2:
- Fix comment on 'slave' parameter to match the parameter name

 drivers/spi/Makefile          |  1 +
 drivers/spi/spi-emul-uclass.c | 15 +++++++++++++++
 include/dm/uclass-id.h        |  1 +
 include/spi.h                 | 45 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 62 insertions(+)
 create mode 100644 drivers/spi/spi-emul-uclass.c
drivers/spi/Makefile +1 -0
index d1f1dd0..a1de028 100644
@@ -8,6 +8,7 @@
 # There are many options which enable SPI, so make this library available
 ifdef CONFIG_DM_SPI
 obj-y += spi-uclass.o
+obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
 else
 obj-y += spi.o
 endif
drivers/spi/spi-emul-uclass.c new file +15 -0
new file mode 100644
index 0000000..b436a0e
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi.h>
+#include <spi_flash.h>
+
+UCLASS_DRIVER(spi_emul) = {
+	.id		= UCLASS_SPI_EMUL,
+	.name		= "spi_emul",
+};
include/dm/uclass-id.h +1 -0
index 0afdc75..6e56382 100644
@@ -18,6 +18,7 @@ enum uclass_id {
 	UCLASS_TEST,
 	UCLASS_TEST_FDT,
 	UCLASS_TEST_BUS,
+	UCLASS_SPI_EMUL,	/* sandbox SPI device emulator */
 
 	/* U-Boot uclasses start here */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
include/spi.h +45 -0

63 lines not on this page · raw message

Signature · 1 line
2.1.0.rc2.206.gedb03e5
#20 lore raw

PATCH v4 6/29 dm: sandbox: Add a SPI emulation uclass

Quoted 20 lines · Simon Glass

U-Boot includes a SPI emulation driver already but it is not explicit, and is hidden in the SPI flash code.

Conceptually with sandbox's SPI implementation we have a layer which creates SPI bus transitions and a layer which interprets them, currently only for SPI flash. The latter is actually an emulation, and it should be possible to add more than one emulation - not just SPI flash.

Add a SPI emulation uclass so that other emulations can be plugged in to support different types of emulated devices on difference buses/chip selects.

---

Changes in v4: None
Changes in v3:
- Add a function comment for sandbox_spi_get_emul()

Quoted 8 lines

Changes in v2:
- Fix comment on 'slave' parameter to match the parameter name

 drivers/spi/Makefile          |  1 +
 drivers/spi/spi-emul-uclass.c | 15 +++++++++++++++
 include/dm/uclass-id.h        |  1 +
 include/spi.h                 | 45 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 62 insertions(+)

Applied to u-boot-dm/master.

#21 lore raw

PATCH v4 7/29 dm: Remove spi_init() from board_r.c when using driver model

In reply to Simon Glass

Driver model does its own init, so we don't need this.

There is still a call in board_f.c but it is only enabled by CONFIG_HARD_SPI. It is easy enough to disable that option when converting boards which use it to driver model.

---

Changes in v4: None
Changes in v3: None
Changes in v2:
- Fix a typo in the commit message

 common/board_r.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
common/board_r.c +1 -1
index 7e1a76d..3affb63 100644
@@ -354,7 +354,7 @@ static int initr_flash(void)
 }
 #endif
 
-#ifdef CONFIG_PPC
+#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI)
 static int initr_spi(void)
 {
 	/* PPC does this here */
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#22 lore raw

PATCH v4 7/29 dm: Remove spi_init() from board_r.c when using driver model

Quoted 10 lines · Simon Glass

Driver model does its own init, so we don't need this.

There is still a call in board_f.c but it is only enabled by CONFIG_HARD_SPI. It is easy enough to disable that option when converting boards which use it to driver model.

---

Quoted 8 lines

Changes in v4: None
Changes in v3: None
Changes in v2:
- Fix a typo in the commit message

 common/board_r.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Applied to u-boot-dm/master.

#23 lore raw

PATCH v4 8/29 dm: Add spi.h header to a few files

In reply to Simon Glass

Some files are using SPI functions but not explitly including the SPI header file. Fix this, since driver model needs it.

---

Changes in v4: None
Changes in v3: None
Changes in v2:
- Add spi.h header to dfu_sf.c

 common/env_sf.c             | 1 +
 drivers/dfu/dfu_sf.c        | 1 +
 drivers/mtd/spi/sf_params.c | 1 +
 3 files changed, 3 insertions(+)
common/env_sf.c +1 -0
index 37ab13a..5e3729c 100644
@@ -12,6 +12,7 @@
 #include <common.h>
 #include <environment.h>
 #include <malloc.h>
+#include <spi.h>
 #include <spi_flash.h>
 #include <search.h>
 #include <errno.h>
drivers/dfu/dfu_sf.c +1 -0
index 91f6df2..c3d3c3b 100644
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <div64.h>
 #include <dfu.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 static long dfu_get_medium_size_sf(struct dfu_entity *dfu)
drivers/mtd/spi/sf_params.c +1 -0
index 453edf0..61545ca 100644
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 #include "sf_internal.h"
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#24 lore raw

PATCH v4 8/29 dm: Add spi.h header to a few files

Quoted 12 lines · Simon Glass

Some files are using SPI functions but not explitly including the SPI header file. Fix this, since driver model needs it.

---

Changes in v4: None
Changes in v3: None
Changes in v2:
- Add spi.h header to dfu_sf.c

Quoted 4 lines
 common/env_sf.c             | 1 +
 drivers/dfu/dfu_sf.c        | 1 +
 drivers/mtd/spi/sf_params.c | 1 +
 3 files changed, 3 insertions(+)

Applied to u-boot-dm/master.

#25 lore raw

PATCH v4 9/29 dm: spi: Adjust cmd_spi to work with driver model

In reply to Simon Glass

Driver model uses a different way to find the SPI bus and slave from the numbered devices given on the command line. Adjust the code to suit.

We use a generic SPI device, and attach it to the SPI bus before performing the transaction.

---

Changes in v4: None
Changes in v3:
- Use a generic SPI device for the 'sspi command'

Changes in v2: None

 common/cmd_spi.c | 39 +++++++++++++++++++++++++++++++--------
 1 file changed, 31 insertions(+), 8 deletions(-)
common/cmd_spi.c +31 -8
index be5709c..64c3ffc 100644
@@ -11,6 +11,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <errno.h>
 #include <spi.h>
 
@@ -42,19 +43,38 @@ static uchar 		din[MAX_SPI_BYTES];
 static int do_spi_xfer(int bus, int cs)
 {
 	struct spi_slave *slave;
-	int rcode = 0;
-
+	int ret = 0;
+
+#ifdef CONFIG_DM_SPI
+	char name[30], *str;
+	struct udevice *dev;
+
+	snprintf(name, sizeof(name), "generic_%d:%d", bus, cs);
+	str = strdup(name);
+	ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv",
+				 str, &dev, &slave);
+	if (ret)
+		return ret;
+#else
 	slave = spi_setup_slave(bus, cs, 1000000, mode);
 	if (!slave) {
 		printf("Invalid device %d:%d\n", bus, cs);
 		return -EINVAL;
 	}
+#endif
 
-	spi_claim_bus(slave);
-	if (spi_xfer(slave, bitlen, dout, din,
-		     SPI_XFER_BEGIN | SPI_XFER_END) != 0) {
-		printf("Error during SPI transaction\n");
-		rcode = -EIO;
+	ret = spi_claim_bus(slave);
+	if (ret)
+		goto done;
+	ret = spi_xfer(slave, bitlen, dout, din,
+		       SPI_XFER_BEGIN | SPI_XFER_END);
+#ifndef CONFIG_DM_SPI
+	/* We don't get an error code in this case */
+	if (ret)
+		ret = -EIO;
+#endif
+	if (ret) {
+		printf("Error %d during SPI transaction\n", ret);
 	} else {
 		int j;
 
@@ -62,10 +82,13 @@ static int do_spi_xfer(int bus, int cs)
 			printf("%02X", din[j]);
 		printf("\n");
 	}
+done:
 	spi_release_bus(slave);
+#ifndef CONFIG_DM_SPI
 	spi_free_slave(slave);
+#endif
 
-	return rcode;
+	return ret;
 }
 
 /*
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#26 lore raw

PATCH v4 9/29 dm: spi: Adjust cmd_spi to work with driver model

Quoted 8 lines · Simon Glass

Driver model uses a different way to find the SPI bus and slave from the numbered devices given on the command line. Adjust the code to suit.

We use a generic SPI device, and attach it to the SPI bus before performing the transaction.

Quoted 8 lines

---

Changes in v4: None
Changes in v3:
- Use a generic SPI device for the 'sspi command'

Changes in v2: None

Applied to u-boot-dm/master.

#27 lore raw

PATCH v4 10/29 dm: sandbox: spi: Move to driver model

In reply to Simon Glass

Adjust the sandbox SPI driver to support driver model and move sandbox over to driver model for SPI.

---

Changes in v4: None
Changes in v3:
- Add implementation/comment for the cs_info() method
- Remove the child_pre_probe() method which is no longer needed

Changes in v2:
- Correct sandbox's xfer() method signature
- Use 'bus' instead of 'dev' to make the API clearer

 arch/sandbox/include/asm/state.h |   1 +
 drivers/spi/sandbox_spi.c        | 200 +++++++++++++++------------------------
 include/configs/sandbox.h        |   3 +-
 3 files changed, 76 insertions(+), 128 deletions(-)
arch/sandbox/include/asm/state.h +1 -0
index d17a82e..4e0981a 100644
@@ -43,6 +43,7 @@ enum state_terminal_raw {
 struct sandbox_spi_info {
 	const char *spec;
 	const struct sandbox_spi_emu_ops *ops;
+	struct udevice *emul;
 };
 
 /* The complete state of the test system */
drivers/spi/sandbox_spi.c +74 -126

254 lines not on this page · raw message

include/configs/sandbox.h +1 -2
index 6972643..c80e4f0 100644
@@ -97,8 +97,7 @@
 #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_SPI_FLASH_ATMEL
 #define CONFIG_SPI_FLASH_EON
 #define CONFIG_SPI_FLASH_GIGADEVICE
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#28 lore raw

PATCH v4 10/29 dm: sandbox: spi: Move to driver model

Quoted 12 lines · Simon Glass

Adjust the sandbox SPI driver to support driver model and move sandbox over to driver model for SPI.

---

Changes in v4: None
Changes in v3:
- Add implementation/comment for the cs_info() method
- Remove the child_pre_probe() method which is no longer needed

Quoted 9 lines

Changes in v2:
- Correct sandbox's xfer() method signature
- Use 'bus' instead of 'dev' to make the API clearer

 arch/sandbox/include/asm/state.h |   1 +
 drivers/spi/sandbox_spi.c        | 200 +++++++++++++++------------------------
 include/configs/sandbox.h        |   3 +-
 3 files changed, 76 insertions(+), 128 deletions(-)

Applied to u-boot-dm/master.

#29 lore raw

PATCH v4 11/29 dm: spi: Rename soft_spi.c to soft_spi_legacy.c

In reply to Simon Glass

Reserve the 'normal' name for use by driver model, and rename the old driver so that it is clear that it is for 'legacy' drivers only.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/spi/Makefile                          | 2 +-
 drivers/spi/{soft_spi.c => soft_spi_legacy.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/spi/{soft_spi.c => soft_spi_legacy.c} (100%)
drivers/spi/Makefile +1 -1
index a1de028..5cc8655 100644
@@ -11,6 +11,7 @@ obj-y += spi-uclass.o
 obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
 else
 obj-y += spi.o
+obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o
 endif
 
 obj-$(CONFIG_EP93XX_SPI) += ep93xx_spi.o
@@ -35,7 +36,6 @@ obj-$(CONFIG_MXS_SPI) += mxs_spi.o
 obj-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
-obj-$(CONFIG_SOFT_SPI) += soft_spi.o
 obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
 obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
drivers/spi/soft_spi_legacy.c renamed from drivers/spi/soft_spi.c +0 -0
similarity index 100%
rename from drivers/spi/soft_spi.c
rename to drivers/spi/soft_spi_legacy.c
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#30 lore raw

PATCH v4 11/29 dm: spi: Rename soft_spi.c to soft_spi_legacy.c

Quoted 7 lines · Simon Glass

Reserve the 'normal' name for use by driver model, and rename the old driver so that it is clear that it is for 'legacy' drivers only.

---

Quoted 9 lines

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/spi/Makefile                          | 2 +-
 drivers/spi/{soft_spi.c => soft_spi_legacy.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/spi/{soft_spi.c => soft_spi_legacy.c} (100%)

Applied to u-boot-dm/master.

#31 lore raw

PATCH v4 12/29 dm: spi: Remove SPI_INIT feature

In reply to Simon Glass

This feature provides for init of a single SPI port for the soft SPI feature. It is not really compatible with driver model since it assumes a single SPI port. Also, inserting SPI init into the driver by means of a #define is not very nice.

This feature is not used by any active boards, so let's remove it.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/spi/soft_spi_legacy.c       | 5 -----
 include/configs/s5pc210_universal.h | 1 -
 include/configs/sacsng.h            | 1 -
 include/configs/zipitz2.h           | 1 -
 4 files changed, 8 deletions(-)
drivers/spi/soft_spi_legacy.c +0 -5
index c969be3..941daa7 100644
@@ -42,11 +42,6 @@ static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
  */
 void spi_init (void)
 {
-#ifdef	SPI_INIT
-	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
-
-	SPI_INIT;
-#endif
 }
 
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
include/configs/s5pc210_universal.h +0 -1
index 27f3d0a..4fa8d66 100644
@@ -194,7 +194,6 @@
 #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()
include/configs/sacsng.h +0 -1
index b5064ab..2dee315 100644
@@ -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; \
include/configs/zipitz2.h +0 -1
index 41a7c99..fe331bc 100644
@@ -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)
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#32 lore raw

PATCH v4 12/29 dm: spi: Remove SPI_INIT feature

Quoted 15 lines · Simon Glass

This feature provides for init of a single SPI port for the soft SPI feature. It is not really compatible with driver model since it assumes a single SPI port. Also, inserting SPI init into the driver by means of a #define is not very nice.

This feature is not used by any active boards, so let's remove it.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

Quoted 5 lines
 drivers/spi/soft_spi_legacy.c       | 5 -----
 include/configs/s5pc210_universal.h | 1 -
 include/configs/sacsng.h            | 1 -
 include/configs/zipitz2.h           | 1 -
 4 files changed, 8 deletions(-)

Applied to u-boot-dm/master.

#33 lore raw

PATCH v4 13/29 dm: spi: Add soft_spi implementation

In reply to Simon Glass

Add a new implementation of soft_spi that uses device tree to specify the GPIOs. This will replace soft_spi_legacy for boards which use driver model.

---

Changes in v4: None
Changes in v3:
- Word-wrap the first paragraph of the binding

Changes in v2: None

 doc/device-tree-bindings/spi/soft-spi.txt |  34 ++++
 drivers/spi/Makefile                      |   1 +
 drivers/spi/soft_spi.c                    | 252 ++++++++++++++++++++++++++++++
 3 files changed, 287 insertions(+)
 create mode 100644 doc/device-tree-bindings/spi/soft-spi.txt
 create mode 100644 drivers/spi/soft_spi.c
doc/device-tree-bindings/spi/soft-spi.txt new file +34 -0
new file mode 100644
index 0000000..d09c1a5
@@ -0,0 +1,34 @@
+Soft SPI
+
+The soft SPI bus implementation allows the use of GPIO pins to simulate a
+SPI bus. No SPI host is required for this to work. The down-side is that the
+performance will typically be much lower than a real SPI bus.
+
+The soft SPI node requires the following properties:
+
+compatible: "u-boot,soft-spi"
+soft_spi_cs: GPIO number to use for SPI chip select (output)
+soft_spi_sclk: GPIO number to use for SPI clock (output)
+soft_spi_mosi: GPIO number to use for SPI MOSI line (output)
+soft_spi_miso GPIO number to use for SPI MISO line (input)
+spi-delay-us: Number of microseconds of delay between each CS transition
+
+The GPIOs should be specified as required by the GPIO controller referenced.
+The first cell holds the phandle of the controller and the second cell
+typically holds the GPIO number.
+
+
+Example:
+
+	soft-spi {
+		compatible = "u-boot,soft-spi";
+		cs-gpio = <&gpio 235 0>;	/* Y43 */
+		sclk-gpio = <&gpio 225 0>;	/* Y31 */
+		mosi-gpio = <&gpio 227 0>;	/* Y33 */
+		miso-gpio = <&gpio 224 0>;	/* Y30 */
+		spi-delay-us = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cs at 0 {
+		};
+	};
drivers/spi/Makefile +1 -0
index 5cc8655..e718528 100644
@@ -9,6 +9,7 @@
 ifdef CONFIG_DM_SPI
 obj-y += spi-uclass.o
 obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
+obj-$(CONFIG_SOFT_SPI) += soft_spi.o
 else
 obj-y += spi.o
 obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o
drivers/spi/soft_spi.c new file +252 -0

252 lines not on this page · raw message

Signature · 1 line
2.1.0.rc2.206.gedb03e5
#34 lore raw

PATCH v4 13/29 dm: spi: Add soft_spi implementation

Quoted 11 lines · Simon Glass

Add a new implementation of soft_spi that uses device tree to specify the GPIOs. This will replace soft_spi_legacy for boards which use driver model.

---

Changes in v4: None
Changes in v3:
- Word-wrap the first paragraph of the binding

Quoted 9 lines

Changes in v2: None

 doc/device-tree-bindings/spi/soft-spi.txt |  34 ++++
 drivers/spi/Makefile                      |   1 +
 drivers/spi/soft_spi.c                    | 252 ++++++++++++++++++++++++++++++
 3 files changed, 287 insertions(+)
 create mode 100644 doc/device-tree-bindings/spi/soft-spi.txt
 create mode 100644 drivers/spi/soft_spi.c

Applied to u-boot-dm/master.

#35 lore raw

PATCH v4 14/29 dm: exynos: Convert SPI to driver model

In reply to Simon Glass

Move the exynos SPI driver over to driver model. This removes quite a bit of boilerplate from the driver, although it adds some for driver model.

A few device tree additions are needed to make the SPI flash available.

---

Changes in v4: None
Changes in v3:
- Add implementation/comment for the cs_info() method
- Use an explicit chip select value instead of reusing device sequence number

Changes in v2:
- Add additional debug() statements
- Adjust xfer() method for new API
- Use 'bus' instead of 'dev' to distinguish bus from slave

 arch/arm/dts/exynos5250-snow.dts      |   8 +
 arch/arm/dts/exynos5420-peach-pit.dts |   1 +
 board/samsung/common/board.c          |   3 -
 drivers/spi/exynos_spi.c              | 513 ++++++++++++----------------------
 include/configs/exynos-common.h       |   1 +
 5 files changed, 190 insertions(+), 336 deletions(-)
arch/arm/dts/exynos5250-snow.dts +8 -0
index 2003412..6fd9275 100644
@@ -53,6 +53,14 @@
 		};
 	};
 
+	spi at 12d30000 {
+		spi-max-frequency = <50000000>;
+		firmware_storage_spi: flash at 0 {
+			compatible = "spi-flash";
+			reg = <0>;
+		};
+	};
+
 	spi at 131b0000 {
 		spi-max-frequency = <1000000>;
 		spi-deactivate-delay = <100>;
arch/arm/dts/exynos5420-peach-pit.dts +1 -0
index c4c4b8e..fde863d 100644
@@ -140,6 +140,7 @@
 	spi at 12d30000 { /* spi1 */
 		spi-max-frequency = <50000000>;
 		firmware_storage_spi: flash at 0 {
+			compatible = "spi-flash";
 			reg = <0>;
 
 			/*
board/samsung/common/board.c +0 -3
index c119641..e1fc123 100644
@@ -87,9 +87,6 @@ int board_init(void)
 	boot_temp_check();
 #endif
 
-#ifdef CONFIG_EXYNOS_SPI
-	spi_init();
-#endif
 	return exynos_init();
 }
 
drivers/spi/exynos_spi.c +180 -333

658 lines not on this page · raw message

include/configs/exynos-common.h +1 -0
index 34a162d..eb6745e 100644
@@ -21,6 +21,7 @@
 #define CONFIG_CMD_DM
 #define CONFIG_DM_GPIO
 #define CONFIG_DM_SERIAL
+#define CONFIG_DM_SPI
 
 #define CONFIG_ARCH_CPU_INIT
 #define CONFIG_DISPLAY_CPUINFO
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#36 lore raw

PATCH v4 14/29 dm: exynos: Convert SPI to driver model

Quoted 19 lines · Simon Glass

Move the exynos SPI driver over to driver model. This removes quite a bit of boilerplate from the driver, although it adds some for driver model.

A few device tree additions are needed to make the SPI flash available.

---

Changes in v4: None
Changes in v3:
- Add implementation/comment for the cs_info() method
- Use an explicit chip select value instead of reusing device sequence number

Changes in v2:
- Add additional debug() statements
- Adjust xfer() method for new API
- Use 'bus' instead of 'dev' to distinguish bus from slave

Quoted 6 lines
 arch/arm/dts/exynos5250-snow.dts      |   8 +
 arch/arm/dts/exynos5420-peach-pit.dts |   1 +
 board/samsung/common/board.c          |   3 -
 drivers/spi/exynos_spi.c              | 513 ++++++++++++----------------------
 include/configs/exynos-common.h       |   1 +
 5 files changed, 190 insertions(+), 336 deletions(-)

Applied to u-boot-dm/master.

#37 lore raw

PATCH v4 15/29 dm: spi: Add documentation on how to convert over SPI drivers

In reply to Simon Glass

This README is intended to help maintainers move their SPI drivers over to driver model. It works through the required steps with an example.

---

Changes in v4: None
Changes in v3:
- Update for the new cs_info() method

Changes in v2:
- Fix typos reported by Jagannadha Sutradharudu Teki
- Update for changes to exynos driver

 doc/driver-model/spi-howto.txt | 594 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 594 insertions(+)
 create mode 100644 doc/driver-model/spi-howto.txt
doc/driver-model/spi-howto.txt new file +594 -0
new file mode 100644
index 0000000..719dbd5
@@ -0,0 +1,594 @@
+How to port a SPI driver to driver model
+========================================
+
+Here is a rough step-by-step guide. It is based around converting the
+exynos SPI driver to driver model (DM) and the example code is based
+around U-Boot v2014.10-rc2 (commit be9f643).
+
+It is quite long since it includes actual code examples.
+
+Before driver model, SPI drivers have their own private structure which
+contains 'struct spi_slave'. With driver model, 'struct spi_slave' still
+exists, but now it is 'per-child data' for the SPI bus. Each child of the
+SPI bus is a SPI slave. The information that was stored in the
+driver-specific slave structure can now be port in private data for the
+SPI bus.
+
+For example, struct tegra_spi_slave looks like this:
+
+struct tegra_spi_slave {
+	struct spi_slave slave;
+	struct tegra_spi_ctrl *ctrl;
+};
+
+In this case 'slave' will be in per-child data, and 'ctrl' will be in the
+SPI's buses private data.
+
+
+0. How long does this take?
+
+You should be able to complete this within 2 hours, including testing but
+excluding preparing the patches. The API is basically the same as before
+with only minor changes:
+
+- methods to set speed and mode are separated out
+- cs_info is used to get information on a chip select
+
+
+1. Enable driver mode for SPI and SPI flash
+
+Add these to your board config:
+
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
+
+
+2. Add the skeleton
+
+Put this code at the bottom of your existing driver file:
+
+struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
+			unsigned int max_hz, unsigned int mode)
+{
+	return NULL;
+}
+
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+				      int spi_node)
+{
+	return NULL;
+}
+
+static int exynos_spi_ofdata_to_platdata(struct udevice *dev)
+{
+	return -ENODEV;
+}
+
+static int exynos_spi_probe(struct udevice *dev)
+{
+	return -ENODEV;
+}
+
+static int exynos_spi_remove(struct udevice *dev)
+{
+	return -ENODEV;
+}
+
+static int exynos_spi_claim_bus(struct udevice *dev)
+{
+
+	return -ENODEV;
+}
+
+static int exynos_spi_release_bus(struct udevice *dev)
+{
+
+	return -ENODEV;
+}
+
+static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			    const void *dout, void *din, unsigned long flags)
+{
+
+	return -ENODEV;
+}
+
+static int exynos_spi_set_speed(struct udevice *dev, uint speed)
+{
+	return -ENODEV;
+}
+
+static int exynos_spi_set_mode(struct udevice *dev, uint mode)
+{
+	return -ENODEV;
+}
+
+static int exynos_cs_info(struct udevice *bus, uint cs,
+			  struct spi_cs_info *info)
+{
+	return -ENODEV;
+}
+
+static const struct dm_spi_ops exynos_spi_ops = {
+	.claim_bus	= exynos_spi_claim_bus,
+	.release_bus	= exynos_spi_release_bus,
+	.xfer		= exynos_spi_xfer,
+	.set_speed	= exynos_spi_set_speed,
+	.set_mode	= exynos_spi_set_mode,
+	.cs_info	= exynos_cs_info,
+};
+
+static const struct udevice_id exynos_spi_ids[] = {
+	{ .compatible = "samsung,exynos-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(exynos_spi) = {
+	.name	= "exynos_spi",
+	.id	= UCLASS_SPI,
+	.of_match = exynos_spi_ids,
+	.ops	= &exynos_spi_ops,
+	.ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
+	.probe	= exynos_spi_probe,
+	.remove	= exynos_spi_remove,
+};
+
+
+3. Replace 'exynos' in the above code with your driver name
+
+
+4. #ifdef out all of the code in your driver except for the above
+
+This will allow you to get it building, which means you can work
+incrementally. Since all the methods return an error initially, there is
+less chance that you will accidentally leave something in.
+
+Also, even though your conversion is basically a rewrite, it might help
+reviewers if you leave functions in the same place in the file,
+particularly for large drivers.
+
+
+5. Add some includes
+
+Add these includes to your driver:
+
+#include <dm.h>
+#include <errno.h>
+
+
+6. Build
+
+At this point you should be able to build U-Boot for your board with the
+empty SPI driver. You still have empty methods in your driver, but we will
+write these one by one.
+
+If you have spi_init() functions or the like that are called from your
+board then the build will fail. Remove these calls and make a note of the
+init that needs to be done.
+
+
+7. Set up your platform data structure
+
+This will hold the information your driver to operate, like its hardware
+address or maximum frequency.
+
+You may already have a struct like this, or you may need to create one
+from some of the #defines or global variables in the driver.
+
+Note that this information is not the run-time information. It should not
+include state that changes. It should be fixed throughout the live of
+U-Boot. Run-time information comes later.
+
+Here is what was in the exynos spi driver:
+
+struct spi_bus {
+	enum periph_id periph_id;
+	s32 frequency;		/* Default clock frequency, -1 for none */
+	struct exynos_spi *regs;
+	int inited;		/* 1 if this bus is ready for use */
+	int node;
+	uint deactivate_delay_us;	/* Delay to wait after deactivate */
+};
+
+Of these, inited is handled by DM and node is the device tree node, which
+DM tells you. The name is not quite right. So in this case we would use:
+
+struct exynos_spi_platdata {
+	enum periph_id periph_id;
+	s32 frequency;		/* Default clock frequency, -1 for none */
+	struct exynos_spi *regs;
+	uint deactivate_delay_us;	/* Delay to wait after deactivate */
+};
+
+
+8a. Write ofdata_to_platdata()   [for device tree only]
+
+This method will convert information in the device tree node into a C
+structure in your driver (called platform data). If you are not using
+device tree, go to 8b.
+
+DM will automatically allocate the struct for us when we are using device
+tree, but we need to tell it the size:
+
+U_BOOT_DRIVER(spi_exynos) = {
+...
+	.platdata_auto_alloc_size = sizeof(struct exynos_spi_platdata),
+
+
+Here is a sample function. It gets a pointer to the platform data and
+fills in the fields from device tree.
+
+static int exynos_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct exynos_spi_platdata *plat = bus->platdata;
+	const void *blob = gd->fdt_blob;
+	int node = bus->of_offset;
+
+	plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
+	plat->periph_id = pinmux_decode_periph_id(blob, node);
+
+	if (plat->periph_id == PERIPH_ID_NONE) {
+		debug("%s: Invalid peripheral ID %d\n", __func__,
+			plat->periph_id);
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	/* Use 500KHz as a suitable default */
+	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+					500000);
+	plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+					"spi-deactivate-delay", 0);
+	debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+	      __func__, plat->regs, plat->periph_id, plat->frequency,
+              plat->deactivate_delay_us);
+
+	return 0;
+}
+
+
+8b. Add the platform data  [non-device-tree only]
+
+Specify this data in a U_BOOT_DEVICE() declaration in your board file:
+
+struct exynos_spi_platdata platdata_spi0 = {
+	.periph_id = ...
+	.frequency = ...
+	.regs = ...
+	.deactivate_delay_us = ...
+};
+
+U_BOOT_DEVICE(board_spi0) = {
+	.name = "exynos_spi",
+	.platdata = &platdata_spi0,
+};
+
+You will unfortunately need to put the struct into a header file in this
+case so that your board file can use it.
+
+
+9. Add the device private data
+
+Most devices have some private data which they use to keep track of things
+while active. This is the run-time information and needs to be stored in
+a structure. There is probably a structure in the driver that includes a
+'struct spi_slave', so you can use that.
+
+struct exynos_spi_slave {
+	struct spi_slave slave;
+	struct exynos_spi *regs;
+	unsigned int freq;		/* Default frequency */
+	unsigned int mode;
+	enum periph_id periph_id;	/* Peripheral ID for this device */
+	unsigned int fifo_size;
+	int skip_preamble;
+	struct spi_bus *bus;		/* Pointer to our SPI bus info */
+	ulong last_transaction_us;	/* Time of last transaction end */
+};
+
+
+We should rename this to make its purpose more obvious, and get rid of
+the slave structure, so we have:
+
+struct exynos_spi_priv {
+	struct exynos_spi *regs;
+	unsigned int freq;		/* Default frequency */
+	unsigned int mode;
+	enum periph_id periph_id;	/* Peripheral ID for this device */
+	unsigned int fifo_size;
+	int skip_preamble;
+	ulong last_transaction_us;	/* Time of last transaction end */
+};
+
+
+DM can auto-allocate this also:
+
+U_BOOT_DRIVER(spi_exynos) = {
+...
+	.priv_auto_alloc_size = sizeof(struct exynos_spi_priv),
+
+
+Note that this is created before the probe method is called, and destroyed
+after the remove method is called. It will be zeroed when the probe
+method is called.
+
+
+10. Add the probe() and remove() methods
+
+Note: It's a good idea to build repeatedly as you are working, to avoid a
+huge amount of work getting things compiling at the end.
+
+The probe method is supposed to set up the hardware. U-Boot used to use
+spi_setup_slave() to do this. So take a look at this function and see
+what you can copy out to set things up.
+
+
+static int exynos_spi_probe(struct udevice *bus)
+{
+	struct exynos_spi_platdata *plat = dev_get_platdata(bus);
+	struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+	priv->regs = plat->regs;
+	if (plat->periph_id == PERIPH_ID_SPI1 ||
+	    plat->periph_id == PERIPH_ID_SPI2)
+		priv->fifo_size = 64;
+	else
+		priv->fifo_size = 256;
+
+	priv->skip_preamble = 0;
+	priv->last_transaction_us = timer_get_us();
+	priv->freq = plat->frequency;
+	priv->periph_id = plat->periph_id;
+
+	return 0;
+}
+
+This implementation doesn't actually touch the hardware, which is somewhat
+unusual for a driver. In this case we will do that when the device is
+claimed by something that wants to use the SPI bus.
+
+For remove we could shut down the clocks, but in this case there is
+nothing to do. DM frees any memory that it allocated, so we can just
+remove exynos_spi_remove() and its reference in U_BOOT_DRIVER.
+
+
+11. Implement set_speed()
+
+This should set up clocks so that the SPI bus is running at the right
+speed. With the old API spi_claim_bus() would normally do this and several
+of the following functions, so let's look at that function:
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+	struct exynos_spi *regs = spi_slave->regs;
+	u32 reg = 0;
+	int ret;
+
+	ret = set_spi_clk(spi_slave->periph_id,
+					spi_slave->freq);
+	if (ret < 0) {
+		debug("%s: Failed to setup spi clock\n", __func__);
+		return ret;
+	}
+
+	exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
+
+	spi_flush_fifo(slave);
+
+	reg = readl(&regs->ch_cfg);
+	reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+	if (spi_slave->mode & SPI_CPHA)
+		reg |= SPI_CH_CPHA_B;
+
+	if (spi_slave->mode & SPI_CPOL)
+		reg |= SPI_CH_CPOL_L;
+
+	writel(reg, &regs->ch_cfg);
+	writel(SPI_FB_DELAY_180, &regs->fb_clk);
+
+	return 0;
+}
+
+
+It sets up the speed, mode, pinmux, feedback delay and clears the FIFOs.
+With DM these will happen in separate methods.
+
+
+Here is an example for the speed part:
+
+static int exynos_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct exynos_spi_platdata *plat = bus->platdata;
+	struct exynos_spi_priv *priv = dev_get_priv(bus);
+	int ret;
+
+	if (speed > plat->frequency)
+		speed = plat->frequency;
+	ret = set_spi_clk(priv->periph_id, speed);
+	if (ret)
+		return ret;
+	priv->freq = speed;
+	debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+	return 0;
+}
+
+
+12. Implement set_mode()
+
+This should adjust the SPI mode (polarity, etc.). Again this code probably
+comes from the old spi_claim_bus(). Here is an example:
+
+
+static int exynos_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct exynos_spi_priv *priv = dev_get_priv(bus);
+	uint32_t reg;
+
+	reg = readl(&priv->regs->ch_cfg);
+	reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+	if (mode & SPI_CPHA)
+		reg |= SPI_CH_CPHA_B;
+
+	if (mode & SPI_CPOL)
+		reg |= SPI_CH_CPOL_L;
+
+	writel(reg, &priv->regs->ch_cfg);
+	priv->mode = mode;
+	debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+	return 0;
+}
+
+
+13. Implement claim_bus()
+
+This is where a client wants to make use of the bus, so claims it first.
+At this point we need to make sure everything is set up ready for data
+transfer. Note that this function is wholly internal to the driver - at
+present the SPI uclass never calls it.
+
+Here again we look at the old claim function and see some code that is
+needed. It is anything unrelated to speed and mode:
+
+static int exynos_spi_claim_bus(struct udevice *bus)
+{
+	struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+	exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
+	spi_flush_fifo(priv->regs);
+
+	writel(SPI_FB_DELAY_180, &priv->regs->fb_clk);
+
+	return 0;
+}
+
+The spi_flush_fifo() function is in the removed part of the code, so we
+need to expose it again (perhaps with an #endif before it and '#if 0'
+after it). It only needs access to priv->regs which is why we have
+passed that in:
+
+/**
+ * Flush spi tx, rx fifos and reset the SPI controller
+ *
+ * @param regs	Pointer to SPI registers
+ */
+static void spi_flush_fifo(struct exynos_spi *regs)
+{
+	clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
+	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+	setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+}
+
+
+14. Implement release_bus()
+
+This releases the bus - in our example the old code in spi_release_bus()
+is a call to spi_flush_fifo, so we add:
+
+static int exynos_spi_release_bus(struct udevice *bus)
+{
+	struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+	spi_flush_fifo(priv->regs);
+
+	return 0;
+}
+
+
+15. Implement xfer()
+
+This is the final method that we need to create, and it is where all the
+work happens. The method parameters are the same as the old spi_xfer() with
+the addition of a 'struct udevice' so conversion is pretty easy. Start
+by copying the contents of spi_xfer() to your new xfer() method and proceed
+from there.
+
+If (flags & SPI_XFER_BEGIN) is non-zero then xfer() normally calls an
+activate function, something like this:
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+	/* If it's too soon to do another transaction, wait */
+	if (spi_slave->bus->deactivate_delay_us &&
+	    spi_slave->last_transaction_us) {
+		ulong delay_us;		/* The delay completed so far */
+		delay_us = timer_get_us() - spi_slave->last_transaction_us;
+		if (delay_us < spi_slave->bus->deactivate_delay_us)
+			udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+	}
+
+	clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+	debug("Activate CS, bus %d\n", spi_slave->slave.bus);
+	spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+}
+
+The new version looks like this:
+
+static void spi_cs_activate(struct udevice *dev)
+{
+	struct udevice *bus = dev->parent;
+	struct exynos_spi_platdata *pdata = dev_get_platdata(bus);
+	struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+	/* If it's too soon to do another transaction, wait */
+	if (pdata->deactivate_delay_us &&
+	    priv->last_transaction_us) {
+		ulong delay_us;		/* The delay completed so far */
+		delay_us = timer_get_us() - priv->last_transaction_us;
+		if (delay_us < pdata->deactivate_delay_us)
+			udelay(pdata->deactivate_delay_us - delay_us);
+	}
+
+	clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+	debug("Activate CS, bus '%s'\n", bus->name);
+	priv->skip_preamble = priv->mode & SPI_PREAMBLE;
+}
+
+All we have really done here is change the pointers and print the device name
+instead of the bus number. Other local static functions can be treated in
+the same way.
+
+
+16. Set up the per-child data and child pre-probe function
+
+To minimise the pain and complexity of the SPI subsystem while the driver
+model change-over is in place, struct spi_slave is used to reference a
+SPI bus slave, even though that slave is actually a struct udevice. In fact
+struct spi_slave is the device's child data. We need to make sure this space
+is available. It is possible to allocate more space that struct spi_slave
+needs, but this is the minimum.
+
+U_BOOT_DRIVER(exynos_spi) = {
+...
+	.per_child_auto_alloc_size	= sizeof(struct spi_slave),
+}
+
+
+17. Optional: Set up cs_info() if you want it
+
+Sometimes it is useful to know whether a SPI chip select is valid, but this
+is not obvious from outside the driver. In this case you can provide a
+method for cs_info() to deal with this. If you don't provide it, then the
+device tree will be used to determine what chip selects are valid.
+
+Return -ENODEV if the supplied chip select is invalid, or 0 if it is valid.
+If you don't provide the cs_info() method, -ENODEV is assumed for all
+chip selects that do not appear in the device tree.
+
+
+18. Test it
+
+Now that you have the code written and it compiles, try testing it using
+the 'sf test' command. You may need to enable CONFIG_CMD_SF_TEST for your
+board.
+
+
+19. Prepare patches and send them to the mailing lists
+
+You can use 'tools/patman/patman' to prepare, check and send patches for
+your work. See the README for details.
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#38 lore raw

PATCH v4 15/29 dm: spi: Add documentation on how to convert over SPI drivers

Quoted 11 lines · Simon Glass

This README is intended to help maintainers move their SPI drivers over to driver model. It works through the required steps with an example.

---

Changes in v4: None
Changes in v3:
- Update for the new cs_info() method

Quoted 7 lines

Changes in v2:
- Fix typos reported by Jagannadha Sutradharudu Teki
- Update for changes to exynos driver

 doc/driver-model/spi-howto.txt | 594 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 594 insertions(+)
 create mode 100644 doc/driver-model/spi-howto.txt

Applied to u-boot-dm/master.

#39 lore raw

PATCH v4 16/29 exynos: universal_c210: Move to driver model soft_spi

In reply to Simon Glass

Adjust this board to use the driver model soft_spi implementation.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/dts/exynos4210-universal_c210.dts | 13 ++++++++
 board/samsung/universal_c210/universal.c   | 52 ------------------------------
 include/configs/s5pc210_universal.h        | 11 +------
 3 files changed, 14 insertions(+), 62 deletions(-)
arch/arm/dts/exynos4210-universal_c210.dts +13 -0
index cf3354f..9139810 100644
@@ -41,6 +41,19 @@
 		status = "disabled";
 	};
 
+	soft-spi {
+		compatible = "u-boot,soft-spi";
+		cs-gpio = <&gpio 235 0>;	/* Y43 */
+		sclk-gpio = <&gpio 225 0>;	/* Y31 */
+		mosi-gpio = <&gpio 227 0>;	/* Y33 */
+		miso-gpio = <&gpio 224 0>;	/* Y30 */
+		spi-delay-us = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cs at 0 {
+		};
+	};
+
 	fimd at 11c00000 {
 		compatible = "samsung,exynos-fimd";
 		reg = <0x11c00000 0xa4>;
board/samsung/universal_c210/universal.c +0 -52

70 lines not on this page · raw message

include/configs/s5pc210_universal.h +1 -10
index 4fa8d66..4b30d14 100644
@@ -187,16 +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)
-#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);
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#40 lore raw

PATCH v4 16/29 exynos: universal_c210: Move to driver model soft_spi

Quoted 6 lines · Simon Glass

Adjust this board to use the driver model soft_spi implementation.

---

Quoted 9 lines

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/dts/exynos4210-universal_c210.dts | 13 ++++++++
 board/samsung/universal_c210/universal.c   | 52 ------------------------------
 include/configs/s5pc210_universal.h        | 11 +------
 3 files changed, 14 insertions(+), 62 deletions(-)

Applied to u-boot-dm/master.

#41 lore raw

PATCH v4 17/29 sf: Tidy up public and private header files

In reply to Simon Glass

Since spi_flash.h is supposed to be the public API for SPI flash, move private things to sf_internal.h. Also tidy up a few comment nits.

---

Changes in v4: None
Changes in v3:
- Add spi.h header to 3 sh boards
- Rebase to master

Changes in v2: None

 board/buffalo/lsxl/lsxl.c           |  3 +-
 board/renesas/sh7752evb/sh7752evb.c |  1 +
 board/renesas/sh7753evb/sh7753evb.c |  1 +
 board/renesas/sh7757lcr/sh7757lcr.c |  1 +
 common/cmd_sf.c                     |  1 +
 drivers/mtd/spi/ramtron.c           |  1 +
 drivers/mtd/spi/sf_internal.h       | 67 +++++++++++++++++++++++++++++++++----
 drivers/mtd/spi/spi_spl_load.c      |  1 +
 include/spi_flash.h                 | 57 +++----------------------------
 9 files changed, 73 insertions(+), 60 deletions(-)
board/buffalo/lsxl/lsxl.c +2 -1
index 659a124..c1cb07b 100644
@@ -13,11 +13,12 @@
 #include <malloc.h>
 #include <netdev.h>
 #include <miiphy.h>
+#include <spi.h>
+#include <spi_flash.h>
 #include <asm/arch/kirkwood.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/gpio.h>
-#include <spi_flash.h>
 
 #include "lsxl.h"
 
board/renesas/sh7752evb/sh7752evb.c +1 -0
index 5eedbf8..3aad532 100644
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/mmc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 int checkboard(void)
board/renesas/sh7753evb/sh7753evb.c +1 -0
index 42b920f..9f64945 100644
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/mmc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 int checkboard(void)
board/renesas/sh7757lcr/sh7757lcr.c +1 -0
index 1464f48..ddcf275 100644
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/mmc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 int checkboard(void)
common/cmd_sf.c +1 -0
index c60e8d1..42d89d4 100644
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <div64.h>
 #include <malloc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 #include <asm/io.h>
drivers/mtd/spi/ramtron.c +1 -0
index d50da37..a23032c 100644
@@ -35,6 +35,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <spi.h>
 #include <spi_flash.h>
 #include "sf_internal.h"
 
drivers/mtd/spi/sf_internal.h +60 -7

104 lines not on this page · raw message

drivers/mtd/spi/spi_spl_load.c +1 -0
index 59cca0f..2e0c871 100644
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <spi.h>
 #include <spi_flash.h>
 #include <spl.h>
 
include/spi_flash.h +5 -52

86 lines not on this page · raw message

Signature · 1 line
2.1.0.rc2.206.gedb03e5
#42 lore raw

PATCH v4 17/29 sf: Tidy up public and private header files

Quoted 14 lines · Simon Glass

Since spi_flash.h is supposed to be the public API for SPI flash, move private things to sf_internal.h. Also tidy up a few comment nits.

---

Changes in v4: None
Changes in v3:
- Add spi.h header to 3 sh boards
- Rebase to master

Changes in v2: None

Quoted 11 lines
 board/buffalo/lsxl/lsxl.c           |  3 +-
 board/renesas/sh7752evb/sh7752evb.c |  1 +
 board/renesas/sh7753evb/sh7753evb.c |  1 +
 board/renesas/sh7757lcr/sh7757lcr.c |  1 +
 common/cmd_sf.c                     |  1 +
 drivers/mtd/spi/ramtron.c           |  1 +
 drivers/mtd/spi/sf_internal.h       | 67 +++++++++++++++++++++++++++++++++----
 drivers/mtd/spi/spi_spl_load.c      |  1 +
 include/spi_flash.h                 | 57 +++----------------------------
 9 files changed, 73 insertions(+), 60 deletions(-)

Applied to u-boot-dm/master.

#43 lore raw

PATCH v4 18/29 spi: Use error return value in sf_ops

In reply to Simon Glass

Adjust spi_flash_probe_slave() to return an error value instead of a pointer so we get the correct error return.

Have the caller allocate memory for spi_flash to simplify error handling, and also so that driver model can use its existing allocated memory.

Add a spi.h include in the sf_params file.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/mtd/spi/sf_probe.c | 90 +++++++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 33 deletions(-)
drivers/mtd/spi/sf_probe.c +57 -33
index 4d148d1..212a825 100644
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
 #include <spi.h>
@@ -95,15 +96,15 @@ static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
 	}
 }
 
-static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
-		u8 *idcode)
+static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
+				     struct spi_flash *flash)
 {
 	const struct spi_flash_params *params;
-	struct spi_flash *flash;
 	u8 cmd;
 	u16 jedec = idcode[1] << 8 | idcode[2];
 	u16 ext_jedec = idcode[3] << 8 | idcode[4];
 
+	/* Validate params from spi_flash_params table */
 	params = spi_flash_params_table;
 	for (; params->name != NULL; params++) {
 		if ((params->jedec >> 16) == idcode[0]) {
@@ -120,13 +121,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
 		printf("SF: Unsupported flash IDs: ");
 		printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
 		       idcode[0], jedec, ext_jedec);
-		return NULL;
-	}
-
-	flash = calloc(1, sizeof(*flash));
-	if (!flash) {
-		debug("SF: Failed to allocate spi_flash\n");
-		return NULL;
+		return -EPROTONOSUPPORT;
 	}
 
 	/* Assign spi data */
@@ -227,15 +222,18 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
 #ifdef CONFIG_SPI_FLASH_BAR
 	u8 curr_bank = 0;
 	if (flash->size > SPI_FLASH_16MB_BOUN) {
+		int ret;
+
 		flash->bank_read_cmd = (idcode[0] == 0x01) ?
 					CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
 		flash->bank_write_cmd = (idcode[0] == 0x01) ?
 					CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
 
-		if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
-					  &curr_bank, 1)) {
+		ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
+					    &curr_bank, 1);
+		if (ret) {
 			debug("SF: fail to read bank addr register\n");
-			return NULL;
+			return ret;
 		}
 		flash->bank_curr = curr_bank;
 	} else {
@@ -250,7 +248,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
 		spi_flash_cmd_write_status(flash, 0);
 #endif
 
-	return flash;
+	return 0;
 }
 
 #ifdef CONFIG_OF_CONTROL
@@ -309,23 +307,29 @@ static int spi_enable_wp_pin(struct spi_flash *flash)
 }
 #endif
 
-static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
+/**
+ * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
+ *
+ * @spi: Bus to probe
+ * @flashp: Pointer to place to put flash info, which may be NULL if the
+ * space should be allocated
+ */
+int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
 {
-	struct spi_flash *flash = NULL;
 	u8 idcode[5];
 	int ret;
 
 	/* Setup spi_slave */
 	if (!spi) {
 		printf("SF: Failed to set up slave\n");
-		return NULL;
+		return -ENODEV;
 	}
 
 	/* Claim spi bus */
 	ret = spi_claim_bus(spi);
 	if (ret) {
 		debug("SF: Failed to claim SPI bus: %d\n", ret);
-		goto err_claim_bus;
+		return ret;
 	}
 
 	/* Read the ID codes */
@@ -340,10 +344,10 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
 	print_buffer(0, idcode, 1, sizeof(idcode), 0);
 #endif
 
-	/* Validate params from spi_flash_params table */
-	flash = spi_flash_validate_params(spi, idcode);
-	if (!flash)
+	if (spi_flash_validate_params(spi, idcode, flash)) {
+		ret = -EINVAL;
 		goto err_read_id;
+	}
 
 	/* Set the quad enable bit - only for quad commands */
 	if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
@@ -351,13 +355,15 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
 	    (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
 		if (spi_flash_set_qeb(flash, idcode[0])) {
 			debug("SF: Fail to set QEB for %02x\n", idcode[0]);
-			return NULL;
+			ret = -EINVAL;
+			goto err_read_id;
 		}
 	}
 
 #ifdef CONFIG_OF_CONTROL
 	if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
 		debug("SF: FDT decode error\n");
+		ret = -EINVAL;
 		goto err_read_id;
 	}
 #endif
@@ -385,32 +391,50 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
 	/* Release spi bus */
 	spi_release_bus(spi);
 
-	return flash;
+	return 0;
 
 err_read_id:
 	spi_release_bus(spi);
-err_claim_bus:
-	spi_free_slave(spi);
-	return NULL;
+	return ret;
+}
+
+static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
+{
+	struct spi_flash *flash;
+
+	/* Allocate space if needed (not used by sf-uclass */
+	flash = calloc(1, sizeof(*flash));
+	if (!flash) {
+		debug("SF: Failed to allocate spi_flash\n");
+		return NULL;
+	}
+
+	if (spi_flash_probe_slave(bus, flash)) {
+		spi_free_slave(bus);
+		free(flash);
+		return NULL;
+	}
+
+	return flash;
 }
 
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
 		unsigned int max_hz, unsigned int spi_mode)
 {
-	struct spi_slave *spi;
+	struct spi_slave *bus;
 
-	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
-	return spi_flash_probe_slave(spi);
+	bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
+	return spi_flash_probe_tail(bus);
 }
 
 #ifdef CONFIG_OF_SPI_FLASH
 struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
 				      int spi_node)
 {
-	struct spi_slave *spi;
+	struct spi_slave *bus;
 
-	spi = spi_setup_slave_fdt(blob, slave_node, spi_node);
-	return spi_flash_probe_slave(spi);
+	bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
+	return spi_flash_probe_tail(bus);
 }
 #endif
 
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#44 lore raw

PATCH v4 18/29 spi: Use error return value in sf_ops

Quoted 10 lines · Simon Glass

Adjust spi_flash_probe_slave() to return an error value instead of a pointer so we get the correct error return.

Have the caller allocate memory for spi_flash to simplify error handling, and also so that driver model can use its existing allocated memory.

Add a spi.h include in the sf_params file.

Quoted 9 lines

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/mtd/spi/sf_probe.c | 90 +++++++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 33 deletions(-)

Applied to u-boot-dm/master.

#45 lore raw

PATCH v4 19/29 dm: sf: Add a uclass for SPI flash

In reply to Simon Glass

Add a driver model uclass for SPI flash which supports the common operations (read, write, erase). Since we must keep support for the non-dm interface, some modification of the spi_flash header is required.

CONFIG_DM_SPI_FLASH is used to enable driver model for SPI flash.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/mtd/spi/Makefile    |  7 ++++-
 drivers/mtd/spi/sf-uclass.c | 63 ++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h      |  1 +
 include/spi_flash.h         | 70 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi/sf-uclass.c
drivers/mtd/spi/Makefile +6 -1
index 9e18fb4..15789a0 100644
@@ -5,13 +5,18 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o
+
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_SPI_LOAD)	+= spi_spl_load.o
 obj-$(CONFIG_SPL_SPI_BOOT)	+= fsl_espi_spl.o
 endif
 
+#ifndef CONFIG_DM_SPI
+obj-$(CONFIG_SPI_FLASH) += sf_probe.o
+#endif
 obj-$(CONFIG_CMD_SF) += sf.o
-obj-$(CONFIG_SPI_FLASH) += sf_params.o sf_probe.o sf_ops.o
+obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o
 obj-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
 obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
drivers/mtd/spi/sf-uclass.c new file +63 -0

63 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index 6e56382..c92adb4 100644
@@ -25,6 +25,7 @@ enum uclass_id {
 	UCLASS_SERIAL,		/* Serial UART */
 	UCLASS_SPI,		/* SPI bus */
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
+	UCLASS_SPI_FLASH,	/* SPI flash */
 
 	UCLASS_COUNT,
 	UCLASS_INVALID = -1,
include/spi_flash.h +70 -0

101 lines not on this page · raw message

Signature · 1 line
2.1.0.rc2.206.gedb03e5
#46 lore raw

PATCH v4 19/29 dm: sf: Add a uclass for SPI flash

Quoted 14 lines · Simon Glass

Add a driver model uclass for SPI flash which supports the common operations (read, write, erase). Since we must keep support for the non-dm interface, some modification of the spi_flash header is required.

CONFIG_DM_SPI_FLASH is used to enable driver model for SPI flash.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

Quoted 7 lines
 drivers/mtd/spi/Makefile    |  7 ++++-
 drivers/mtd/spi/sf-uclass.c | 63 ++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h      |  1 +
 include/spi_flash.h         | 70 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi/sf-uclass.c

Applied to u-boot-dm/master.

#47 lore raw

PATCH v4 20/29 dm: Convert spi_flash_probe() and 'sf probe' to use driver model

In reply to Simon Glass

We want the SPI flash probing feature to operate as a standard driver. Add a driver for the basic probing feature used by most boards. This will be activated by device_probe() as with any other driver.

The 'sf probe' command currently keeps track of the SPI slave that it last used. This doesn't work with driver model, since some other driver or system may have probed the device and have access to it too. On the other hand, if we try to probe a device twice the second probe is a nop with driver model.

Fix this by searching for the matching device, removing it, and then probing it again. This should work as expected regardless of other device activity.

---

Changes in v4: None
Changes in v3:
- Add a debug() in the probe method
- Make sure the old device is both removed and unbound in 'sf probe'

Changes in v2: None

 common/cmd_sf.c            | 25 ++++++++++++++++++
 drivers/mtd/spi/sf_probe.c | 66 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 2 deletions(-)
common/cmd_sf.c +25 -0
index 42d89d4..95a6f89 100644
@@ -8,11 +8,13 @@
 
 #include <common.h>
 #include <div64.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spi.h>
 #include <spi_flash.h>
 
 #include <asm/io.h>
+#include <dm/device-internal.h>
 
 static struct spi_flash *flash;
 
@@ -81,7 +83,12 @@ static int do_spi_flash_probe(int argc, char * const argv[])
 	unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
 	unsigned int mode = CONFIG_SF_DEFAULT_MODE;
 	char *endp;
+#ifdef CONFIG_DM_SPI_FLASH
+	struct udevice *new, *bus_dev;
+	int ret;
+#else
 	struct spi_flash *new;
+#endif
 
 	if (argc >= 2) {
 		cs = simple_strtoul(argv[1], &endp, 0);
@@ -109,6 +116,23 @@ static int do_spi_flash_probe(int argc, char * const argv[])
 			return -1;
 	}
 
+#ifdef CONFIG_DM_SPI_FLASH
+	/* Remove the old device, otherwise probe will just be a nop */
+	ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
+	if (!ret) {
+		device_remove(new);
+		device_unbind(new);
+	}
+	flash = NULL;
+	ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
+	if (ret) {
+		printf("Failed to initialize SPI flash at %u:%u (error %d)\n",
+		       bus, cs, ret);
+		return 1;
+	}
+
+	flash = new->uclass_priv;
+#else
 	new = spi_flash_probe(bus, cs, speed, mode);
 	if (!new) {
 		printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
@@ -118,6 +142,7 @@ static int do_spi_flash_probe(int argc, char * const argv[])
 	if (flash)
 		spi_flash_free(flash);
 	flash = new;
+#endif
 
 	return 0;
 }
drivers/mtd/spi/sf_probe.c +64 -2

93 lines not on this page · raw message

Signature · 1 line
2.1.0.rc2.206.gedb03e5
#48 lore raw

PATCH v4 20/29 dm: Convert spi_flash_probe() and 'sf probe' to use driver model

Quoted 23 lines · Simon Glass

We want the SPI flash probing feature to operate as a standard driver. Add a driver for the basic probing feature used by most boards. This will be activated by device_probe() as with any other driver.

The 'sf probe' command currently keeps track of the SPI slave that it last used. This doesn't work with driver model, since some other driver or system may have probed the device and have access to it too. On the other hand, if we try to probe a device twice the second probe is a nop with driver model.

Fix this by searching for the matching device, removing it, and then probing it again. This should work as expected regardless of other device activity.

---

Changes in v4: None
Changes in v3:
- Add a debug() in the probe method
- Make sure the old device is both removed and unbound in 'sf probe'

Quoted 6 lines

Changes in v2: None

 common/cmd_sf.c            | 25 ++++++++++++++++++
 drivers/mtd/spi/sf_probe.c | 66 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 2 deletions(-)

Applied to u-boot-dm/master.

#49 lore raw

PATCH v4 21/29 dm: sf: sandbox: Convert SPI flash driver to driver model

In reply to Simon Glass

Convert sandbox's spi flash emulation driver to use driver model.

---

Changes in v4: None
Changes in v3:
- Add a few more debug() statements
- Use an explicit chip select value instead of reusing device sequence number

Changes in v2: None

 arch/sandbox/include/asm/spi.h   |  13 --
 arch/sandbox/include/asm/state.h |   1 -
 drivers/mtd/spi/sandbox.c        | 338 +++++++++++++++++++++++++++++++++------
 include/configs/sandbox.h        |   1 +
 4 files changed, 292 insertions(+), 61 deletions(-)
arch/sandbox/include/asm/spi.h +0 -13
index 49b4a0f..9985e3c 100644
@@ -33,19 +33,6 @@ struct sandbox_spi_emu_ops {
 };
 
 /*
- * There are times when the data lines are allowed to tristate.  What
- * is actually sensed on the line depends on the hardware.  It could
- * always be 0xFF/0x00 (if there are pull ups/downs), or things could
- * float and so we'd get garbage back.  This func encapsulates that
- * scenario so we can worry about the details here.
- */
-static inline void sandbox_spi_tristate(u8 *buf, uint len)
-{
-	/* XXX: make this into a user config option ? */
-	memset(buf, 0xff, len);
-}
-
-/*
  * Extract the bus/cs from the spi spec and return the start of the spi
  * client spec.  If the bus/cs are invalid for the current config, then
  * it returns NULL.
arch/sandbox/include/asm/state.h +0 -1
index 4e0981a..32d55cc 100644
@@ -42,7 +42,6 @@ enum state_terminal_raw {
 
 struct sandbox_spi_info {
 	const char *spec;
-	const struct sandbox_spi_emu_ops *ops;
 	struct udevice *emul;
 };
 
drivers/mtd/spi/sandbox.c +291 -47

516 lines not on this page · raw message

include/configs/sandbox.h +1 -0
index c80e4f0..9adc5cc 100644
@@ -98,6 +98,7 @@
 #define CONFIG_CMD_SPI
 #define CONFIG_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
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#50 lore raw

PATCH v4 21/29 dm: sf: sandbox: Convert SPI flash driver to driver model

Quoted 11 lines · Simon Glass

Convert sandbox's spi flash emulation driver to use driver model.

---

Changes in v4: None
Changes in v3:
- Add a few more debug() statements
- Use an explicit chip select value instead of reusing device sequence number

Quoted 7 lines

Changes in v2: None

 arch/sandbox/include/asm/spi.h   |  13 --
 arch/sandbox/include/asm/state.h |   1 -
 drivers/mtd/spi/sandbox.c        | 338 +++++++++++++++++++++++++++++++++------
 include/configs/sandbox.h        |   1 +
 4 files changed, 292 insertions(+), 61 deletions(-)

Applied to u-boot-dm/master.

#51 lore raw

PATCH v4 22/29 dm: exynos: config: Use driver model for SPI flash

In reply to Simon Glass

Use driver model for exynos5 board SPI flash.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/configs/exynos-common.h | 1 +
 1 file changed, 1 insertion(+)
include/configs/exynos-common.h +1 -0
index eb6745e..6ba9bb7 100644
@@ -22,6 +22,7 @@
 #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
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#53 lore raw

PATCH v4 23/29 dm: spi: Add tests

In reply to Simon Glass

These tests use SPI flash (and the sandbox emulation) to operate.

---

Changes in v4: None
Changes in v3:
- Expand SPI tests to cover compatibility functions
- Minor renames for clarity

Changes in v2:
- Create a 'spi.bin' file for the SPI tests

 test/dm/Makefile   |   1 +
 test/dm/spi.c      | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/dm/test-dm.sh |   2 +
 3 files changed, 130 insertions(+)
 create mode 100644 test/dm/spi.c
test/dm/Makefile +1 -0
index 5c2415e..d1b9c9a 100644
@@ -18,4 +18,5 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
+obj-$(CONFIG_DM_SPI) += spi.o
 endif
test/dm/spi.c new file +127 -0

127 lines not on this page · raw message

test/dm/test-dm.sh +2 -0
index ef5aca5..bb99677 100755
@@ -4,4 +4,6 @@ NUM_CPUS=$(cat /proc/cpuinfo |grep -c processor)
 dtc -I dts -O dtb test/dm/test.dts -o test/dm/test.dtb
 make O=sandbox sandbox_config
 make O=sandbox -s -j${NUM_CPUS}
+dd if=/dev/zero of=spi.bin bs=1M count=2
 ./sandbox/u-boot -d test/dm/test.dtb -c "dm test"
+rm spi.bin
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#54 lore raw

PATCH v4 23/29 dm: spi: Add tests

Quoted 11 lines · Simon Glass

These tests use SPI flash (and the sandbox emulation) to operate.

---

Changes in v4: None
Changes in v3:
- Expand SPI tests to cover compatibility functions
- Minor renames for clarity

Quoted 9 lines

Changes in v2:
- Create a 'spi.bin' file for the SPI tests

 test/dm/Makefile   |   1 +
 test/dm/spi.c      | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/dm/test-dm.sh |   2 +
 3 files changed, 130 insertions(+)
 create mode 100644 test/dm/spi.c

Applied to u-boot-dm/master.

#55 lore raw

PATCH v4 24/29 dm: sf: Add tests for SPI flash

In reply to Simon Glass

Add a simple test for SPI that uses SPI flash. It operates by creating a SPI flash file and using the 'sf test' command to test that all operations work correctly.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 test/dm/Makefile |  1 +
 test/dm/sf.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 17 ++++++++++++++++-
 3 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/sf.c
test/dm/Makefile +1 -0
index d1b9c9a..75d3d41 100644
@@ -19,4 +19,5 @@ obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_SPI) += spi.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 endif
test/dm/sf.c new file +43 -0

43 lines not on this page · raw message

test/dm/test.dts +16 -1
index 8489595..1fba792 100644
@@ -81,7 +81,7 @@
 		compatible = "google,another-fdt-test";
 	};
 
-	base-gpios {
+	gpio_a: base-gpios {
 		compatible = "sandbox,gpio";
 		gpio-bank-name = "a";
 		num-gpios = <20>;
@@ -92,4 +92,19 @@
 		gpio-bank-name = "b";
 		num-gpios = <10>;
 	};
+
+	spi at 0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0>;
+		compatible = "sandbox,spi";
+		cs-gpios = <0>, <&gpio_a 0>;
+		spi.bin at 0 {
+			reg = <0>;
+			compatible = "spansion,m25p16", "spi-flash";
+			spi-max-frequency = <40000000>;
+			sandbox,filename = "spi.bin";
+		};
+	};
+
 };
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#56 lore raw

PATCH v4 24/29 dm: sf: Add tests for SPI flash

Quoted 12 lines · Simon Glass

Add a simple test for SPI that uses SPI flash. It operates by creating a SPI flash file and using the 'sf test' command to test that all operations work correctly.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

Quoted 5 lines
 test/dm/Makefile |  1 +
 test/dm/sf.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 test/dm/test.dts | 17 ++++++++++++++++-
 3 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/sf.c

Applied to u-boot-dm/master.

#57 lore raw

PATCH v4 25/29 dm: tegra: dts: Add aliases for spi on tegra30 boards

In reply to Simon Glass

All boards with a SPI interface have a suitable spi alias except the tegra30 boards. Add these missing aliases.

---

Changes in v4: None
Changes in v3:
- Add new patch to add aliases for spi on tegra30 boards

Changes in v2: None

 arch/arm/dts/tegra20-trimslice.dts | 1 +
 arch/arm/dts/tegra30-beaver.dts    | 1 +
 arch/arm/dts/tegra30-cardhu.dts    | 1 +
 arch/arm/dts/tegra30-colibri.dts   | 1 +
 4 files changed, 4 insertions(+)
arch/arm/dts/tegra20-trimslice.dts +1 -0
index cee5cfe..74e8a16 100644
@@ -15,6 +15,7 @@
 		usb1 = "/usb at c5000000";
 		sdhci0 = "/sdhci at c8000600";
 		sdhci1 = "/sdhci at c8000000";
+		spi0 = "/spi at 7000c380";
 	};
 
 	memory {
arch/arm/dts/tegra30-beaver.dts +1 -0
index ad140de..9acd84d 100644
@@ -18,6 +18,7 @@
 		i2c4 = "/i2c at 7000c700";
 		sdhci0 = "/sdhci at 78000600";
 		sdhci1 = "/sdhci at 78000000";
+		spi0 = "/spi at 7000da00";
 		usb0 = "/usb at 7d000000";
 		usb1 = "/usb at 7d008000";
 	};
arch/arm/dts/tegra30-cardhu.dts +1 -0
index b4fbe71..1b8ed73 100644
@@ -18,6 +18,7 @@
 		i2c4 = "/i2c at 7000c700";
 		sdhci0 = "/sdhci at 78000600";
 		sdhci1 = "/sdhci at 78000000";
+		spi0 = "/spi at 7000da00";
 		usb0 = "/usb at 7d008000";
 	};
 
arch/arm/dts/tegra30-colibri.dts +1 -0
index 43d03ca..df79c26 100644
@@ -12,6 +12,7 @@
 		i2c2 = "/i2c at 7000c700";
 		sdhci0 = "/sdhci at 78000600";
 		sdhci1 = "/sdhci at 78000200";
+		spi0 = "/spi at 7000d400";
 		usb0 = "/usb at 7d000000";
 		usb1 = "/usb at 7d004000"; /* on module only, for ASIX */
 		usb2 = "/usb at 7d008000";
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#58 lore raw

PATCH v4 25/29 dm: tegra: dts: Add aliases for spi on tegra30 boards

Quoted 11 lines · Simon Glass

All boards with a SPI interface have a suitable spi alias except the tegra30 boards. Add these missing aliases.

---

Changes in v4: None
Changes in v3:
- Add new patch to add aliases for spi on tegra30 boards

Quoted 7 lines

Changes in v2: None

 arch/arm/dts/tegra20-trimslice.dts | 1 +
 arch/arm/dts/tegra30-beaver.dts    | 1 +
 arch/arm/dts/tegra30-cardhu.dts    | 1 +
 arch/arm/dts/tegra30-colibri.dts   | 1 +
 4 files changed, 4 insertions(+)

Applied to u-boot-dm/master.

#59 lore raw

PATCH v4 26/29 dm: tegra: spi: Convert to driver model

In reply to Simon Glass

This converts the Tegra SPI drivers to use driver model. This is tested on:

- Tegra20 - trimslice
- Tegra30 - beaver
- Tegra124 - dalmore

(not tested on Tegra124)

---

Changes in v4:
- Drop the incorrect compulab hunk from this patch

Changes in v3:
- Add implementation/comment for the cs_info() method
- Add new patch to convert Tegra SPI to driver model

Changes in v2: None

 arch/arm/include/asm/arch-tegra114/tegra114_spi.h  |  41 ----
 arch/arm/include/asm/arch-tegra20/tegra20_sflash.h |  41 ----
 arch/arm/include/asm/arch-tegra20/tegra20_slink.h  |  41 ----
 board/nvidia/common/board.c                        |   3 +-
 drivers/spi/Makefile                               |   1 -
 drivers/spi/fdt_spi.c                              | 186 ---------------
 drivers/spi/tegra114_spi.c                         | 254 +++++++++++----------
 drivers/spi/tegra20_sflash.c                       | 238 ++++++++++---------
 drivers/spi/tegra20_slink.c                        | 235 ++++++++++---------
 drivers/spi/tegra_spi.h                            |  12 +
 include/configs/tegra-common-post.h                |   2 +-
 include/configs/tegra-common.h                     |   2 +
 12 files changed, 396 insertions(+), 660 deletions(-)
 delete mode 100644 arch/arm/include/asm/arch-tegra114/tegra114_spi.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_sflash.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_slink.h
 delete mode 100644 drivers/spi/fdt_spi.c
 create mode 100644 drivers/spi/tegra_spi.h
arch/arm/include/asm/arch-tegra114/tegra114_spi.h deleted +0 -41
deleted file mode 100644
index 48197bc..0000000
@@ -1,41 +0,0 @@
-/*
- * NVIDIA Tegra SPI controller
- *
- * Copyright 2010-2013 NVIDIA Corporation
- *
- * This software may be used and distributed according to the
- * terms of the GNU Public License, Version 2, incorporated
- * herein by reference.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * Version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#ifndef _TEGRA114_SPI_H_
-#define _TEGRA114_SPI_H_
-
-#include <asm/types.h>
-
-int tegra114_spi_init(int *node_list, int count);
-int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs);
-struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
-				  unsigned int max_hz, unsigned int mode);
-void tegra114_spi_free_slave(struct spi_slave *slave);
-int tegra114_spi_claim_bus(struct spi_slave *slave);
-void tegra114_spi_cs_activate(struct spi_slave *slave);
-void tegra114_spi_cs_deactivate(struct spi_slave *slave);
-int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-		     const void *data_out, void *data_in, unsigned long flags);
-
-#endif	/* _TEGRA114_SPI_H_ */
arch/arm/include/asm/arch-tegra20/tegra20_sflash.h deleted +0 -41

41 lines not on this page · raw message

arch/arm/include/asm/arch-tegra20/tegra20_slink.h deleted +0 -41

41 lines not on this page · raw message

board/nvidia/common/board.c +1 -2
index d01abce..03f055d 100644
@@ -114,9 +114,8 @@ int board_init(void)
 	clock_init();
 	clock_verify();
 
-#ifdef CONFIG_FDT_SPI
+#ifdef CONFIG_TEGRA_SPI
 	pin_mux_spi();
-	spi_init();
 #endif
 
 #ifdef CONFIG_PWM_TEGRA
drivers/spi/Makefile +0 -1
index e718528..eabbf27 100644
@@ -40,7 +40,6 @@ obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
 obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
 obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
-obj-$(CONFIG_FDT_SPI) += fdt_spi.o
 obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
 obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
drivers/spi/fdt_spi.c deleted +0 -186

186 lines not on this page · raw message

drivers/spi/tegra114_spi.c +134 -120

343 lines not on this page · raw message

drivers/spi/tegra20_sflash.c +125 -113

331 lines not on this page · raw message

drivers/spi/tegra20_slink.c +121 -114

322 lines not on this page · raw message

drivers/spi/tegra_spi.h new file +12 -0
new file mode 100644
index 0000000..fb2b50f
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+struct tegra_spi_platdata {
+	enum periph_id periph_id;
+	int frequency;		/* Default clock frequency, -1 for none */
+	ulong base;
+	uint deactivate_delay_us;	/* Delay to wait after deactivate */
+};
include/configs/tegra-common-post.h +1 -1
index 23e3c8a..a258699 100644
@@ -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 */
include/configs/tegra-common.h +2 -0
index 834b3d5..4719ee1 100644
@@ -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
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#60 lore raw

PATCH v4 26/29 dm: tegra: spi: Convert to driver model

Quoted 32 lines · Simon Glass

This converts the Tegra SPI drivers to use driver model. This is tested on:

- Tegra20 - trimslice
- Tegra30 - beaver
- Tegra124 - dalmore

(not tested on Tegra124)

---

Changes in v4:
- Drop the incorrect compulab hunk from this patch

Changes in v3:
- Add implementation/comment for the cs_info() method
- Add new patch to convert Tegra SPI to driver model

Changes in v2: None

 arch/arm/include/asm/arch-tegra114/tegra114_spi.h  |  41 ----
 arch/arm/include/asm/arch-tegra20/tegra20_sflash.h |  41 ----
 arch/arm/include/asm/arch-tegra20/tegra20_slink.h  |  41 ----
 board/nvidia/common/board.c                        |   3 +-
 drivers/spi/Makefile                               |   1 -
 drivers/spi/fdt_spi.c                              | 186 ---------------
 drivers/spi/tegra114_spi.c                         | 254 +++++++++++----------
 drivers/spi/tegra20_sflash.c                       | 238 ++++++++++---------
 drivers/spi/tegra20_slink.c                        | 235 ++++++++++---------
 drivers/spi/tegra_spi.h                            |  12 +
Quoted 9 lines
 include/configs/tegra-common-post.h                |   2 +-
 include/configs/tegra-common.h                     |   2 +
 12 files changed, 396 insertions(+), 660 deletions(-)
 delete mode 100644 arch/arm/include/asm/arch-tegra114/tegra114_spi.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_sflash.h
 delete mode 100644 arch/arm/include/asm/arch-tegra20/tegra20_slink.h
 delete mode 100644 drivers/spi/fdt_spi.c
 create mode 100644 drivers/spi/tegra_spi.h

Applied to u-boot-dm/master.

#61 lore raw

PATCH v4 27/29 dm: cros_ec: Add support for driver model

In reply to Simon Glass

Add support for driver model if enabled. This involves minimal changes to the code, mostly just plumbing around the edges.

---

Changes in v4:
- Remove a extra tab character (oops)

Changes in v3:
- Add a missing tab character

Changes in v2: None

 common/cros_ec.c               |  30 ++++++++++
 drivers/misc/cros_ec.c         | 122 +++++++++++++++++++++++++++++++++++++----
 drivers/misc/cros_ec_sandbox.c |   9 ++-
 include/cros_ec.h              |  27 ++++++++-
 include/dm/uclass-id.h         |   1 +
 5 files changed, 174 insertions(+), 15 deletions(-)
common/cros_ec.c +30 -0
index b8ce1b5..bb299bc 100644
@@ -10,25 +10,44 @@
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
+#include <errno.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_DM_CROS_EC
 struct local_info {
 	struct cros_ec_dev *cros_ec_dev;	/* Pointer to cros_ec device */
 	int cros_ec_err;			/* Error for cros_ec, 0 if ok */
 };
 
 static struct local_info local;
+#endif
 
 struct cros_ec_dev *board_get_cros_ec_dev(void)
 {
+#ifdef CONFIG_DM_CROS_EC
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
+	if (ret) {
+		debug("%s: Error %d\n", __func__, ret);
+		return NULL;
+	}
+	return dev->uclass_priv;
+#else
 	return local.cros_ec_dev;
+#endif
 }
 
 static int board_init_cros_ec_devices(const void *blob)
 {
+#ifndef CONFIG_DM_CROS_EC
 	local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev);
 	if (local.cros_ec_err)
 		return -1;  /* Will report in board_late_init() */
+#endif
 
 	return 0;
 }
@@ -40,5 +59,16 @@ int cros_ec_board_init(void)
 
 int cros_ec_get_error(void)
 {
+#ifdef CONFIG_DM_CROS_EC
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
+	if (ret && ret != -ENODEV)
+		return ret;
+
+	return 0;
+#else
 	return local.cros_ec_err;
+#endif
 }
drivers/misc/cros_ec.c +110 -12

248 lines not on this page · raw message

drivers/misc/cros_ec_sandbox.c +7 -2
index 8a04af5..431cf26 100644
@@ -525,8 +525,13 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
 	int node;
 	int err;
 
-	state = &s_state;
-	err = cros_ec_decode_ec_flash(blob, &ec->ec_config);
+	node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
+	if (node < 0) {
+		debug("Failed to find chrome-ec node'\n");
+		return -1;
+	}
+
+	err = cros_ec_decode_ec_flash(blob, node, &ec->ec_config);
 	if (err)
 		return err;
 
include/cros_ec.h +26 -1
index 1e4d8db..9e13146 100644
@@ -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.
include/dm/uclass-id.h +1 -0
index c92adb4..0ea7a6f 100644
@@ -26,6 +26,7 @@ enum uclass_id {
 	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,
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#62 lore raw

PATCH v4 27/29 dm: cros_ec: Add support for driver model

Quoted 13 lines · Simon Glass

Add support for driver model if enabled. This involves minimal changes to the code, mostly just plumbing around the edges.

---

Changes in v4:
- Remove a extra tab character (oops)

Changes in v3:
- Add a missing tab character

Quoted 9 lines

Changes in v2: None

 common/cros_ec.c               |  30 ++++++++++
 drivers/misc/cros_ec.c         | 122 +++++++++++++++++++++++++++++++++++++----
 drivers/misc/cros_ec_sandbox.c |   9 ++-
 include/cros_ec.h              |  27 ++++++++-
 include/dm/uclass-id.h         |   1 +
 5 files changed, 174 insertions(+), 15 deletions(-)

Applied to u-boot-dm/master.

#63 lore raw

PATCH v4 28/29 dm: sandbox: cros_ec: Move sandbox cros_ec to driver module

In reply to Simon Glass

Adjust the sandbox cros_ec emulation driver to work with driver model, and switch over to driver model for sandbox cros_ec.

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/misc/cros_ec_sandbox.c | 90 +++++++++++++++++++++++++++++++++++++++---
 include/configs/sandbox.h      |  1 +
 2 files changed, 86 insertions(+), 5 deletions(-)
drivers/misc/cros_ec_sandbox.c +85 -5
index 431cf26..99cc529 100644
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
 #include <ec_commands.h>
 #include <errno.h>
 #include <hash.h>
@@ -85,7 +86,7 @@ struct ec_state {
 	struct ec_keymatrix_entry *matrix;	/* the key matrix info */
 	uint8_t keyscan[KEYBOARD_COLS];
 	bool recovery_req;
-} s_state, *state;
+} s_state, *g_state;
 
 /**
  * cros_ec_read_state() - read the sandbox EC state from the state file
@@ -138,7 +139,7 @@ static int cros_ec_read_state(const void *blob, int node)
  */
 static int cros_ec_write_state(void *blob, int node)
 {
-	struct ec_state *ec = &s_state;
+	struct ec_state *ec = g_state;
 
 	/* We are guaranteed enough space to write basic properties */
 	fdt_setprop_u32(blob, node, "current-image", ec->current_image);
@@ -369,7 +370,7 @@ static int process_cmd(struct ec_state *ec,
 		struct fmap_entry *entry;
 		int ret, size;
 
-		entry = &state->ec_config.region[EC_FLASH_REGION_RW];
+		entry = &ec->ec_config.region[EC_FLASH_REGION_RW];
 
 		switch (req->cmd) {
 		case EC_VBOOT_HASH_RECALC:
@@ -426,7 +427,7 @@ static int process_cmd(struct ec_state *ec,
 		case EC_FLASH_REGION_RO:
 		case EC_FLASH_REGION_RW:
 		case EC_FLASH_REGION_WP_RO:
-			entry = &state->ec_config.region[req->region];
+			entry = &ec->ec_config.region[req->region];
 			resp->offset = entry->offset;
 			resp->size = entry->length;
 			len = sizeof(*resp);
@@ -466,16 +467,24 @@ static int process_cmd(struct ec_state *ec,
 	return len;
 }
 
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+	struct cros_ec_dev *dev = udev->uclass_priv;
+	struct ec_state *ec = dev_get_priv(dev->dev);
+#else
 int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
 			   int in_bytes)
 {
+	struct ec_state *ec = &s_state;
+#endif
 	struct ec_host_request *req_hdr = (struct ec_host_request *)dev->dout;
 	const void *req_data = req_hdr + 1;
 	struct ec_host_response *resp_hdr = (struct ec_host_response *)dev->din;
 	void *resp_data = resp_hdr + 1;
 	int len;
 
-	len = process_cmd(&s_state, req_hdr, req_data, resp_hdr, resp_data);
+	len = process_cmd(ec, req_hdr, req_data, resp_hdr, resp_data);
 	if (len < 0)
 		return len;
 
@@ -498,7 +507,11 @@ int cros_ec_sandbox_decode_fdt(struct cros_ec_dev *dev, const void *blob)
 
 void cros_ec_check_keyboard(struct cros_ec_dev *dev)
 {
+#ifdef CONFIG_DM_CROS_EC
+	struct ec_state *ec = dev_get_priv(dev->dev);
+#else
 	struct ec_state *ec = &s_state;
+#endif
 	ulong start;
 
 	printf("Press keys for EC to detect on reset (ESC=recovery)...");
@@ -512,6 +525,52 @@ void cros_ec_check_keyboard(struct cros_ec_dev *dev)
 	}
 }
 
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_probe(struct udevice *dev)
+{
+	struct ec_state *ec = dev->priv;
+	struct cros_ec_dev *cdev = dev->uclass_priv;
+	const void *blob = gd->fdt_blob;
+	int node;
+	int err;
+
+	memcpy(ec, &s_state, sizeof(*ec));
+	err = cros_ec_decode_ec_flash(blob, dev->of_offset, &ec->ec_config);
+	if (err)
+		return err;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+	if (node < 0) {
+		debug("%s: No cros_ec keyboard found\n", __func__);
+	} else if (keyscan_read_fdt_matrix(ec, blob, node)) {
+		debug("%s: Could not read key matrix\n", __func__);
+		return -1;
+	}
+
+	/* If we loaded EC data, check that the length matches */
+	if (ec->flash_data &&
+	    ec->flash_data_len != ec->ec_config.flash.length) {
+		printf("EC data length is %x, expected %x, discarding data\n",
+		       ec->flash_data_len, ec->ec_config.flash.length);
+		os_free(ec->flash_data);
+		ec->flash_data = NULL;
+	}
+
+	/* Otherwise allocate the memory */
+	if (!ec->flash_data) {
+		ec->flash_data_len = ec->ec_config.flash.length;
+		ec->flash_data = os_malloc(ec->flash_data_len);
+		if (!ec->flash_data)
+			return -ENOMEM;
+	}
+
+	cdev->dev = dev;
+	g_state = ec;
+	return cros_ec_register(dev);
+}
+
+#else
+
 /**
  * Initialize sandbox EC emulation.
  *
@@ -562,3 +621,24 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
 
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_CROS_EC
+struct dm_cros_ec_ops cros_ec_ops = {
+	.packet = cros_ec_sandbox_packet,
+};
+
+static const struct udevice_id cros_ec_ids[] = {
+	{ .compatible = "google,cros-ec" },
+	{ }
+};
+
+U_BOOT_DRIVER(cros_ec_sandbox) = {
+	.name		= "cros_ec",
+	.id		= UCLASS_CROS_EC,
+	.of_match	= cros_ec_ids,
+	.probe		= cros_ec_probe,
+	.priv_auto_alloc_size = sizeof(struct ec_state),
+	.ops		= &cros_ec_ops,
+};
+#endif
include/configs/sandbox.h +1 -0
index 9adc5cc..2fd2c64 100644
@@ -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
 
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#64 lore raw

PATCH v4 28/29 dm: sandbox: cros_ec: Move sandbox cros_ec to driver module

Quoted 7 lines · Simon Glass

Adjust the sandbox cros_ec emulation driver to work with driver model, and switch over to driver model for sandbox cros_ec.

---

Quoted 8 lines

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/misc/cros_ec_sandbox.c | 90 +++++++++++++++++++++++++++++++++++++++---
 include/configs/sandbox.h      |  1 +
 2 files changed, 86 insertions(+), 5 deletions(-)

Applied to u-boot-dm/master.

#65 lore raw

PATCH v4 29/29 dm: exynos: cros_ec: Move cros_ec_spi to driver model

In reply to Simon Glass

Adjust this driver to use driver model and move smdk5420 boards over to use it.

Series-changes 4
- Add review/ack tags for SPI maintainer (Jagan)

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/misc/cros_ec_spi.c  | 68 +++++++++++++++++++++++++++++++++++++++------
 include/configs/peach-pit.h |  1 +
 2 files changed, 60 insertions(+), 9 deletions(-)
drivers/misc/cros_ec_spi.c +59 -9
index 015333f..89616ce 100644
@@ -15,23 +15,34 @@
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
+#include <errno.h>
 #include <spi.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+	struct cros_ec_dev *dev = udev->uclass_priv;
+#else
 int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
 {
+#endif
+	struct spi_slave *slave = dev_get_parentdata(dev->dev);
 	int rv;
 
 	/* Do the transfer */
-	if (spi_claim_bus(dev->spi)) {
+	if (spi_claim_bus(slave)) {
 		debug("%s: Cannot claim SPI bus\n", __func__);
 		return -1;
 	}
 
-	rv = spi_xfer(dev->spi, max(out_bytes, in_bytes) * 8,
+	rv = spi_xfer(slave, max(out_bytes, in_bytes) * 8,
 		      dev->dout, dev->din,
 		      SPI_XFER_BEGIN | SPI_XFER_END);
 
-	spi_release_bus(dev->spi);
+	spi_release_bus(slave);
 
 	if (rv) {
 		debug("%s: Cannot complete SPI transfer\n", __func__);
@@ -56,10 +67,19 @@ int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
  * @param din_len	Maximum size of response in bytes
  * @return number of bytes in response, or -1 on error
  */
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_spi_command(struct udevice *udev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len)
+{
+	struct cros_ec_dev *dev = udev->uclass_priv;
+#else
 int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 		     const uint8_t *dout, int dout_len,
 		     uint8_t **dinp, int din_len)
 {
+#endif
+	struct spi_slave *slave = dev_get_parentdata(dev->dev);
 	int in_bytes = din_len + 4;	/* status, length, checksum, trailer */
 	uint8_t *out;
 	uint8_t *p;
@@ -92,7 +112,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 	 */
 	memset(dev->din, '\0', in_bytes);
 
-	if (spi_claim_bus(dev->spi)) {
+	if (spi_claim_bus(slave)) {
 		debug("%s: Cannot claim SPI bus\n", __func__);
 		return -1;
 	}
@@ -113,10 +133,10 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 	p = dev->din + sizeof(int64_t) - 2;
 	len = dout_len + 4;
 	cros_ec_dump_data("out", cmd, out, len);
-	rv = spi_xfer(dev->spi, max(len, in_bytes) * 8, out, p,
+	rv = spi_xfer(slave, max(len, in_bytes) * 8, out, p,
 		      SPI_XFER_BEGIN | SPI_XFER_END);
 
-	spi_release_bus(dev->spi);
+	spi_release_bus(slave);
 
 	if (rv) {
 		debug("%s: Cannot complete SPI transfer\n", __func__);
@@ -146,6 +166,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 	return len;
 }
 
+#ifndef CONFIG_DM_CROS_EC
 int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
 {
 	/* Decode interface-specific FDT params */
@@ -165,11 +186,40 @@ int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
  */
 int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
 {
-	dev->spi = spi_setup_slave_fdt(blob, dev->node, dev->parent_node);
-	if (!dev->spi) {
+	int ret;
+
+	ret = spi_setup_slave_fdt(blob, dev->node, dev->parent_node,
+				  &slave);
+	if (ret) {
 		debug("%s: Could not setup SPI slave\n", __func__);
-		return -1;
+		return ret;
 	}
 
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_probe(struct udevice *dev)
+{
+	return cros_ec_register(dev);
+}
+
+struct dm_cros_ec_ops cros_ec_ops = {
+	.packet = cros_ec_spi_packet,
+	.command = cros_ec_spi_command,
+};
+
+static const struct udevice_id cros_ec_ids[] = {
+	{ .compatible = "google,cros-ec" },
+	{ }
+};
+
+U_BOOT_DRIVER(cros_ec_spi) = {
+	.name		= "cros_ec",
+	.id		= UCLASS_CROS_EC,
+	.of_match	= cros_ec_ids,
+	.probe		= cros_ec_probe,
+	.ops		= &cros_ec_ops,
+};
+#endif
include/configs/peach-pit.h +1 -0
index ab8ac60..91bd37d 100644
@@ -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
Signature · 1 line
2.1.0.rc2.206.gedb03e5
#66 lore raw

PATCH v4 29/29 dm: exynos: cros_ec: Move cros_ec_spi to driver model

Quoted 10 lines · Simon Glass

Adjust this driver to use driver model and move smdk5420 boards over to use it.

Series-changes 4
- Add review/ack tags for SPI maintainer (Jagan)

---

Quoted 8 lines

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/misc/cros_ec_spi.c  | 68 +++++++++++++++++++++++++++++++++++++++------
 include/configs/peach-pit.h |  1 +
 2 files changed, 60 insertions(+), 9 deletions(-)

Applied to u-boot-dm/master.

With a comment and a device tree decode call added to cros_ec_probe() to work around a current limitation, unfortunately.