Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/drivers/spi/sandbox_spi.c
Line
Count
Source
1
/*
2
 * Simulate a SPI port
3
 *
4
 * Copyright (c) 2011-2013 The Chromium OS Authors.
5
 * See file CREDITS for list of people who contributed to this
6
 * project.
7
 *
8
 * Licensed under the GPL-2 or later.
9
 */
10
11
#define LOG_CATEGORY UCLASS_SPI
12
13
#include <dm.h>
14
#include <log.h>
15
#include <malloc.h>
16
#include <spi.h>
17
#include <spi_flash.h>
18
#include <os.h>
19
20
#include <linux/errno.h>
21
#include <asm/spi.h>
22
#include <asm/state.h>
23
#include <dm/acpi.h>
24
#include <dm/device-internal.h>
25
26
/**
27
 * struct sandbox_spi_priv - Sandbox SPI private data
28
 *
29
 * Helper struct to keep track of the sandbox SPI bus internal state. It is
30
 * used in unit tests to verify that dm spi functions update the bus
31
 * speed/mode properly (for instance, when jumping back and forth between spi
32
 * slaves claiming the bus, we need to make sure that the bus speed is updated
33
 * accordingly for each slave).
34
 *
35
 * @speed:  Current bus speed.
36
 * @mode: Current bus mode.
37
 */
38
struct sandbox_spi_priv {
39
  uint speed;
40
  uint mode;
41
};
42
43
__weak int sandbox_spi_get_emul(struct sandbox_state *state,
44
        struct udevice *bus, struct udevice *slave,
45
        struct udevice **emulp)
46
{
47
  return -ENOENT;
48
}
49
50
uint sandbox_spi_get_speed(struct udevice *dev)
51
0
{
52
0
  struct sandbox_spi_priv *priv = dev_get_priv(dev);
53
54
0
  return priv->speed;
55
0
}
56
57
uint sandbox_spi_get_mode(struct udevice *dev)
58
0
{
59
0
  struct sandbox_spi_priv *priv = dev_get_priv(dev);
60
61
0
  return priv->mode;
62
0
}
63
64
static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen,
65
          const void *dout, void *din, unsigned long flags)
66
0
{
67
0
  struct udevice *bus = slave->parent;
68
0
  struct sandbox_state *state = state_get_current();
69
0
  struct dm_spi_emul_ops *ops;
70
0
  struct udevice *emul;
71
0
  uint bytes = bitlen / 8, i;
72
0
  int ret;
73
0
  uint busnum, cs;
74
75
0
  if (bitlen == 0)
76
0
    return 0;
77
78
  /* we can only do 8 bit transfers */
79
0
  if (bitlen % 8) {
80
0
    printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n",
81
0
           bitlen);
82
0
    return -EINVAL;
83
0
  }
84
85
0
  busnum = dev_seq(bus);
86
0
  cs = spi_chip_select(slave);
87
0
  if (busnum >= CONFIG_SANDBOX_SPI_MAX_BUS ||
88
0
      cs >= CONFIG_SANDBOX_SPI_MAX_CS) {
89
0
    printf("%s: busnum=%u, cs=%u: out of range\n", __func__,
90
0
           busnum, cs);
91
0
    return -ENOENT;
92
0
  }
93
0
  ret = sandbox_spi_get_emul(state, bus, slave, &emul);
94
0
  if (ret) {
95
0
    printf("%s: busnum=%u, cs=%u: no emulation available (err=%d)\n",
96
0
           __func__, busnum, cs, ret);
97
0
    return -ENOENT;
98
0
  }
99
0
  ret = device_probe(emul);
100
0
  if (ret)
101
0
    return ret;
102
103
0
  ops = spi_emul_get_ops(emul);
104
0
  ret = ops->xfer(emul, bitlen, dout, din, flags);
105
106
0
  log_content("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
107
0
        ret, ret ? "bad" : "good");
108
0
  if (din) {
109
0
    for (i = 0; i < bytes; ++i)
110
0
      log_content(" %u:%02x", i, ((u8 *)din)[i]);
111
0
  }
112
0
  log_content("\n");
113
114
0
  return ret;
115
0
}
116
117
static int sandbox_spi_set_speed(struct udevice *bus, uint speed)
118
0
{
119
0
  struct sandbox_spi_priv *priv = dev_get_priv(bus);
120
121
0
  priv->speed = speed;
122
123
0
  return 0;
124
0
}
125
126
static int sandbox_spi_set_mode(struct udevice *bus, uint mode)
127
0
{
128
0
  struct sandbox_spi_priv *priv = dev_get_priv(bus);
129
130
0
  priv->mode = mode;
131
132
0
  return 0;
133
0
}
134
135
static int sandbox_cs_info(struct udevice *bus, uint cs,
136
         struct spi_cs_info *info)
137
0
{
138
  /* Always allow activity on CS 0, CS 1 */
139
0
  if (cs >= 2)
140
0
    return -EINVAL;
141
142
0
  return 0;
143
0
}
144
145
static int sandbox_spi_get_mmap(struct udevice *dev, ulong *map_basep,
146
        uint *map_sizep, uint *offsetp)
147
0
{
148
0
  *map_basep = 0x1000;
149
0
  *map_sizep = 0x2000;
150
0
  *offsetp = 0x100;
151
152
0
  return 0;
153
0
}
154
155
static const struct dm_spi_ops sandbox_spi_ops = {
156
  .xfer   = sandbox_spi_xfer,
157
  .set_speed  = sandbox_spi_set_speed,
158
  .set_mode = sandbox_spi_set_mode,
159
  .cs_info  = sandbox_cs_info,
160
  .get_mmap = sandbox_spi_get_mmap,
161
};
162
163
static const struct udevice_id sandbox_spi_ids[] = {
164
  { .compatible = "sandbox,spi" },
165
  { }
166
};
167
168
U_BOOT_DRIVER(sandbox_spi) = {
169
  .name = "sandbox_spi",
170
  .id = UCLASS_SPI,
171
  .of_match = sandbox_spi_ids,
172
  .ops  = &sandbox_spi_ops,
173
  .priv_auto = sizeof(struct sandbox_spi_priv),
174
};