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.
16 #include <commonlib/helpers.h>
17 #include <spi-generic.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
);
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
,
39 const struct spi_ctrlr
*ctrlr
= slave
->ctrlr
;
42 if (!ctrlr
|| !ctrlr
->xfer
)
45 ret
= ctrlr
->xfer(slave
, op
->dout
, op
->bytesout
, op
->din
, op
->bytesin
);
47 op
->status
= SPI_OP_FAILURE
;
49 op
->status
= SPI_OP_SUCCESS
;
54 static int spi_xfer_vector_default(const struct spi_slave
*slave
,
55 struct spi_op vectors
[], size_t count
)
60 for (i
= 0; i
< count
; i
++) {
61 ret
= spi_xfer_single_op(slave
, &vectors
[i
]);
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
);
91 unsigned int spi_crop_chunk(const struct spi_slave
*slave
, unsigned int cmd_len
,
94 const struct spi_ctrlr
*ctrlr
= slave
->ctrlr
;
95 unsigned int ctrlr_max
;
97 bool deduct_opcode_len
;
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
)
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
)
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
;
138 if (slave
->ctrlr
== NULL
)
144 if (slave
->ctrlr
->setup
)
145 return slave
->ctrlr
->setup(slave
);