ec/google/chromeec: Define ACPI_NOTIFY_CROS_EC_MKBP constant
[coreboot2.git] / src / drivers / spi / spi-generic.c
blobf45ec25dcb96a1ac2dd2e85d41c8c90c07a0b23a
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <assert.h>
4 #include <commonlib/helpers.h>
5 #include <spi-generic.h>
6 #include <stddef.h>
7 #include <string.h>
9 int spi_claim_bus(const struct spi_slave *slave)
11 const struct spi_ctrlr *ctrlr = slave->ctrlr;
12 if (ctrlr && ctrlr->claim_bus)
13 return ctrlr->claim_bus(slave);
14 return 0;
17 void spi_release_bus(const struct spi_slave *slave)
19 const struct spi_ctrlr *ctrlr = slave->ctrlr;
20 if (ctrlr && ctrlr->release_bus)
21 ctrlr->release_bus(slave);
24 static int spi_xfer_single_op(const struct spi_slave *slave,
25 struct spi_op *op)
27 const struct spi_ctrlr *ctrlr = slave->ctrlr;
28 int ret;
30 if (!ctrlr || !ctrlr->xfer)
31 return -1;
33 ret = ctrlr->xfer(slave, op->dout, op->bytesout, op->din, op->bytesin);
34 if (ret)
35 op->status = SPI_OP_FAILURE;
36 else
37 op->status = SPI_OP_SUCCESS;
39 return ret;
42 static int spi_xfer_vector_default(const struct spi_slave *slave,
43 struct spi_op vectors[], size_t count)
45 size_t i;
46 int ret;
48 for (i = 0; i < count; i++) {
49 ret = spi_xfer_single_op(slave, &vectors[i]);
50 if (ret)
51 return ret;
54 return 0;
57 int spi_xfer_vector(const struct spi_slave *slave,
58 struct spi_op vectors[], size_t count)
60 const struct spi_ctrlr *ctrlr = slave->ctrlr;
62 if (ctrlr && ctrlr->xfer_vector)
63 return ctrlr->xfer_vector(slave, vectors, count);
65 return spi_xfer_vector_default(slave, vectors, count);
68 int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
69 void *din, size_t bytesin)
71 const struct spi_ctrlr *ctrlr = slave->ctrlr;
73 if (ctrlr && ctrlr->xfer)
74 return ctrlr->xfer(slave, dout, bytesout, din, bytesin);
76 return -1;
79 unsigned int spi_crop_chunk(const struct spi_slave *slave, unsigned int cmd_len,
80 unsigned int buf_len)
82 const struct spi_ctrlr *ctrlr = slave->ctrlr;
83 unsigned int ctrlr_max;
84 bool deduct_cmd_len;
85 bool deduct_opcode_len;
87 if (!ctrlr)
88 return 0;
90 deduct_cmd_len = !!(ctrlr->flags & SPI_CNTRLR_DEDUCT_CMD_LEN);
91 deduct_opcode_len = !!(ctrlr->flags & SPI_CNTRLR_DEDUCT_OPCODE_LEN);
92 ctrlr_max = ctrlr->max_xfer_size;
94 assert(ctrlr_max != 0);
96 /* Assume opcode is always one byte and deduct it from the cmd_len
97 as the hardware has a separate register for the opcode. */
98 if (deduct_opcode_len)
99 cmd_len--;
101 /* Subtract command length from usable buffer size. If
102 deduct_opcode_len is set, only subtract the number command bytes
103 after the opcode. If the adjusted cmd_len is larger than ctrlr_max
104 return 0 to indicate an error. */
105 if (deduct_cmd_len) {
106 if (ctrlr_max >= cmd_len) {
107 ctrlr_max -= cmd_len;
108 } else {
109 ctrlr_max = 0;
110 printk(BIOS_WARNING, "%s: Command longer than buffer\n", __func__);
114 return MIN(ctrlr_max, buf_len);
117 void __weak spi_init(void)
119 /* Default weak implementation - do nothing. */
122 int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
124 size_t i;
126 memset(slave, 0, sizeof(*slave));
128 for (i = 0; i < spi_ctrlr_bus_map_count; i++) {
129 if ((spi_ctrlr_bus_map[i].bus_start <= bus) &&
130 (spi_ctrlr_bus_map[i].bus_end >= bus)) {
131 slave->ctrlr = spi_ctrlr_bus_map[i].ctrlr;
132 break;
136 if (slave->ctrlr == NULL) {
137 printk(BIOS_ERR, "Can't find SPI bus %u\n", bus);
138 return -1;
141 slave->bus = bus;
142 slave->cs = cs;
144 if (slave->ctrlr->setup)
145 return slave->ctrlr->setup(slave);
147 return 0;