{drivers,southbridge}: Replace min() with MIN()
[coreboot.git] / src / drivers / spi / spi-generic.c
blobbc4fb086cd734ceed9292490ed8586fd7b5e6ea8
1 /*
2 * This file is part of the coreboot project.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <assert.h>
16 #include <commonlib/helpers.h>
17 #include <spi-generic.h>
18 #include <stddef.h>
19 #include <string.h>
21 int spi_claim_bus(const struct spi_slave *slave)
23 const struct spi_ctrlr *ctrlr = slave->ctrlr;
24 if (ctrlr && ctrlr->claim_bus)
25 return ctrlr->claim_bus(slave);
26 return 0;
29 void spi_release_bus(const struct spi_slave *slave)
31 const struct spi_ctrlr *ctrlr = slave->ctrlr;
32 if (ctrlr && ctrlr->release_bus)
33 ctrlr->release_bus(slave);
36 static int spi_xfer_single_op(const struct spi_slave *slave,
37 struct spi_op *op)
39 const struct spi_ctrlr *ctrlr = slave->ctrlr;
40 int ret;
42 if (!ctrlr || !ctrlr->xfer)
43 return -1;
45 ret = ctrlr->xfer(slave, op->dout, op->bytesout, op->din, op->bytesin);
46 if (ret)
47 op->status = SPI_OP_FAILURE;
48 else
49 op->status = SPI_OP_SUCCESS;
51 return ret;
54 static int spi_xfer_vector_default(const struct spi_slave *slave,
55 struct spi_op vectors[], size_t count)
57 size_t i;
58 int ret;
60 for (i = 0; i < count; i++) {
61 ret = spi_xfer_single_op(slave, &vectors[i]);
62 if (ret)
63 return ret;
66 return 0;
69 int spi_xfer_vector(const struct spi_slave *slave,
70 struct spi_op vectors[], size_t count)
72 const struct spi_ctrlr *ctrlr = slave->ctrlr;
74 if (ctrlr && ctrlr->xfer_vector)
75 return ctrlr->xfer_vector(slave, vectors, count);
77 return spi_xfer_vector_default(slave, vectors, count);
80 int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
81 void *din, size_t bytesin)
83 const struct spi_ctrlr *ctrlr = slave->ctrlr;
85 if (ctrlr && ctrlr->xfer)
86 return ctrlr->xfer(slave, dout, bytesout, din, bytesin);
88 return -1;
91 unsigned int spi_crop_chunk(const struct spi_slave *slave, unsigned int cmd_len,
92 unsigned int buf_len)
94 const struct spi_ctrlr *ctrlr = slave->ctrlr;
95 unsigned int ctrlr_max;
96 bool deduct_cmd_len;
97 bool deduct_opcode_len;
99 if (!ctrlr)
100 return 0;
102 deduct_cmd_len = !!(ctrlr->flags & SPI_CNTRLR_DEDUCT_CMD_LEN);
103 deduct_opcode_len = !!(ctrlr->flags & SPI_CNTRLR_DEDUCT_OPCODE_LEN);
104 ctrlr_max = ctrlr->max_xfer_size;
106 assert (ctrlr_max != 0);
108 /* Assume opcode is always one byte and deduct it from the cmd_len
109 as the hardware has a separate register for the opcode. */
110 if (deduct_opcode_len)
111 cmd_len--;
113 if (deduct_cmd_len && (ctrlr_max > cmd_len))
114 ctrlr_max -= cmd_len;
116 return MIN(ctrlr_max, buf_len);
119 void __weak spi_init(void)
121 /* Default weak implementation - do nothing. */
124 int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
126 size_t i;
128 memset(slave, 0, sizeof(*slave));
130 for (i = 0; i < spi_ctrlr_bus_map_count; i++) {
131 if ((spi_ctrlr_bus_map[i].bus_start <= bus) &&
132 (spi_ctrlr_bus_map[i].bus_end >= bus)) {
133 slave->ctrlr = spi_ctrlr_bus_map[i].ctrlr;
134 break;
138 if (slave->ctrlr == NULL)
139 return -1;
141 slave->bus = bus;
142 slave->cs = cs;
144 if (slave->ctrlr->setup)
145 return slave->ctrlr->setup(slave);
147 return 0;