Commit 8fee226da36f799e69041b2ab381064693199c7f

Authored by Tom Rini

Merge branch 'agust@denx.de' of git://git.denx.de/u-boot-staging

Showing 11 changed files Side-by-side Diff

Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt
  1 +gdsys IO endpoint of IHS FPGA devices
  2 +
  3 +The IO endpoint of IHS FPGA devices is a packet-based transmission interface
  4 +that allows interconnected gdsys devices to send and receive data over the
  5 +FPGA's main ethernet connection.
  6 +
  7 +Required properties:
  8 +- compatible: must be "gdsys,io-endpoint"
  9 +- reg: describes the address and length of the endpoint's register map (within
  10 + the FPGA's register space)
  11 +
  12 +Example:
  13 +
  14 +fpga0_ep0 {
  15 + compatible = "gdsys,io-endpoint";
  16 + reg = <0x020 0x10
  17 + 0x320 0x10
  18 + 0x340 0x10
  19 + 0x360 0x10>;
  20 +};
arch/sandbox/dts/test.dts
... ... @@ -286,6 +286,10 @@
286 286 mbox-names = "other", "test";
287 287 };
288 288  
  289 + misc-test {
  290 + compatible = "sandbox,misc_sandbox";
  291 + };
  292 +
289 293 mmc2 {
290 294 compatible = "sandbox,mmc";
291 295 };
drivers/misc/Kconfig
... ... @@ -277,5 +277,11 @@
277 277 depends on MISC
278 278 help
279 279 Support gdsys FPGA's RXAUI control.
  280 +
  281 +config GDSYS_IOEP
  282 + bool "Enable gdsys IOEP driver"
  283 + depends on MISC
  284 + help
  285 + Support gdsys FPGA's IO endpoint driver.
280 286 endmenu
drivers/misc/Makefile
... ... @@ -39,7 +39,7 @@
39 39 obj-$(CONFIG_SANDBOX) += spltest_sandbox.o
40 40 endif
41 41 endif
42   -obj-$(CONFIG_SANDBOX) += syscon_sandbox.o
  42 +obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o
43 43 obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
44 44 obj-$(CONFIG_TEGRA186_BPMP) += tegra186_bpmp.o
45 45 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
... ... @@ -53,5 +53,6 @@
53 53 obj-$(CONFIG_STM32_RCC) += stm32_rcc.o
54 54 obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o
55 55 obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
  56 +obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
