From e369e58df79cf152c299b898e31c42f08167082a Mon Sep 17 00:00:00 2001 From: Mario Six Date: Tue, 26 Jun 2018 08:46:48 +0200 Subject: core: Add functions to set properties in live-tree Implement a set of functions to manipulate properties in a live device tree: * ofnode_write_prop() to set generic properties of a node * ofnode_write_string() to set string properties of a node * ofnode_set_enabled() to either enable or disable a node Signed-off-by: Mario Six Reviewed-by: Simon Glass --- drivers/core/ofnode.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'drivers') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index a7e19277232..1e354803b06 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -791,3 +791,73 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname, propname, propval, proplen)); } } + +int ofnode_write_prop(ofnode node, const char *propname, int len, + const void *value) +{ + const struct device_node *np = ofnode_to_np(node); + struct property *pp; + struct property *pp_last = NULL; + struct property *new; + + if (!of_live_active()) + return -ENOSYS; + + if (!np) + return -EINVAL; + + for (pp = np->properties; pp; pp = pp->next) { + if (strcmp(pp->name, propname) == 0) { + /* Property exists -> change value */ + pp->value = (void *)value; + pp->length = len; + return 0; + } + pp_last = pp; + } + + if (!pp_last) + return -ENOENT; + + /* Property does not exist -> append new property */ + new = malloc(sizeof(struct property)); + if (!new) + return -ENOMEM; + + new->name = strdup(propname); + if (!new->name) + return -ENOMEM; + + new->value = (void *)value; + new->length = len; + new->next = NULL; + + pp_last->next = new; + + return 0; +} + +int ofnode_write_string(ofnode node, const char *propname, const char *value) +{ + if (!of_live_active()) + return -ENOSYS; + + assert(ofnode_valid(node)); + + debug("%s: %s = %s", __func__, propname, value); + + return ofnode_write_prop(node, propname, strlen(value) + 1, value); +} + +int ofnode_set_enabled(ofnode node, bool value) +{ + if (!of_live_active()) + return -ENOSYS; + + assert(ofnode_valid(node)); + + if (value) + return ofnode_write_string(node, "status", "okay"); + else + return ofnode_write_string(node, "status", "disable"); +} -- cgit v1.3.1 From e4c98a59db99e6bfba74d27cc571d59213acb64e Mon Sep 17 00:00:00 2001 From: Mario Six Date: Tue, 26 Jun 2018 08:46:50 +0200 Subject: core: Add dev_{disable,enable}_by_path We cannot use device structures to disable devices, since getting them with the API functions would bind and activate the device, which would fail if the underlying device does not exist. Reviewed-by: Simon Glass --- drivers/core/device.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/dm/device.h | 16 +++++++++++ 2 files changed, 94 insertions(+) (limited to 'drivers') diff --git a/drivers/core/device.c b/drivers/core/device.c index fd59fe1e0f5..feed43c8c3e 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -516,6 +516,33 @@ static int device_get_device_tail(struct udevice *dev, int ret, return 0; } +/** + * device_find_by_ofnode() - Return device associated with given ofnode + * + * The returned device is *not* activated. + * + * @node: The ofnode for which a associated device should be looked up + * @devp: Pointer to structure to hold the found device + * Return: 0 if OK, -ve on error + */ +static int device_find_by_ofnode(ofnode node, struct udevice **devp) +{ + struct uclass *uc; + struct udevice *dev; + int ret; + + list_for_each_entry(uc, &gd->uclass_root, sibling_node) { + ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node, + &dev); + if (!ret || dev) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + int device_get_child(struct udevice *parent, int index, struct udevice **devp) { struct udevice *dev; @@ -739,3 +766,54 @@ bool of_machine_is_compatible(const char *compat) return !fdt_node_check_compatible(fdt, 0, compat); } + +int dev_disable_by_path(const char *path) +{ + struct uclass *uc; + ofnode node = ofnode_path(path); + struct udevice *dev; + int ret = 1; + + if (!of_live_active()) + return -ENOSYS; + + list_for_each_entry(uc, &gd->uclass_root, sibling_node) { + ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node, &dev); + if (!ret) + break; + } + + if (ret) + return ret; + + ret = device_remove(dev, DM_REMOVE_NORMAL); + if (ret) + return ret; + + ret = device_unbind(dev); + if (ret) + return ret; + + return ofnode_set_enabled(node, false); +} + +int dev_enable_by_path(const char *path) +{ + ofnode node = ofnode_path(path); + ofnode pnode = ofnode_get_parent(node); + struct udevice *parent; + int ret = 1; + + if (!of_live_active()) + return -ENOSYS; + + ret = device_find_by_ofnode(pnode, &parent); + if (ret) + return ret; + + ret = ofnode_set_enabled(node, true); + if (ret) + return ret; + + return lists_bind_fdt(parent, node, NULL); +} diff --git a/include/dm/device.h b/include/dm/device.h index 3120b68fcc6..9812d86f08b 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -600,6 +600,22 @@ bool device_is_compatible(struct udevice *dev, const char *compat); */ bool of_machine_is_compatible(const char *compat); +/** + * dev_disable_by_path() - Disable a device given its device tree path + * + * @path: The device tree path identifying the device to be disabled + * @return 0 on success, -ve on error + */ +int dev_disable_by_path(const char *path); + +/** + * dev_enable_by_path() - Enable a device given its device tree path + * + * @path: The device tree path identifying the device to be enabled + * @return 0 on success, -ve on error + */ +int dev_enable_by_path(const char *path); + /** * device_is_on_pci_bus - Test if a device is on a PCI bus * -- cgit v1.3.1 From 5381c2856de3ed0191135b435cff39789e5f17ad Mon Sep 17 00:00:00 2001 From: Mario Six Date: Tue, 31 Jul 2018 11:44:11 +0200 Subject: drivers: Add board uclass Since there is no canonical "board device" that can be used in board files, it is difficult to use DM function for board initialization in these cases. Hence, add a uclass that implements a simple "board device", which can hold devices not suitable anywhere else in the device tree, and is also able to read encoded information, e.g. hard-wired GPIOs on a GPIO expander, read-only memory ICs, etc. that carry information about the hardware. The devices of this uclass expose methods to read generic data types (integers, strings, booleans) to encode the information provided by the hardware. Reviewed-by: Simon Glass Signed-off-by: Mario Six --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/board/Kconfig | 7 +++ drivers/board/Makefile | 6 ++ drivers/board/board-uclass.c | 60 +++++++++++++++++++ include/board.h | 139 +++++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + 7 files changed, 216 insertions(+) create mode 100644 drivers/board/Kconfig create mode 100644 drivers/board/Makefile create mode 100644 drivers/board/board-uclass.c create mode 100644 include/board.h (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 56536c4b191..64ba5bf25f1 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -24,6 +24,8 @@ source "drivers/ddr/Kconfig" source "drivers/demo/Kconfig" +source "drivers/board/Kconfig" + source "drivers/ddr/fsl/Kconfig" source "drivers/dfu/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 23ea609b094..764f51d7464 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -71,6 +71,7 @@ obj-y += ata/ obj-$(CONFIG_DM_DEMO) += demo/ obj-$(CONFIG_BIOSEMU) += bios_emulator/ obj-y += block/ +obj-y += board/ obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/ obj-$(CONFIG_CPU) += cpu/ obj-y += crypto/ diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig new file mode 100644 index 00000000000..c9a52dc20e0 --- /dev/null +++ b/drivers/board/Kconfig @@ -0,0 +1,7 @@ +menuconfig BOARD + bool "Device Information" + help + Support methods to query hardware configurations from internal + mechanisms (e.g. reading GPIO values, determining the presence of + devices on busses, etc.). This enables the usage of U-Boot with + modular board architectures. diff --git a/drivers/board/Makefile b/drivers/board/Makefile new file mode 100644 index 00000000000..12dd2030cfa --- /dev/null +++ b/drivers/board/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2017 +# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc +obj-$(CONFIG_BOARD) += board-uclass.o +obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o diff --git a/drivers/board/board-uclass.c b/drivers/board/board-uclass.c new file mode 100644 index 00000000000..a516ba49629 --- /dev/null +++ b/drivers/board/board-uclass.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include +#include +#include + +int board_get(struct udevice **devp) +{ + return uclass_first_device_err(UCLASS_BOARD, devp); +} + +int board_detect(struct udevice *dev) +{ + struct board_ops *ops = board_get_ops(dev); + + if (!ops->detect) + return -ENOSYS; + + return ops->detect(dev); +} + +int board_get_bool(struct udevice *dev, int id, bool *val) +{ + struct board_ops *ops = board_get_ops(dev); + + if (!ops->get_bool) + return -ENOSYS; + + return ops->get_bool(dev, id, val); +} + +int board_get_int(struct udevice *dev, int id, int *val) +{ + struct board_ops *ops = board_get_ops(dev); + + if (!ops->get_int) + return -ENOSYS; + + return ops->get_int(dev, id, val); +} + +int board_get_str(struct udevice *dev, int id, size_t size, char *val) +{ + struct board_ops *ops = board_get_ops(dev); + + if (!ops->get_str) + return -ENOSYS; + + return ops->get_str(dev, id, size, val); +} + +UCLASS_DRIVER(board) = { + .id = UCLASS_BOARD, + .name = "board", + .post_bind = dm_scan_fdt_dev, +}; diff --git a/include/board.h b/include/board.h new file mode 100644 index 00000000000..9dc78684f8e --- /dev/null +++ b/include/board.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +/* + * This uclass encapsulates hardware methods to gather information about a + * board or a specific device such as hard-wired GPIOs on GPIO expanders, + * read-only data in flash ICs, or similar. + * + * The interface offers functions to read the usual standard data types (bool, + * int, string) from the device, each of which is identified by a static + * numeric ID (which will usually be defined as a enum in a header file). + * + * If for example the board had a read-only serial number flash IC, we could + * call + * + * ret = board_detect(dev); + * if (ret) { + * debug("board device not found."); + * return ret; + * } + * + * ret = board_get_int(dev, ID_SERIAL_NUMBER, &serial); + * if (ret) { + * debug("Error when reading serial number from device."); + * return ret; + * } + * + * to read the serial number. + */ + +struct board_ops { + /** + * detect() - Run the hardware info detection procedure for this + * device. + * @dev: The device containing the information + * + * This operation might take a long time (e.g. read from EEPROM, + * check the presence of a device on a bus etc.), hence this is not + * done in the probe() method, but later during operation in this + * dedicated method. + * + * Return: 0 if OK, -ve on error. + */ + int (*detect)(struct udevice *dev); + + /** + * get_bool() - Read a specific bool data value that describes the + * hardware setup. + * @dev: The board instance to gather the data. + * @id: A unique identifier for the bool value to be read. + * @val: Pointer to a buffer that receives the value read. + * + * Return: 0 if OK, -ve on error. + */ + int (*get_bool)(struct udevice *dev, int id, bool *val); + + /** + * get_int() - Read a specific int data value that describes the + * hardware setup. + * @dev: The board instance to gather the data. + * @id: A unique identifier for the int value to be read. + * @val: Pointer to a buffer that receives the value read. + * + * Return: 0 if OK, -ve on error. + */ + int (*get_int)(struct udevice *dev, int id, int *val); + + /** + * get_str() - Read a specific string data value that describes the + * hardware setup. + * @dev: The board instance to gather the data. + * @id: A unique identifier for the string value to be read. + * @size: The size of the buffer to receive the string data. + * @val: Pointer to a buffer that receives the value read. + * + * Return: 0 if OK, -ve on error. + */ + int (*get_str)(struct udevice *dev, int id, size_t size, char *val); +}; + +#define board_get_ops(dev) ((struct board_ops *)(dev)->driver->ops) + +/** + * board_detect() - Run the hardware info detection procedure for this device. + * + * @dev: The device containing the information + * + * Return: 0 if OK, -ve on error. + */ +int board_detect(struct udevice *dev); + +/** + * board_get_bool() - Read a specific bool data value that describes the + * hardware setup. + * @dev: The board instance to gather the data. + * @id: A unique identifier for the bool value to be read. + * @val: Pointer to a buffer that receives the value read. + * + * Return: 0 if OK, -ve on error. + */ +int board_get_bool(struct udevice *dev, int id, bool *val); + +/** + * board_get_int() - Read a specific int data value that describes the + * hardware setup. + * @dev: The board instance to gather the data. + * @id: A unique identifier for the int value to be read. + * @val: Pointer to a buffer that receives the value read. + * + * Return: 0 if OK, -ve on error. + */ +int board_get_int(struct udevice *dev, int id, int *val); + +/** + * board_get_str() - Read a specific string data value that describes the + * hardware setup. + * @dev: The board instance to gather the data. + * @id: A unique identifier for the string value to be read. + * @size: The size of the buffer to receive the string data. + * @val: Pointer to a buffer that receives the value read. + * + * Return: 0 if OK, -ve on error. + */ +int board_get_str(struct udevice *dev, int id, size_t size, char *val); + +/** + * board_get() - Return the board device for the board in question. + * @devp: Pointer to structure to receive the board device. + * + * Since there can only be at most one board instance, the API can supply a + * function that returns the unique device. This is especially useful for use + * in board files. + * + * Return: 0 if OK, -ve on error. + */ +int board_get(struct udevice **devp); diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 7027ea076db..5e19465894b 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -30,6 +30,7 @@ enum uclass_id { UCLASS_ADC, /* Analog-to-digital converter */ UCLASS_AHCI, /* SATA disk controller */ UCLASS_BLK, /* Block device */ + UCLASS_BOARD, /* Device information from hardware */ UCLASS_CLK, /* Clock source, e.g. used by peripherals */ UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ -- cgit v1.3.1 From 6238ae4d60476dd7535b781ef3f255f676851283 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Tue, 31 Jul 2018 11:44:12 +0200 Subject: board: Add gazerbeam driver Add a board driver for the upcoming gdsys Gazerbeam board. Signed-off-by: Mario Six Reviewed-by: Simon Glass --- .../bindings/board/gdsys,board_gazerbeam.txt | 46 ++++ drivers/board/Kconfig | 10 + drivers/board/gazerbeam.c | 262 +++++++++++++++++++++ drivers/board/gazerbeam.h | 18 ++ 4 files changed, 336 insertions(+) create mode 100644 Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt create mode 100644 drivers/board/gazerbeam.c create mode 100644 drivers/board/gazerbeam.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt new file mode 100644 index 00000000000..28c1080d904 --- /dev/null +++ b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt @@ -0,0 +1,46 @@ +gdsys Gazerbeam board driver + +This driver provides capabilities to access the gdsys Gazerbeam board's device +information. Furthermore, phandles to some internal devices are provided for +the board files. + +Required properties: +- compatible: should be "gdsys,board_gazerbeam" +- csb: phandle to the board's coherent system bus (CSB) device node +- rxaui[0-3]: phandles to the rxaui control device nodes +- fpga[0-1]: phandles to the board's gdsys FPGA device nodes +- ioep[0-1]: phandles to the board's IO endpoint device nodes +- ver-gpios: GPIO list to read the hardware version from +- var-gpios: GPIO list to read the hardware variant information from +- reset-gpios: GPIO list for the board's reset GPIOs + +Example: + + +board { + compatible = "gdsys,board_gazerbeam"; + csb = <&board_soc>; + serdes = <&SERDES>; + rxaui0 = <&RXAUI0>; + rxaui1 = <&RXAUI1>; + rxaui2 = <&RXAUI2>; + rxaui3 = <&RXAUI3>; + fpga0 = <&FPGA0>; + fpga1 = <&FPGA1>; + ioep0 = <&IOEP0>; + ioep1 = <&IOEP1>; + + ver-gpios = <&PPCPCA 12 0 + &PPCPCA 13 0 + &PPCPCA 14 0 + &PPCPCA 15 0>; + + /* MC2/SC-Board */ + var-gpios-mc2 = <&GPIO_VB0 0 0 /* VAR-MC_SC */ + &GPIO_VB0 11 0>; /* VAR-CON */ + /* MC4-Board */ + var-gpios-mc4 = <&GPIO_VB1 0 0 /* VAR-MC_SC */ + &GPIO_VB1 11 0>; /* VAR-CON */ + + reset-gpios = <&gpio0 1 0 &gpio0 2 1>; +}; diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig index c9a52dc20e0..cc1cf272055 100644 --- a/drivers/board/Kconfig +++ b/drivers/board/Kconfig @@ -5,3 +5,13 @@ menuconfig BOARD mechanisms (e.g. reading GPIO values, determining the presence of devices on busses, etc.). This enables the usage of U-Boot with modular board architectures. + +if BOARD + + +config BOARD_GAZERBEAM + bool "Enable device information for the Gazerbeam board" + help + Support querying device information for the gdsys Gazerbeam board. + +endif diff --git a/drivers/board/gazerbeam.c b/drivers/board/gazerbeam.c new file mode 100644 index 00000000000..481cce8e809 --- /dev/null +++ b/drivers/board/gazerbeam.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include +#include +#include +#include +#include + +#include "gazerbeam.h" + +/* Sequence number of I2C bus that holds the GPIO expanders */ +static const int I2C_BUS_SEQ_NO = 1; + +/* I2C address of SC/MC2 expander */ +static const int MC2_EXPANDER_ADDR = 0x20; +/* I2C address of MC4 expander */ +static const int MC4_EXPANDER_ADDR = 0x22; + +/* Number of the GPIO to read the SC data from */ +static const int SC_GPIO_NO; +/* Number of the GPIO to read the CON data from */ +static const int CON_GPIO_NO = 1; + +/** + * struct board_gazerbeam_priv - Private data structure for the gazerbeam board + * driver. + * @reset_gpios: GPIOs for the board's reset GPIOs. + * @var_gpios: GPIOs for the board's hardware variant GPIOs + * @ver_gpios: GPIOs for the board's hardware version GPIOs + * @variant: Container for the board's hardware variant (CON/CPU) + * @multichannel: Container for the board's multichannel variant (MC4/MC2/SC) + * @hwversion: Container for the board's hardware version + */ +struct board_gazerbeam_priv { + struct gpio_desc reset_gpios[2]; + struct gpio_desc var_gpios[2]; + struct gpio_desc ver_gpios[4]; + int variant; + int multichannel; + int hwversion; +}; + +/** + * _read_board_variant_data() - Read variant information from the hardware. + * @dev: The board device for which to determine the multichannel and device + * type information. + * + * The data read from the board's hardware (mostly hard-wired GPIOs) is stored + * in the private data structure of the driver to be used by other driver + * methods. + * + * Return: 0 if OK, -ve on error. + */ +static int _read_board_variant_data(struct udevice *dev) +{ + struct board_gazerbeam_priv *priv = dev_get_priv(dev); + struct udevice *i2c_bus; + struct udevice *dummy; + char *listname; + int mc4, mc2, sc, con; + int gpio_num; + int res; + + res = uclass_get_device_by_seq(UCLASS_I2C, I2C_BUS_SEQ_NO, &i2c_bus); + if (res) { + debug("%s: Could not get I2C bus %d (err = %d)\n", + dev->name, I2C_BUS_SEQ_NO, res); + return res; + } + + if (!i2c_bus) { + debug("%s: Could not get I2C bus %d\n", + dev->name, I2C_BUS_SEQ_NO); + return -EIO; + } + + mc2 = !dm_i2c_probe(i2c_bus, MC2_EXPANDER_ADDR, 0, &dummy); + mc4 = !dm_i2c_probe(i2c_bus, MC4_EXPANDER_ADDR, 0, &dummy); + + if (mc2 && mc4) { + debug("%s: Board hardware configuration inconsistent.\n", + dev->name); + return -EINVAL; + } + + listname = mc2 ? "var-gpios-mc2" : "var-gpios-mc4"; + + gpio_num = gpio_request_list_by_name(dev, listname, priv->var_gpios, + ARRAY_SIZE(priv->var_gpios), + GPIOD_IS_IN); + if (gpio_num < 0) { + debug("%s: Requesting gpio list %s failed (err = %d).\n", + dev->name, listname, gpio_num); + return gpio_num; + } + + sc = dm_gpio_get_value(&priv->var_gpios[SC_GPIO_NO]); + if (sc < 0) { + debug("%s: Error while reading 'sc' GPIO (err = %d)", + dev->name, sc); + return sc; + } + + con = dm_gpio_get_value(&priv->var_gpios[CON_GPIO_NO]); + if (con < 0) { + debug("%s: Error while reading 'con' GPIO (err = %d)", + dev->name, con); + return con; + } + + if ((sc && mc2) || (sc && mc4) || (!sc && !mc2 && !mc4)) { + debug("%s: Board hardware configuration inconsistent.\n", + dev->name); + return -EINVAL; + } + + priv->variant = con ? VAR_CON : VAR_CPU; + + priv->multichannel = mc4 ? 4 : (mc2 ? 2 : (sc ? 1 : 0)); + + return 0; +} + +/** + * _read_hwversion() - Read the hardware version from the board. + * @dev: The board device for which to read the hardware version. + * + * The hardware version read from the board (from hard-wired GPIOs) is stored + * in the private data structure of the driver to be used by other driver + * methods. + * + * Return: 0 if OK, -ve on error. + */ +static int _read_hwversion(struct udevice *dev) +{ + struct board_gazerbeam_priv *priv = dev_get_priv(dev); + int res; + + res = gpio_request_list_by_name(dev, "ver-gpios", priv->ver_gpios, + ARRAY_SIZE(priv->ver_gpios), + GPIOD_IS_IN); + if (res < 0) { + debug("%s: Error getting GPIO list 'ver-gpios' (err = %d)\n", + dev->name, res); + return -ENODEV; + } + + res = dm_gpio_get_values_as_int(priv->ver_gpios, + ARRAY_SIZE(priv->ver_gpios)); + if (res < 0) { + debug("%s: Error reading HW version from expander (err = %d)\n", + dev->name, res); + return res; + } + + priv->hwversion = res; + + res = gpio_free_list(dev, priv->ver_gpios, ARRAY_SIZE(priv->ver_gpios)); + if (res < 0) { + debug("%s: Error freeing HW version GPIO list (err = %d)\n", + dev->name, res); + return res; + } + + return 0; +} + +static int board_gazerbeam_detect(struct udevice *dev) +{ + int res; + + res = _read_board_variant_data(dev); + if (res) { + debug("%s: Error reading multichannel variant (err = %d)\n", + dev->name, res); + return res; + } + + res = _read_hwversion(dev); + if (res) { + debug("%s: Error reading hardware version (err = %d)\n", + dev->name, res); + return res; + } + + return 0; +} + +static int board_gazerbeam_get_int(struct udevice *dev, int id, int *val) +{ + struct board_gazerbeam_priv *priv = dev_get_priv(dev); + + switch (id) { + case BOARD_MULTICHANNEL: + *val = priv->multichannel; + break; + case BOARD_VARIANT: + *val = priv->variant; + break; + case BOARD_HWVERSION: + *val = priv->hwversion; + break; + default: + debug("%s: Integer value %d unknown\n", dev->name, id); + return -EINVAL; + } + + return 0; +} + +static const struct udevice_id board_gazerbeam_ids[] = { + { .compatible = "gdsys,board_gazerbeam" }, + { /* sentinel */ } +}; + +static const struct board_ops board_gazerbeam_ops = { + .detect = board_gazerbeam_detect, + .get_int = board_gazerbeam_get_int, +}; + +static int board_gazerbeam_probe(struct udevice *dev) +{ + struct board_gazerbeam_priv *priv = dev_get_priv(dev); + int gpio_num, i; + + gpio_num = gpio_request_list_by_name(dev, "reset-gpios", + priv->reset_gpios, + ARRAY_SIZE(priv->reset_gpios), + GPIOD_IS_OUT); + + if (gpio_num < 0) { + debug("%s: Error getting GPIO list 'reset-gpios' (err = %d)\n", + dev->name, gpio_num); + return gpio_num; + } + + /* Set startup-finished GPIOs */ + for (i = 0; i < ARRAY_SIZE(priv->reset_gpios); i++) { + int res = dm_gpio_set_value(&priv->reset_gpios[i], 0); + + if (res) { + debug("%s: Error while setting GPIO %d (err = %d)\n", + dev->name, i, res); + return res; + } + } + + return 0; +} + +U_BOOT_DRIVER(board_gazerbeam) = { + .name = "board_gazerbeam", + .id = UCLASS_BOARD, + .of_match = board_gazerbeam_ids, + .ops = &board_gazerbeam_ops, + .priv_auto_alloc_size = sizeof(struct board_gazerbeam_priv), + .probe = board_gazerbeam_probe, +}; diff --git a/drivers/board/gazerbeam.h b/drivers/board/gazerbeam.h new file mode 100644 index 00000000000..0ca003a3739 --- /dev/null +++ b/drivers/board/gazerbeam.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +enum { + BOARD_MULTICHANNEL, + BOARD_VARIANT, + BOARD_HWVERSION, +}; + +enum { + VAR_CON, + VAR_CPU, +}; -- cgit v1.3.1 From e6fd0181082a04e743a07ebd9f6fdd0e06dc1399 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Tue, 31 Jul 2018 11:44:13 +0200 Subject: test: Add tests for board uclass Add tests for the new board uclass. Reviewed-by: Simon Glass Signed-off-by: Mario Six --- arch/sandbox/dts/test.dts | 4 ++ configs/sandbox64_defconfig | 2 + configs/sandbox_defconfig | 2 + configs/sandbox_flattree_defconfig | 2 + configs/sandbox_noblk_defconfig | 2 + configs/sandbox_spl_defconfig | 2 + drivers/board/Kconfig | 7 ++- drivers/board/Makefile | 1 + drivers/board/sandbox.c | 107 +++++++++++++++++++++++++++++++++++++ drivers/board/sandbox.h | 12 +++++ test/dm/Makefile | 1 + test/dm/board.c | 57 ++++++++++++++++++++ 12 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 drivers/board/sandbox.c create mode 100644 drivers/board/sandbox.h create mode 100644 test/dm/board.c (limited to 'drivers') diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index b8524e3b7d6..751c13b51da 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -642,6 +642,10 @@ }; }; }; + + board { + compatible = "sandbox,board_sandbox"; + }; }; #include "sandbox_pmic.dtsi" diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 27797c6990b..b80e2eba9c2 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -86,6 +86,8 @@ CONFIG_CPU=y CONFIG_DM_DEMO=y CONFIG_DM_DEMO_SIMPLE=y CONFIG_DM_DEMO_SHAPE=y +CONFIG_BOARD=y +CONFIG_BOARD_SANDBOX=y CONFIG_PM8916_GPIO=y CONFIG_SANDBOX_GPIO=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 0b209686bf9..356c48b2208 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -91,6 +91,8 @@ CONFIG_CPU=y CONFIG_DM_DEMO=y CONFIG_DM_DEMO_SIMPLE=y CONFIG_DM_DEMO_SHAPE=y +CONFIG_BOARD=y +CONFIG_BOARD_SANDBOX=y CONFIG_PM8916_GPIO=y CONFIG_SANDBOX_GPIO=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 618d6462a8c..1d3dd9f4515 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -70,6 +70,8 @@ CONFIG_CPU=y CONFIG_DM_DEMO=y CONFIG_DM_DEMO_SIMPLE=y CONFIG_DM_DEMO_SHAPE=y +CONFIG_BOARD=y +CONFIG_BOARD_SANDBOX=y CONFIG_PM8916_GPIO=y CONFIG_SANDBOX_GPIO=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig index a7691daa008..5789cf3c8a1 100644 --- a/configs/sandbox_noblk_defconfig +++ b/configs/sandbox_noblk_defconfig @@ -77,6 +77,8 @@ CONFIG_CPU=y CONFIG_DM_DEMO=y CONFIG_DM_DEMO_SIMPLE=y CONFIG_DM_DEMO_SHAPE=y +CONFIG_BOARD=y +CONFIG_BOARD_SANDBOX=y CONFIG_PM8916_GPIO=y CONFIG_SANDBOX_GPIO=y CONFIG_DM_I2C_COMPAT=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index dad5e1ce770..3ee276f085b 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -91,6 +91,8 @@ CONFIG_CPU=y CONFIG_DM_DEMO=y CONFIG_DM_DEMO_SIMPLE=y CONFIG_DM_DEMO_SHAPE=y +CONFIG_BOARD=y +CONFIG_BOARD_SANDBOX=y CONFIG_PM8916_GPIO=y CONFIG_SANDBOX_GPIO=y CONFIG_DM_I2C_COMPAT=y diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig index cc1cf272055..2a3fc9c049b 100644 --- a/drivers/board/Kconfig +++ b/drivers/board/Kconfig @@ -10,8 +10,13 @@ if BOARD config BOARD_GAZERBEAM - bool "Enable device information for the Gazerbeam board" + bool "Enable board driver for the Gazerbeam board" help Support querying device information for the gdsys Gazerbeam board. +config BOARD_SANDBOX + bool "Enable board driver for the Sandbox board" + help + Support querying device information for the Sandbox boards. + endif diff --git a/drivers/board/Makefile b/drivers/board/Makefile index 12dd2030cfa..22243380af8 100644 --- a/drivers/board/Makefile +++ b/drivers/board/Makefile @@ -4,3 +4,4 @@ # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc obj-$(CONFIG_BOARD) += board-uclass.o obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o +obj-$(CONFIG_BOARD_SANDBOX) += sandbox.o diff --git a/drivers/board/sandbox.c b/drivers/board/sandbox.c new file mode 100644 index 00000000000..50621e47a4f --- /dev/null +++ b/drivers/board/sandbox.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include +#include +#include + +#include "sandbox.h" + +struct board_sandbox_priv { + bool called_detect; + int test_i1; + int test_i2; +}; + +char vacation_spots[][64] = {"R'lyeh", "Dreamlands", "Plateau of Leng", + "Carcosa", "Yuggoth", "The Nameless City"}; + +int board_sandbox_detect(struct udevice *dev) +{ + struct board_sandbox_priv *priv = dev_get_priv(dev); + + priv->called_detect = true; + priv->test_i2 = 100; + + return 0; +} + +int board_sandbox_get_bool(struct udevice *dev, int id, bool *val) +{ + struct board_sandbox_priv *priv = dev_get_priv(dev); + + switch (id) { + case BOOL_CALLED_DETECT: + /* Checks if the dectect method has been called */ + *val = priv->called_detect; + return 0; + } + + return -ENOENT; +} + +int board_sandbox_get_int(struct udevice *dev, int id, int *val) +{ + struct board_sandbox_priv *priv = dev_get_priv(dev); + + switch (id) { + case INT_TEST1: + *val = priv->test_i1; + /* Increments with every call */ + priv->test_i1++; + return 0; + case INT_TEST2: + *val = priv->test_i2; + /* Decrements with every call */ + priv->test_i2--; + return 0; + } + + return -ENOENT; +} + +int board_sandbox_get_str(struct udevice *dev, int id, size_t size, char *val) +{ + struct board_sandbox_priv *priv = dev_get_priv(dev); + int i1 = priv->test_i1; + int i2 = priv->test_i2; + int index = (i1 * i2) % ARRAY_SIZE(vacation_spots); + + switch (id) { + case STR_VACATIONSPOT: + /* Picks a vacation spot depending on i1 and i2 */ + snprintf(val, size, vacation_spots[index]); + return 0; + } + + return -ENOENT; +} + +static const struct udevice_id board_sandbox_ids[] = { + { .compatible = "sandbox,board_sandbox" }, + { /* sentinel */ } +}; + +static const struct board_ops board_sandbox_ops = { + .detect = board_sandbox_detect, + .get_bool = board_sandbox_get_bool, + .get_int = board_sandbox_get_int, + .get_str = board_sandbox_get_str, +}; + +int board_sandbox_probe(struct udevice *dev) +{ + return 0; +} + +U_BOOT_DRIVER(board_sandbox) = { + .name = "board_sandbox", + .id = UCLASS_BOARD, + .of_match = board_sandbox_ids, + .ops = &board_sandbox_ops, + .priv_auto_alloc_size = sizeof(struct board_sandbox_priv), + .probe = board_sandbox_probe, +}; diff --git a/drivers/board/sandbox.h b/drivers/board/sandbox.h new file mode 100644 index 00000000000..2cff494f56e --- /dev/null +++ b/drivers/board/sandbox.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +enum { + BOOL_CALLED_DETECT, + INT_TEST1, + INT_TEST2, + STR_VACATIONSPOT, +}; diff --git a/test/dm/Makefile b/test/dm/Makefile index 8b1ba915d01..d7f5d6b0616 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o obj-$(CONFIG_UT_DM) += core.o ifneq ($(CONFIG_SANDBOX),) obj-$(CONFIG_BLK) += blk.o +obj-$(CONFIG_BOARD) += board.o obj-$(CONFIG_CLK) += clk.o obj-$(CONFIG_DM_ETH) += eth.o obj-$(CONFIG_DM_GPIO) += gpio.o diff --git a/test/dm/board.c b/test/dm/board.c new file mode 100644 index 00000000000..0f267a19260 --- /dev/null +++ b/test/dm/board.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include +#include +#include +#include +#include + +#include "../../drivers/board/sandbox.h" + +static int dm_test_board(struct unit_test_state *uts) +{ + struct udevice *board; + bool called_detect; + char str[64]; + int i; + + board_get(&board); + ut_assert(board); + + board_get_bool(board, BOOL_CALLED_DETECT, &called_detect); + ut_assert(!called_detect); + + board_detect(board); + + board_get_bool(board, BOOL_CALLED_DETECT, &called_detect); + ut_assert(called_detect); + + board_get_str(board, STR_VACATIONSPOT, sizeof(str), str); + ut_assertok(strcmp(str, "R'lyeh")); + + board_get_int(board, INT_TEST1, &i); + ut_asserteq(0, i); + + board_get_int(board, INT_TEST2, &i); + ut_asserteq(100, i); + + board_get_str(board, STR_VACATIONSPOT, sizeof(str), str); + ut_assertok(strcmp(str, "Carcosa")); + + board_get_int(board, INT_TEST1, &i); + ut_asserteq(1, i); + + board_get_int(board, INT_TEST2, &i); + ut_asserteq(99, i); + + board_get_str(board, STR_VACATIONSPOT, sizeof(str), str); + ut_assertok(strcmp(str, "Yuggoth")); + + return 0; +} + +DM_TEST(dm_test_board, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); -- cgit v1.3.1 From e7a52ba65be227f4fa06b851d1d92af1bef694e0 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Wed, 19 Sep 2018 03:43:43 -0700 Subject: firmware: Add FIRMWARE config prompt string There is no prompt string for FIRMWARE config. Without this, FIRMWARE config cannot be enabled through menuconfing or config file. Fix this by adding prompt summary. Signed-off-by: Rajan Vaja Reviewed-by: Simon Glass --- drivers/firmware/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index cb73b70f5b2..feaea8130fd 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -1,5 +1,5 @@ config FIRMWARE - bool + bool "Enable Firmware driver support" config ARM_PSCI_FW bool -- cgit v1.3.1 From 31b8217e83a63d1c8c70edcdcdf5aff3b1791640 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Wed, 19 Sep 2018 03:43:46 -0700 Subject: dm: test: Add "/firmware" node scan test Add a test which verifies that all subnodes under "/firmware" nodes are scanned. Signed-off-by: Rajan Vaja Reviewed-by: Simon Glass Added 'imply FIRMWARE' to sandbox Kconfig to fix test failures, fixed ordering of lines in arch/sandbox/dts/test.dts and test/dm/Makefile, updated #if condition in drivers/firmware/firmware-uclass.c: Signed-off-by: Simon Glass --- arch/Kconfig | 1 + arch/sandbox/dts/test.dts | 6 ++++++ drivers/firmware/Makefile | 1 + drivers/firmware/firmware-sandbox.c | 20 ++++++++++++++++++++ drivers/firmware/firmware-uclass.c | 2 +- test/dm/Makefile | 1 + test/dm/firmware.c | 22 ++++++++++++++++++++++ 7 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/firmware-sandbox.c create mode 100644 test/dm/firmware.c (limited to 'drivers') diff --git a/arch/Kconfig b/arch/Kconfig index 11900b02b99..9b4bcbf2fd2 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -89,6 +89,7 @@ config SANDBOX imply CMD_SF_TEST imply CRC32_VERIFY imply FAT_WRITE + imply FIRMWARE imply HASH_VERIFY imply LZMA imply SCSI diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 751c13b51da..42ceeb994e8 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -190,6 +190,12 @@ fake-host-hwaddr = [00 00 66 44 22 22]; }; + firmware { + sandbox_firmware: sandbox-firmware { + compatible = "sandbox,firmware"; + }; + }; + gpio_a: base-gpios { compatible = "sandbox,gpio"; gpio-controller; diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 1cdda14977d..6cb83582b9f 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_FIRMWARE) += firmware-uclass.o obj-$(CONFIG_ARM_PSCI_FW) += psci.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o +obj-$(CONFIG_SANDBOX) += firmware-sandbox.o diff --git a/drivers/firmware/firmware-sandbox.c b/drivers/firmware/firmware-sandbox.c new file mode 100644 index 00000000000..d970d75f781 --- /dev/null +++ b/drivers/firmware/firmware-sandbox.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * sandbox firmware driver + * + * Copyright (C) 2018 Xilinx, Inc. + */ + +#include +#include + +static const struct udevice_id generic_sandbox_firmware_ids[] = { + { .compatible = "sandbox,firmware" }, + { } +}; + +U_BOOT_DRIVER(sandbox_firmware) = { + .name = "sandbox_firmware", + .id = UCLASS_FIRMWARE, + .of_match = generic_sandbox_firmware_ids, +}; diff --git a/drivers/firmware/firmware-uclass.c b/drivers/firmware/firmware-uclass.c index 3d33b6deba3..7fcd7fb9047 100644 --- a/drivers/firmware/firmware-uclass.c +++ b/drivers/firmware/firmware-uclass.c @@ -7,7 +7,7 @@ UCLASS_DRIVER(firmware) = { .id = UCLASS_FIRMWARE, .name = "firmware", -#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .post_bind = dm_scan_fdt_dev, #endif }; diff --git a/test/dm/Makefile b/test/dm/Makefile index d7f5d6b0616..00acc7f2429 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_BLK) += blk.o obj-$(CONFIG_BOARD) += board.o obj-$(CONFIG_CLK) += clk.o obj-$(CONFIG_DM_ETH) += eth.o +obj-$(CONFIG_FIRMWARE) += firmware.o obj-$(CONFIG_DM_GPIO) += gpio.o obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_LED) += led.o diff --git a/test/dm/firmware.c b/test/dm/firmware.c new file mode 100644 index 00000000000..60fdcbb33f4 --- /dev/null +++ b/test/dm/firmware.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Xilinx, Inc. + */ + +#include +#include +#include +#include +#include +#include + +/* Base test of firmware probe */ +static int dm_test_firmware_probe(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_FIRMWARE, + "sandbox-firmware", &dev)); + return 0; +} +DM_TEST(dm_test_firmware_probe, DM_TESTF_SCAN_FDT); -- cgit v1.3.1