56 57 obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
drivers/misc/gdsys_ioep.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * (C) Copyright 2017
  4 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
  5 + *
  6 + * based on the cmd_ioloop driver/command, which is
  7 + *
  8 + * (C) Copyright 2014
  9 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
  10 + *
  11 + * SPDX-License-Identifier: GPL-2.0+
  12 + */
  13 +
  14 +#include <common.h>
  15 +#include <dm.h>
  16 +#include <misc.h>
  17 +#include <regmap.h>
  18 +
  19 +#include "gdsys_ioep.h"
  20 +
  21 +/**
  22 + * struct gdsys_ioep_priv - Private data structure for IOEP devices
  23 + * @map: Register map to be used for the device
  24 + * @state: Flag to keep the current status of the RX control (enabled/disabled)
  25 + */
  26 +struct gdsys_ioep_priv {
  27 + struct regmap *map;
  28 + bool state;
  29 +};
  30 +
  31 +/**
  32 + * enum last_spec - Convenience enum for read data sanity check
  33 + * @READ_DATA_IS_LAST: The data to be read should be the final data of the
  34 + * current packet
  35 + * @READ_DATA_IS_NOT_LAST: The data to be read should not be the final data of
  36 + * the current packet
  37 + */
  38 +enum last_spec {
  39 + READ_DATA_IS_LAST,
  40 + READ_DATA_IS_NOT_LAST,
  41 +};
  42 +
  43 +static int gdsys_ioep_set_receive(struct udevice *dev, bool val)
  44 +{
  45 + struct gdsys_ioep_priv *priv = dev_get_priv(dev);
  46 + u16 state;
  47 +
  48 + priv->state = !priv->state;
  49 +
  50 + if (val)
  51 + state = CTRL_PROC_RECEIVE_ENABLE;
  52 + else
  53 + state = ~CTRL_PROC_RECEIVE_ENABLE;
  54 +
  55 + gdsys_ioep_set(priv->map, tx_control, state);
  56 +
  57 + if (val) {
  58 + /* Set device address to dummy 1 */
  59 + gdsys_ioep_set(priv->map, device_address, 1);
  60 + }
  61 +
  62 + return !priv->state;
  63 +}
  64 +
  65 +static int gdsys_ioep_send(struct udevice *dev, int offset,
  66 + const void *buf, int size)
  67 +{
  68 + struct gdsys_ioep_priv *priv = dev_get_priv(dev);
  69 + int k;
  70 + u16 *p = (u16 *)buf;
  71 +
  72 + for (k = 0; k < size; ++k)
  73 + gdsys_ioep_set(priv->map, transmit_data, *(p++));
  74 +
  75 + gdsys_ioep_set(priv->map, tx_control, CTRL_PROC_RECEIVE_ENABLE |
  76 + CTRL_FLUSH_TRANSMIT_BUFFER);
  77 +
  78 + return 0;
  79 +}
  80 +
  81 +/**
  82 + * receive_byte_buffer() - Read data from a IOEP device
  83 + * @dev: The IOEP device to read data from
  84 + * @len: The length of the data to read
  85 + * @buffer: The buffer to read the data into
  86 + * @last_spec: Flag to indicate if the data to be read in this call should be
  87 + * the final data of the current packet (i.e. it should be empty
  88 + * after this read)
  89 + *
  90 + * Return: 0 if OK, -ve on error
  91 + */
  92 +static int receive_byte_buffer(struct udevice *dev, uint len,
  93 + u16 *buffer, enum last_spec last_spec)
  94 +{
  95 + struct gdsys_ioep_priv *priv = dev_get_priv(dev);
  96 + int k;
  97 + int ret = -EIO;
  98 +
  99 + for (k = 0; k < len; ++k) {
  100 + u16 rx_tx_status;
  101 +
  102 + gdsys_ioep_get(priv->map, receive_data, buffer++);
  103 +
  104 + gdsys_ioep_get(priv->map, rx_tx_status, &rx_tx_status);
  105 + /*
  106 + * Sanity check: If the data read should have been the last,
  107 + * but wasn't, something is wrong
  108 + */
  109 + if (k == (len - 1) && (last_spec == READ_DATA_IS_NOT_LAST ||
  110 + rx_tx_status & STATE_RX_DATA_LAST))
  111 + ret = 0;
  112 + }
  113 +
  114 + if (ret)
  115 + debug("%s: Error while receiving bufer (err = %d)\n",
  116 + dev->name, ret);
  117 +
  118 + return ret;
  119 +}
  120 +
  121 +static int gdsys_ioep_receive(struct udevice *dev, int offset, void *buf,
  122 + int size)
  123 +{
  124 + int ret;
  125 + struct io_generic_packet header;
  126 + u16 *p = (u16 *)buf;
  127 + const int header_words = sizeof(struct io_generic_packet) / sizeof(u16);
  128 + uint len;
  129 +
  130 + /* Read the packet header */
  131 + ret = receive_byte_buffer(dev, header_words, p, READ_DATA_IS_NOT_LAST);
  132 + if (ret) {
  133 + debug("%s: Failed to read header data (err = %d)\n",
  134 + dev->name, ret);
  135 + return ret;
  136 + }
  137 +
  138 + memcpy(&header, p, header_words * sizeof(u16));
  139 + p += header_words;
  140 +
  141 + /* Get payload data length */
  142 + len = (header.packet_length + 1) / sizeof(u16);
  143 +
  144 + /* Read the packet payload */
  145 + ret = receive_byte_buffer(dev, len, p, READ_DATA_IS_LAST);
  146 + if (ret) {
  147 + debug("%s: Failed to read payload data (err = %d)\n",
  148 + dev->name, ret);
  149 + return ret;
  150 + }
  151 +
  152 + return 0;
  153 +}
  154 +
  155 +static int gdsys_ioep_get_and_reset_status(struct udevice *dev, int msgid,
  156 + void *tx_msg, int tx_size,
  157 + void *rx_msg, int rx_size)
  158 +{
  159 + struct gdsys_ioep_priv *priv = dev_get_priv(dev);
  160 + const u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
  161 + STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
  162 + STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
  163 + u16 *status = rx_msg;
  164 +
  165 + gdsys_ioep_get(priv->map, rx_tx_status, status);
  166 +
  167 + gdsys_ioep_set(priv->map, rx_tx_status, *status);
  168 +
  169 + return (*status & mask) ? 1 : 0;
  170 +}
  171 +
  172 +static const struct misc_ops gdsys_ioep_ops = {
  173 + .set_enabled = gdsys_ioep_set_receive,
  174 + .write = gdsys_ioep_send,
  175 + .read = gdsys_ioep_receive,
  176 + .call = gdsys_ioep_get_and_reset_status,
  177 +};
  178 +
  179 +static int gdsys_ioep_probe(struct udevice *dev)
  180 +{
  181 + struct gdsys_ioep_priv *priv = dev_get_priv(dev);
  182 + int ret;
  183 +
  184 + ret = regmap_init_mem(dev_ofnode(dev), &priv->map);
  185 + if (ret) {
  186 + debug("%s: Could not initialize regmap (err = %d)",
  187 + dev->name, ret);
  188 + return ret;
  189 + }
  190 +
  191 + priv->state = false;
  192 +
  193 + return 0;
  194 +}
  195 +
  196 +static const struct udevice_id gdsys_ioep_ids[] = {
  197 + { .compatible = "gdsys,io-endpoint" },
  198 + { }
  199 +};
  200 +
  201 +U_BOOT_DRIVER(gdsys_ioep) = {
  202 + .name = "gdsys_ioep",
  203 + .id = UCLASS_MISC,
  204 + .ops = &gdsys_ioep_ops,
  205 + .flags = DM_UC_FLAG_SEQ_ALIAS,
  206 + .of_match = gdsys_ioep_ids,
  207 + .probe = gdsys_ioep_probe,
  208 + .priv_auto_alloc_size = sizeof(struct gdsys_ioep_priv),
  209 +};
drivers/misc/gdsys_ioep.h
  1 +/* SPDX-License-Identifier: GPL-2.0+ */
  2 +/*
  3 + * (C) Copyright 2018
  4 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
  5 + */
  6 +
  7 +#ifndef __GDSYS_IOEP_H_
  8 +#define __GDSYS_IOEP_H_
  9 +
  10 +/**
  11 + * struct io_generic_packet - header structure for GDSYS IOEP packets
  12 + * @target_address: Target protocol address of the packet.
  13 + * @source_address: Source protocol address of the packet.
  14 + * @packet_type: Packet type.
  15 + * @bc: Block counter (filled in by FPGA).
  16 + * @packet_length: Length of the packet's payload bytes.
  17 + */
  18 +struct io_generic_packet {
  19 + u16 target_address;
  20 + u16 source_address;
  21 + u8 packet_type;
  22 + u8 bc;
  23 + u16 packet_length;
  24 +} __attribute__((__packed__));
  25 +
  26 +/**
  27 + * struct gdsys_ioep_regs - Registers of a IOEP device
  28 + * @transmit_data: Register that receives data to be sent
  29 + * @tx_control: TX control register
  30 + * @receive_data: Register filled with the received data
  31 + * @rx_tx_status: RX/TX status register
  32 + * @device_address: Register for setting/reading the device's address
  33 + * @target_address: Register for setting/reading the remote endpoint's address
  34 + * @int_enable: Interrupt/Interrupt enable register
  35 + */
  36 +struct gdsys_ioep_regs {
  37 + u16 transmit_data;
  38 + u16 tx_control;
  39 + u16 receive_data;
  40 + u16 rx_tx_status;
  41 + u16 device_address;
  42 + u16 target_address;
  43 + u16 int_enable;
  44 +};
  45 +
  46 +/**
  47 + * gdsys_ioep_set() - Convenience macro to write registers of a IOEP device
  48 + * @map: Register map to write the value in
  49 + * @member: Name of the member in the gdsys_ioep_regs structure to write
  50 + * @val: Value to write to the register
  51 + */
  52 +#define gdsys_ioep_set(map, member, val) \
  53 + regmap_set(map, struct gdsys_ioep_regs, member, val)
  54 +
  55 +/**
  56 + * gdsys_ioep_get() - Convenience macro to read registers of a IOEP device
  57 + * @map: Register map to read the value from
  58 + * @member: Name of the member in the gdsys_ioep_regs structure to read
  59 + * @valp: Pointer to buffer to read the register value into
  60 + */
  61 +#define gdsys_ioep_get(map, member, valp) \
  62 + regmap_get(map, struct gdsys_ioep_regs, member, valp)
  63 +
  64 +/**
  65 + * enum rx_tx_status_values - Enum to describe the fields of the rx_tx_status
  66 + * register
  67 + * @STATE_TX_PACKET_BUILDING: The device is currently building a packet
  68 + * (and accepting data for it)
  69 + * @STATE_TX_TRANSMITTING: A packet is currenly being transmitted
  70 + * @STATE_TX_BUFFER_FULL: The TX buffer is full
  71 + * @STATE_TX_ERR: A TX error occurred
  72 + * @STATE_RECEIVE_TIMEOUT: A receive timeout occurred
  73 + * @STATE_PROC_RX_STORE_TIMEOUT: A RX store timeout for a processor packet
  74 + * occurred
  75 + * @STATE_PROC_RX_RECEIVE_TIMEOUT: A RX receive timeout for a processor packet
  76 + * occurred
  77 + * @STATE_RX_DIST_ERR: A error occurred in the distribution block
  78 + * @STATE_RX_LENGTH_ERR: A length invalid error occurred
  79 + * @STATE_RX_FRAME_CTR_ERR: A frame count error occurred (two
  80 + * non-increasing frame count numbers
  81 + * encountered)
  82 + * @STATE_RX_FCS_ERR: A CRC error occurred
  83 + * @STATE_RX_PACKET_DROPPED: A RX packet has been dropped
  84 + * @STATE_RX_DATA_LAST: The data to be read is the final data of the
  85 + * current packet
  86 + * @STATE_RX_DATA_FIRST: The data to be read is the first data of the
  87 + * current packet
  88 + * @STATE_RX_DATA_AVAILABLE: RX data is available to be read
  89 + */
  90 +enum rx_tx_status_values {
  91 + STATE_TX_PACKET_BUILDING = BIT(0),
  92 + STATE_TX_TRANSMITTING = BIT(1),
  93 + STATE_TX_BUFFER_FULL = BIT(2),
  94 + STATE_TX_ERR = BIT(3),
  95 + STATE_RECEIVE_TIMEOUT = BIT(4),
  96 + STATE_PROC_RX_STORE_TIMEOUT = BIT(5),
  97 + STATE_PROC_RX_RECEIVE_TIMEOUT = BIT(6),
  98 + STATE_RX_DIST_ERR = BIT(7),
  99 + STATE_RX_LENGTH_ERR = BIT(8),
  100 + STATE_RX_FRAME_CTR_ERR = BIT(9),
  101 + STATE_RX_FCS_ERR = BIT(10),
  102 + STATE_RX_PACKET_DROPPED = BIT(11),
  103 + STATE_RX_DATA_LAST = BIT(12),
  104 + STATE_RX_DATA_FIRST = BIT(13),
  105 + STATE_RX_DATA_AVAILABLE = BIT(15),
  106 +};
  107 +
  108 +/**
  109 + * enum tx_control_values - Enum to describe the fields of the tx_control
  110 + * register
  111 + * @CTRL_PROC_RECEIVE_ENABLE: Enable packet reception for the processor
  112 + * @CTRL_FLUSH_TRANSMIT_BUFFER: Flush the transmit buffer (and send packet data)
  113 + */
  114 +enum tx_control_values {
  115 + CTRL_PROC_RECEIVE_ENABLE = BIT(12),
  116 + CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15),
  117 +};
  118 +
  119 +/**
  120 + * enum int_enable_values - Enum to describe the fields of the int_enable
  121 + * register
  122 + * @IRQ_CPU_TRANSMITBUFFER_FREE_STATUS: The transmit buffer is free (packet
  123 + * data can be transmitted to the
  124 + * device)
  125 + * @IRQ_CPU_PACKET_TRANSMITTED_EVENT: A packet has been transmitted
  126 + * @IRQ_NEW_CPU_PACKET_RECEIVED_EVENT: A new packet has been received
  127 + * @IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS: RX packet data are available to be
  128 + * read
  129 + */
  130 +enum int_enable_values {
  131 + IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = BIT(5),
  132 + IRQ_CPU_PACKET_TRANSMITTED_EVENT = BIT(6),
  133 + IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = BIT(7),
  134 + IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = BIT(8),
  135 +};
  136 +
  137 +#endif /* __GDSYS_IOEP_H_ */
drivers/misc/misc-uclass.c
... ... @@ -55,6 +55,16 @@
55 55 return ops->call(dev, msgid, tx_msg, tx_size, rx_msg, rx_size);
56 56 }
57 57  
  58 +int misc_set_enabled(struct udevice *dev, bool val)
  59 +{
  60 + const struct misc_ops *ops = device_get_ops(dev);
  61 +
  62 + if (!ops->set_enabled)
  63 + return -ENOSYS;
  64 +
  65 + return ops->set_enabled(dev, val);
  66 +}
  67 +
58 68 UCLASS_DRIVER(misc) = {
59 69 .id = UCLASS_MISC,
60 70 .name = "misc",
drivers/misc/misc_sandbox.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * (C) Copyright 2018
  4 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <dm.h>
  9 +#include <misc.h>
  10 +
  11 +struct misc_sandbox_priv {
  12 + u8 mem[128];
  13 + ulong last_ioctl;
  14 + bool enabled;
  15 +};
  16 +
  17 +int misc_sandbox_read(struct udevice *dev, int offset, void *buf, int size)
  18 +{
  19 + struct misc_sandbox_priv *priv = dev_get_priv(dev);
  20 +
  21 + memcpy(buf, priv->mem + offset, size);
  22 +
  23 + return 0;
  24 +}
  25 +
  26 +int misc_sandbox_write(struct udevice *dev, int offset, const void *buf,
  27 + int size)
  28 +{
  29 + struct misc_sandbox_priv *priv = dev_get_priv(dev);
  30 +
  31 + memcpy(priv->mem + offset, buf, size);
  32 +
  33 + return 0;
  34 +}
  35 +
  36 +int misc_sandbox_ioctl(struct udevice *dev, unsigned long request, void *buf)
  37 +{
  38 + struct misc_sandbox_priv *priv = dev_get_priv(dev);
  39 +
  40 + priv->last_ioctl = request;
  41 +
  42 + return 0;
  43 +}
  44 +
  45 +int misc_sandbox_call(struct udevice *dev, int msgid, void *tx_msg,
  46 + int tx_size, void *rx_msg, int rx_size)
  47 +{
  48 + struct misc_sandbox_priv *priv = dev_get_priv(dev);
  49 +
  50 + if (msgid == 0) {
  51 + int num = *(int *)tx_msg;
  52 +
  53 + switch (num) {
  54 + case 0:
  55 + strncpy(rx_msg, "Zero", rx_size);
  56 + break;
  57 + case 1:
  58 + strncpy(rx_msg, "One", rx_size);
  59 + break;
  60 + case 2:
  61 + strncpy(rx_msg, "Two", rx_size);
  62 + break;
  63 + default:
  64 + return -EINVAL;
  65 + }
  66 + }
  67 +
  68 + if (msgid == 1) {
  69 + int num = *(int *)tx_msg;
  70 +
  71 + switch (num) {
  72 + case 0:
  73 + strncpy(rx_msg, "Forty", rx_size);
  74 + break;
  75 + case 1:
  76 + strncpy(rx_msg, "Forty-one", rx_size);
  77 + break;
  78 + case 2:
  79 + strncpy(rx_msg, "Forty-two", rx_size);
  80 + break;
  81 + default:
  82 + return -EINVAL;
  83 + }
  84 + }
  85 +
  86 + if (msgid == 2)
  87 + memcpy(rx_msg, &priv->last_ioctl, sizeof(priv->last_ioctl));
  88 +
  89 + if (msgid == 3)
  90 + memcpy(rx_msg, &priv->enabled, sizeof(priv->enabled));
  91 +
  92 + return 0;
  93 +}
  94 +
  95 +int misc_sandbox_set_enabled(struct udevice *dev, bool val)
  96 +{
  97 + struct misc_sandbox_priv *priv = dev_get_priv(dev);
  98 +
  99 + priv->enabled = !priv->enabled;
  100 +
  101 + return 0;
  102 +}
  103 +
  104 +static const struct misc_ops misc_sandbox_ops = {
  105 + .read = misc_sandbox_read,
  106 + .write = misc_sandbox_write,
  107 + .ioctl = misc_sandbox_ioctl,
  108 + .call = misc_sandbox_call,
  109 + .set_enabled = misc_sandbox_set_enabled,
  110 +};
  111 +
  112 +int misc_sandbox_probe(struct udevice *dev)
  113 +{
  114 + struct misc_sandbox_priv *priv = dev_get_priv(dev);
  115 +
  116 + priv->enabled = true;
  117 +
  118 + return 0;
  119 +}
  120 +
  121 +static const struct udevice_id misc_sandbox_ids[] = {
  122 + { .compatible = "sandbox,misc_sandbox" },
  123 + { }
  124 +};
  125 +
  126 +U_BOOT_DRIVER(misc_sandbox) = {
  127 + .name = "misc_sandbox",
  128 + .id = UCLASS_MISC,
  129 + .ops = &misc_sandbox_ops,
  130 + .of_match = misc_sandbox_ids,
  131 + .probe = misc_sandbox_probe,
  132 + .priv_auto_alloc_size = sizeof(struct misc_sandbox_priv),
  133 +};
... ... @@ -6,38 +6,47 @@
6 6 #ifndef _MISC_H_
7 7 #define _MISC_H_
8 8  
9   -/*
10   - * Read the device to buffer, optional.
11   - *
  9 +/**
  10 + * misc_read() - Read the device to buffer, optional.
12 11 * @dev: the device
13 12 * @offset: offset to read the device
14 13 * @buf: pointer to data buffer
15 14 * @size: data size in bytes to read the device
16   - * @return: 0 if OK, -ve on error
  15 + *
  16 + * Return: 0 if OK, -ve on error
17 17 */
18 18 int misc_read(struct udevice *dev, int offset, void *buf, int size);
19   -/*
20   - * Write buffer to the device, optional.
21   - *
  19 +
  20 +/**
  21 + * misc_write() - Write buffer to the device, optional.
22 22 * @dev: the device
23 23 * @offset: offset to write the device
24 24 * @buf: pointer to data buffer
25 25 * @size: data size in bytes to write the device
26   - * @return: 0 if OK, -ve on error
  26 + *
  27 + * Return: 0 if OK, -ve on error
27 28 */
28 29 int misc_write(struct udevice *dev, int offset, void *buf, int size);
29   -/*
30   - * Assert command to the device, optional.
31   - *
  30 +
  31 +/**
  32 + * misc_ioctl() - Assert command to the device, optional.
32 33 * @dev: the device
33 34 * @request: command to be sent to the device
34 35 * @buf: pointer to buffer related to the request
35   - * @return: 0 if OK, -ve on error
  36 + *
  37 + * Return: 0 if OK, -ve on error
36 38 */
37 39 int misc_ioctl(struct udevice *dev, unsigned long request, void *buf);
38 40  
39   -/*
40   - * Send a message to the device and wait for a response.
  41 +/**
  42 + * misc_call() - Send a message to the device and wait for a response.
  43 + * @dev: the device.
  44 + * @msgid: the message ID/number to send.
  45 + * @tx_msg: the request/transmit message payload.
  46 + * @tx_size: the size of the buffer pointed at by tx_msg.
  47 + * @rx_msg: the buffer to receive the response message payload. May be NULL if
  48 + * the caller only cares about the error code.
  49 + * @rx_size: the size of the buffer pointed at by rx_msg.
41 50 *
42 51 * The caller provides the message type/ID and payload to be sent.
43 52 * The callee constructs any message header required, transmits it to the
44 53  
... ... @@ -45,18 +54,28 @@
45 54 * strips any message header from the response, and returns the error code
46 55 * (or a parsed version of it) and the response message payload.
47 56 *
48   - * @dev: the device.
49   - * @msgid: the message ID/number to send.
50   - * tx_msg: the request/transmit message payload.
51   - * tx_size: the size of the buffer pointed at by tx_msg.
52   - * rx_msg: the buffer to receive the response message payload. May be NULL if
53   - * the caller only cares about the error code.
54   - * rx_size: the size of the buffer pointed at by rx_msg.
55   - * @return the response message size if OK, -ve on error
  57 + * Return: the response message size if OK, -ve on error
56 58 */
57 59 int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size,
58 60 void *rx_msg, int rx_size);
59 61  
  62 +/**
  63 + * misc_set_enabled() - Enable or disable a device.
  64 + * @dev: the device to enable or disable.
  65 + * @val: the flag that tells the driver to either enable or disable the device.
  66 + *
  67 + * The semantics of "disable" and "enable" should be understood here as
  68 + * activating or deactivating the device's primary function, hence a "disabled"
  69 + * device should be dormant, but still answer to commands and queries.
  70 + *
  71 + * A probed device may start in a disabled or enabled state, depending on the
  72 + * driver and hardware.
  73 + *
  74 + * Return: -ve on error, 0 if the previous state was "disabled", 1 if the
  75 + * previous state was "enabled"
  76 + */
  77 +int misc_set_enabled(struct udevice *dev, bool val);
  78 +
60 79 /*
61 80 * struct misc_ops - Driver model Misc operations
62 81 *
63 82  
64 83  
65 84  
66 85  
67 86  
68 87  
69 88  
70 89  
71 90  
72 91  
73 92  
74 93  
... ... @@ -64,50 +83,62 @@
64 83 * use driver model.
65 84 */
66 85 struct misc_ops {
67   - /*
  86 + /**
68 87 * Read the device to buffer, optional.
69   - *
70 88 * @dev: the device
71 89 * @offset: offset to read the device
72 90 * @buf: pointer to data buffer
73 91 * @size: data size in bytes to read the device
74   - * @return: 0 if OK, -ve on error
  92 + *
  93 + * Return: 0 if OK, -ve on error
75 94 */
76 95 int (*read)(struct udevice *dev, int offset, void *buf, int size);
77   - /*
  96 +
  97 + /**
78 98 * Write buffer to the device, optional.
79   - *
80 99 * @dev: the device
81 100 * @offset: offset to write the device
82 101 * @buf: pointer to data buffer
83 102 * @size: data size in bytes to write the device
84   - * @return: 0 if OK, -ve on error
  103 + *
  104 + * Return: 0 if OK, -ve on error
85 105 */
86 106 int (*write)(struct udevice *dev, int offset, const void *buf,
87 107 int size);
88   - /*
  108 + /**
89 109 * Assert command to the device, optional.
90   - *
91 110 * @dev: the device
92 111 * @request: command to be sent to the device
93 112 * @buf: pointer to buffer related to the request
94   - * @return: 0 if OK, -ve on error
  113 + *
  114 + * Return: 0 if OK, -ve on error
95 115 */
96 116 int (*ioctl)(struct udevice *dev, unsigned long request, void *buf);
97   - /*
  117 +
  118 + /**
98 119 * Send a message to the device and wait for a response.
99   - *
100 120 * @dev: the device
101 121 * @msgid: the message ID/number to send
102   - * tx_msg: the request/transmit message payload
103   - * tx_size: the size of the buffer pointed at by tx_msg
104   - * rx_msg: the buffer to receive the response message payload. May be
105   - * NULL if the caller only cares about the error code.
106   - * rx_size: the size of the buffer pointed at by rx_msg
107   - * @return the response message size if OK, -ve on error
  122 + * @tx_msg: the request/transmit message payload
  123 + * @tx_size: the size of the buffer pointed at by tx_msg
  124 + * @rx_msg: the buffer to receive the response message payload. May be
  125 + * NULL if the caller only cares about the error code.
  126 + * @rx_size: the size of the buffer pointed at by rx_msg
  127 + *
  128 + * Return: the response message size if OK, -ve on error
108 129 */
109 130 int (*call)(struct udevice *dev, int msgid, void *tx_msg, int tx_size,
110 131 void *rx_msg, int rx_size);
  132 + /**
  133 + * Enable or disable a device, optional.
  134 + * @dev: the device to enable.
  135 + * @val: the flag that tells the driver to either enable or disable the
  136 + * device.
  137 + *
  138 + * Return: -ve on error, 0 if the previous state was "disabled", 1 if
  139 + * the previous state was "enabled"
  140 + */
  141 + int (*set_enabled)(struct udevice *dev, bool val);
111 142 };
112 143  
113 144 #endif /* _MISC_H_ */
... ... @@ -45,5 +45,6 @@
45 45 obj-$(CONFIG_SPMI) += spmi.o
46 46 obj-$(CONFIG_WDT) += wdt.o
47 47 obj-$(CONFIG_AXI) += axi.o
  48 +obj-$(CONFIG_MISC) += misc.o
48 49 endif
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * (C) Copyright 2018
  4 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <dm.h>
  9 +#include <dm/test.h>
  10 +#include <misc.h>
  11 +#include <test/ut.h>
  12 +
  13 +static int dm_test_misc(struct unit_test_state *uts)
  14 +{
  15 + struct udevice *dev;
  16 + u8 buf[16];
  17 + int id;
  18 + ulong last_ioctl;
  19 + bool enabled;
  20 +
  21 + ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "misc-test", &dev));
  22 +
  23 + /* Read / write tests */
  24 + ut_assertok(misc_write(dev, 0, "TEST", 4));
  25 + ut_assertok(misc_write(dev, 4, "WRITE", 5));
  26 + ut_assertok(misc_read(dev, 0, buf, 9));
  27 +
  28 + ut_assertok(memcmp(buf, "TESTWRITE", 9));
  29 +
  30 + /* Call tests */
  31 +
  32 + id = 0;
  33 + ut_assertok(misc_call(dev, 0, &id, 4, buf, 16));
  34 + ut_assertok(memcmp(buf, "Zero", 4));
  35 +
  36 + id = 2;
  37 + ut_assertok(misc_call(dev, 0, &id, 4, buf, 16));
  38 + ut_assertok(memcmp(buf, "Two", 3));
  39 +
  40 + ut_assertok(misc_call(dev, 1, &id, 4, buf, 16));
  41 + ut_assertok(memcmp(buf, "Forty-two", 9));
  42 +
  43 + id = 1;
  44 + ut_assertok(misc_call(dev, 1, &id, 4, buf, 16));
  45 + ut_assertok(memcmp(buf, "Forty-one", 9));
  46 +
  47 + /* IOCTL tests */
  48 +
  49 + ut_assertok(misc_ioctl(dev, 6, NULL));
  50 + /* Read back last issued ioctl */
  51 + ut_assertok(misc_call(dev, 2, NULL, 0, &last_ioctl,
  52 + sizeof(last_ioctl)));
  53 + ut_asserteq(6, last_ioctl)
  54 +
  55 + ut_assertok(misc_ioctl(dev, 23, NULL));
  56 + /* Read back last issued ioctl */
  57 + ut_assertok(misc_call(dev, 2, NULL, 0, &last_ioctl,
  58 + sizeof(last_ioctl)));
  59 + ut_asserteq(23, last_ioctl)
  60 +
  61 + /* Enable / disable tests */
  62 +
  63 + /* Read back enable/disable status */
  64 + ut_assertok(misc_call(dev, 3, NULL, 0, &enabled,
  65 + sizeof(enabled)));
  66 + ut_asserteq(true, enabled);
  67 +
  68 + ut_assertok(misc_set_enabled(dev, false));
  69 + /* Read back enable/disable status */
  70 + ut_assertok(misc_call(dev, 3, NULL, 0, &enabled,
  71 + sizeof(enabled)));
  72 + ut_asserteq(false, enabled);
  73 +
  74 + ut_assertok(misc_set_enabled(dev, true));
  75 + /* Read back enable/disable status */
  76 + ut_assertok(misc_call(dev, 3, NULL, 0, &enabled,
  77 + sizeof(enabled)));
  78 + ut_asserteq(true, enabled);
  79 +
  80 + return 0;
  81 +}
  82 +
  83 +DM_TEST(dm_test_misc, DM_TESTF_SCAN_FDT);