1*253c8305SRuslan Bukin /*-
2*253c8305SRuslan Bukin * Copyright (c) 2012-2025 Patrick Kelsey. All rights reserved.
3*253c8305SRuslan Bukin * Copyright (c) 2025 Ruslan Bukin <br@bsdpad.com>
4*253c8305SRuslan Bukin *
5*253c8305SRuslan Bukin * Redistribution and use in source and binary forms, with or without
6*253c8305SRuslan Bukin * modification, are permitted provided that the following conditions
7*253c8305SRuslan Bukin * are met:
8*253c8305SRuslan Bukin * 1. Redistributions of source code must retain the above copyright
9*253c8305SRuslan Bukin * notice, this list of conditions and the following disclaimer.
10*253c8305SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright
11*253c8305SRuslan Bukin * notice, this list of conditions and the following disclaimer in the
12*253c8305SRuslan Bukin * documentation and/or other materials provided with the distribution.
13*253c8305SRuslan Bukin *
14*253c8305SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*253c8305SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*253c8305SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*253c8305SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18*253c8305SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*253c8305SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*253c8305SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*253c8305SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*253c8305SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*253c8305SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*253c8305SRuslan Bukin * SUCH DAMAGE.
25*253c8305SRuslan Bukin *
26*253c8305SRuslan Bukin * Portions of this software may have been developed with reference to
27*253c8305SRuslan Bukin * the SD Simplified Specification. The following disclaimer may apply:
28*253c8305SRuslan Bukin *
29*253c8305SRuslan Bukin * The following conditions apply to the release of the simplified
30*253c8305SRuslan Bukin * specification ("Simplified Specification") by the SD Card Association and
31*253c8305SRuslan Bukin * the SD Group. The Simplified Specification is a subset of the complete SD
32*253c8305SRuslan Bukin * Specification which is owned by the SD Card Association and the SD
33*253c8305SRuslan Bukin * Group. This Simplified Specification is provided on a non-confidential
34*253c8305SRuslan Bukin * basis subject to the disclaimers below. Any implementation of the
35*253c8305SRuslan Bukin * Simplified Specification may require a license from the SD Card
36*253c8305SRuslan Bukin * Association, SD Group, SD-3C LLC or other third parties.
37*253c8305SRuslan Bukin *
38*253c8305SRuslan Bukin * Disclaimers:
39*253c8305SRuslan Bukin *
40*253c8305SRuslan Bukin * The information contained in the Simplified Specification is presented only
41*253c8305SRuslan Bukin * as a standard specification for SD Cards and SD Host/Ancillary products and
42*253c8305SRuslan Bukin * is provided "AS-IS" without any representations or warranties of any
43*253c8305SRuslan Bukin * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
44*253c8305SRuslan Bukin * Card Association for any damages, any infringements of patents or other
45*253c8305SRuslan Bukin * right of the SD Group, SD-3C LLC, the SD Card Association or any third
46*253c8305SRuslan Bukin * parties, which may result from its use. No license is granted by
47*253c8305SRuslan Bukin * implication, estoppel or otherwise under any patent or other rights of the
48*253c8305SRuslan Bukin * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
49*253c8305SRuslan Bukin * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
50*253c8305SRuslan Bukin * or the SD Card Association to disclose or distribute any technical
51*253c8305SRuslan Bukin * information, know-how or other confidential information to any third party.
52*253c8305SRuslan Bukin *
53*253c8305SRuslan Bukin *
54*253c8305SRuslan Bukin * CRC routines adapted from public domain code written by Lammert Bies.
55*253c8305SRuslan Bukin *
56*253c8305SRuslan Bukin *
57*253c8305SRuslan Bukin * This is an implementation of mmcbr that communicates with SD/MMC cards in
58*253c8305SRuslan Bukin * SPI mode via spibus_if. In order to minimize changes to the existing
59*253c8305SRuslan Bukin * MMC/SD stack (and allow for maximal reuse of the same), the behavior of
60*253c8305SRuslan Bukin * the SD-bus command set is emulated as much as possible, where required.
61*253c8305SRuslan Bukin *
62*253c8305SRuslan Bukin * The SPI bus ownership behavior is to acquire the SPI bus for the entire
63*253c8305SRuslan Bukin * duration that the MMC host is acquired.
64*253c8305SRuslan Bukin *
65*253c8305SRuslan Bukin * CRC checking is enabled by default, but can be disabled at runtime
66*253c8305SRuslan Bukin * per-card via sysctl (e.g. sysctl dev.mmcspi.0.use_crc=0).
67*253c8305SRuslan Bukin *
68*253c8305SRuslan Bukin * Considered, but not implemented:
69*253c8305SRuslan Bukin * - Card presence detection
70*253c8305SRuslan Bukin * - Card power control
71*253c8305SRuslan Bukin * - Detection of lock switch state on cards that have them
72*253c8305SRuslan Bukin * - Yielding the CPU during long card busy cycles
73*253c8305SRuslan Bukin *
74*253c8305SRuslan Bukin * Originally developed and tested using a MicroTik RouterBOARD RB450G and
75*253c8305SRuslan Bukin * 31 microSD cards available circa 2012.
76*253c8305SRuslan Bukin */
77*253c8305SRuslan Bukin
78*253c8305SRuslan Bukin #include <sys/param.h>
79*253c8305SRuslan Bukin #include <sys/systm.h>
80*253c8305SRuslan Bukin #include <sys/bus.h>
81*253c8305SRuslan Bukin #include <sys/conf.h>
82*253c8305SRuslan Bukin #include <sys/kernel.h>
83*253c8305SRuslan Bukin #include <sys/lock.h>
84*253c8305SRuslan Bukin #include <sys/module.h>
85*253c8305SRuslan Bukin #include <sys/mutex.h>
86*253c8305SRuslan Bukin #include <sys/resource.h>
87*253c8305SRuslan Bukin #include <sys/sysctl.h>
88*253c8305SRuslan Bukin
89*253c8305SRuslan Bukin #include <dev/mmc/bridge.h>
90*253c8305SRuslan Bukin #include <dev/mmc/mmcreg.h>
91*253c8305SRuslan Bukin #include <dev/mmc/mmcbrvar.h>
92*253c8305SRuslan Bukin #include <dev/spibus/spi.h>
93*253c8305SRuslan Bukin
94*253c8305SRuslan Bukin #include <dev/ofw/ofw_bus.h>
95*253c8305SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h>
96*253c8305SRuslan Bukin
97*253c8305SRuslan Bukin #include "mmcbr_if.h"
98*253c8305SRuslan Bukin #include "spibus_if.h"
99*253c8305SRuslan Bukin
100*253c8305SRuslan Bukin #define MMCSPI_RETRIES 3
101*253c8305SRuslan Bukin #define MMCSPI_TIMEOUT_SEC 3
102*253c8305SRuslan Bukin
103*253c8305SRuslan Bukin #define MMCSPI_MAX_RSP_LEN 5 /* max length of an Rn response */
104*253c8305SRuslan Bukin #define MMCSPI_OCR_LEN 4
105*253c8305SRuslan Bukin
106*253c8305SRuslan Bukin #define MMCSPI_DATA_BLOCK_LEN 512
107*253c8305SRuslan Bukin #define MMCSPI_DATA_CRC_LEN 2
108*253c8305SRuslan Bukin
109*253c8305SRuslan Bukin #define MMCSPI_POLL_LEN 8 /* amount to read when searching */
110*253c8305SRuslan Bukin
111*253c8305SRuslan Bukin #define MMCSPI_R1_MASK 0x80 /* mask used to search for R1 tokens */
112*253c8305SRuslan Bukin #define MMCSPI_R1_VALUE 0x00 /* value used to search for R1 tokens */
113*253c8305SRuslan Bukin #define MMCSPI_DR_MASK 0x11 /* mask used to search for data resp tokens */
114*253c8305SRuslan Bukin #define MMCSPI_DR_VALUE 0x01 /* value used to search for data resp tokens */
115*253c8305SRuslan Bukin
116*253c8305SRuslan Bukin #define MMCSPI_DR_ERR_MASK 0x0e
117*253c8305SRuslan Bukin #define MMCSPI_DR_ERR_NONE 0x04
118*253c8305SRuslan Bukin #define MMCSPI_DR_ERR_CRC 0x0a
119*253c8305SRuslan Bukin #define MMCSPI_DR_ERR_WRITE 0x0c
120*253c8305SRuslan Bukin
121*253c8305SRuslan Bukin #define MMCSPI_TOKEN_SB 0xfe /* start block token for read single,
122*253c8305SRuslan Bukin read multi, and write single */
123*253c8305SRuslan Bukin #define MMCSPI_TOKEN_SB_WM 0xfc /* start block token for write multi */
124*253c8305SRuslan Bukin #define MMCSPI_TOKEN_ST 0xfd /* stop transmission token */
125*253c8305SRuslan Bukin #define MMCSPI_IS_DE_TOKEN(x) (0 == ((x) & 0xf0)) /* detector for data
126*253c8305SRuslan Bukin error token */
127*253c8305SRuslan Bukin
128*253c8305SRuslan Bukin #define MMCSPI_R1_IDLE 0x01
129*253c8305SRuslan Bukin #define MMCSPI_R1_ERASE_RST 0x02
130*253c8305SRuslan Bukin #define MMCSPI_R1_ILL_CMD 0x04
131*253c8305SRuslan Bukin #define MMCSPI_R1_CRC_ERR 0x08
132*253c8305SRuslan Bukin #define MMCSPI_R1_ERASE_ERR 0x10
133*253c8305SRuslan Bukin #define MMCSPI_R1_ADDR_ERR 0x20
134*253c8305SRuslan Bukin #define MMCSPI_R1_PARAM_ERR 0x40
135*253c8305SRuslan Bukin
136*253c8305SRuslan Bukin #define MMCSPI_R1_ERR_MASK (MMCSPI_R1_PARAM_ERR | MMCSPI_R1_ADDR_ERR | \
137*253c8305SRuslan Bukin MMCSPI_R1_ERASE_ERR | MMCSPI_R1_CRC_ERR | \
138*253c8305SRuslan Bukin MMCSPI_R1_ILL_CMD)
139*253c8305SRuslan Bukin
140*253c8305SRuslan Bukin #define MMCSPI_R2_LOCKED 0x01
141*253c8305SRuslan Bukin #define MMCSPI_R2_WP_ER_LCK 0x02
142*253c8305SRuslan Bukin #define MMCSPI_R2_ERR 0x04
143*253c8305SRuslan Bukin #define MMCSPI_R2_CC_ERR 0x08
144*253c8305SRuslan Bukin #define MMCSPI_R2_ECC_FAIL 0x10
145*253c8305SRuslan Bukin #define MMCSPI_R2_WP_VIOLATE 0x20
146*253c8305SRuslan Bukin #define MMCSPI_R2_ERASE_PARAM 0x40
147*253c8305SRuslan Bukin #define MMCSPI_R2_OOR_CSD_OW 0x80
148*253c8305SRuslan Bukin
149*253c8305SRuslan Bukin /* commands that only apply to the SPI interface */
150*253c8305SRuslan Bukin #define MMCSPI_READ_OCR 58
151*253c8305SRuslan Bukin #define MMCSPI_CRC_ON_OFF 59
152*253c8305SRuslan Bukin
153*253c8305SRuslan Bukin static struct ofw_compat_data compat_data[] = {
154*253c8305SRuslan Bukin { "mmc-spi-slot", 1 },
155*253c8305SRuslan Bukin { NULL, 0 }
156*253c8305SRuslan Bukin };
157*253c8305SRuslan Bukin
158*253c8305SRuslan Bukin struct mmcspi_command {
159*253c8305SRuslan Bukin struct mmc_command *mmc_cmd; /* command passed from mmc layer */
160*253c8305SRuslan Bukin uint32_t opcode; /* possibly translated opcode */
161*253c8305SRuslan Bukin uint32_t arg; /* possibly translated arg */
162*253c8305SRuslan Bukin uint32_t flags; /* possibly translated flags */
163*253c8305SRuslan Bukin uint32_t retries; /* possibly translated retry count */
164*253c8305SRuslan Bukin struct mmc_data *data; /* possibly redirected data segment */
165*253c8305SRuslan Bukin unsigned int error_mask; /* R1 errors check mask */
166*253c8305SRuslan Bukin unsigned char use_crc; /* do crc checking for this command */
167*253c8305SRuslan Bukin unsigned char rsp_type; /* SPI response type of this command */
168*253c8305SRuslan Bukin #define MMCSPI_RSP_R1 0
169*253c8305SRuslan Bukin #define MMCSPI_RSP_R1B 1
170*253c8305SRuslan Bukin #define MMCSPI_RSP_R2 2
171*253c8305SRuslan Bukin #define MMCSPI_RSP_R3 3
172*253c8305SRuslan Bukin #define MMCSPI_RSP_R7 4
173*253c8305SRuslan Bukin unsigned char rsp_len; /* response len of this command */
174*253c8305SRuslan Bukin unsigned char mmc_rsp_type; /* MMC reponse type to translate to */
175*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_NONE 0
176*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_R1 1
177*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_R1B 2
178*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_R2 3
179*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_R3 4
180*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_R6 5
181*253c8305SRuslan Bukin #define MMCSPI_TO_MMC_RSP_R7 6
182*253c8305SRuslan Bukin struct mmc_data ldata; /* local read data */
183*253c8305SRuslan Bukin };
184*253c8305SRuslan Bukin
185*253c8305SRuslan Bukin struct mmcspi_slot {
186*253c8305SRuslan Bukin struct mmcspi_softc *sc; /* back pointer to parent bridge */
187*253c8305SRuslan Bukin device_t dev; /* mmc device for slot */
188*253c8305SRuslan Bukin boolean_t bus_busy; /* host has been acquired */
189*253c8305SRuslan Bukin struct mmc_host host; /* host parameters */
190*253c8305SRuslan Bukin struct mtx mtx; /* slot mutex */
191*253c8305SRuslan Bukin uint8_t last_ocr[MMCSPI_OCR_LEN]; /* ocr retrieved after CMD8 */
192*253c8305SRuslan Bukin uint32_t last_opcode; /* last opcode requested by mmc layer */
193*253c8305SRuslan Bukin uint32_t last_flags; /* last flags requested by mmc layer */
194*253c8305SRuslan Bukin unsigned int crc_enabled; /* crc checking is enabled */
195*253c8305SRuslan Bukin unsigned int crc_init_done; /* whether the initial crc setting has
196*253c8305SRuslan Bukin been sent to the card */
197*253c8305SRuslan Bukin #define MMCSPI_MAX_LDATA_LEN 16
198*253c8305SRuslan Bukin uint8_t ldata_buf[MMCSPI_MAX_LDATA_LEN];
199*253c8305SRuslan Bukin };
200*253c8305SRuslan Bukin
201*253c8305SRuslan Bukin struct mmcspi_softc {
202*253c8305SRuslan Bukin device_t dev; /* this mmc bridge device */
203*253c8305SRuslan Bukin device_t busdev;
204*253c8305SRuslan Bukin struct mmcspi_slot slot;
205*253c8305SRuslan Bukin unsigned int use_crc; /* command CRC checking */
206*253c8305SRuslan Bukin };
207*253c8305SRuslan Bukin
208*253c8305SRuslan Bukin #if defined(MMCSPI_ENABLE_DEBUG_FUNCS)
209*253c8305SRuslan Bukin static void mmcspi_dump_data(device_t dev, const char *label, uint8_t *data,
210*253c8305SRuslan Bukin unsigned int len);
211*253c8305SRuslan Bukin static void mmcspi_dump_spi_bus(device_t dev, unsigned int len);
212*253c8305SRuslan Bukin #endif
213*253c8305SRuslan Bukin
214*253c8305SRuslan Bukin #define MMCSPI_LOCK_SLOT(_slot) mtx_lock(&(_slot)->mtx)
215*253c8305SRuslan Bukin #define MMCSPI_UNLOCK_SLOT(_slot) mtx_unlock(&(_slot)->mtx)
216*253c8305SRuslan Bukin #define MMCSPI_SLOT_LOCK_INIT(_slot) mtx_init(&(_slot)->mtx, \
217*253c8305SRuslan Bukin "SD slot mtx", "mmcspi", MTX_DEF)
218*253c8305SRuslan Bukin #define MMCSPI_SLOT_LOCK_DESTROY(_slot) mtx_destroy(&(_slot)->mtx);
219*253c8305SRuslan Bukin #define MMCSPI_ASSERT_SLOT_LOCKED(_slot) mtx_assert(&(_slot)->mtx, \
220*253c8305SRuslan Bukin MA_OWNED);
221*253c8305SRuslan Bukin #define MMCSPI_ASSERT_SLOT_UNLOCKED(_slot) mtx_assert(&(_slot)->mtx, \
222*253c8305SRuslan Bukin MA_NOTOWNED);
223*253c8305SRuslan Bukin
224*253c8305SRuslan Bukin #define TRACE_ZONE_ENABLED(zone) (trace_zone_mask & TRACE_ZONE_##zone)
225*253c8305SRuslan Bukin
226*253c8305SRuslan Bukin #define TRACE_ENTER(dev) \
227*253c8305SRuslan Bukin if (TRACE_ZONE_ENABLED(ENTER)) { \
228*253c8305SRuslan Bukin device_printf(dev, "%s: enter\n", __func__); \
229*253c8305SRuslan Bukin }
230*253c8305SRuslan Bukin
231*253c8305SRuslan Bukin #define TRACE_EXIT(dev) \
232*253c8305SRuslan Bukin if (TRACE_ZONE_ENABLED(EXIT)) { \
233*253c8305SRuslan Bukin device_printf(dev, "%s: exit\n", __func__); \
234*253c8305SRuslan Bukin }
235*253c8305SRuslan Bukin
236*253c8305SRuslan Bukin #define TRACE(dev, zone, ...) \
237*253c8305SRuslan Bukin if (TRACE_ZONE_ENABLED(zone)) { \
238*253c8305SRuslan Bukin device_printf(dev, __VA_ARGS__); \
239*253c8305SRuslan Bukin }
240*253c8305SRuslan Bukin
241*253c8305SRuslan Bukin #define TRACE_ZONE_ENTER (1ul << 0) /* function entrance */
242*253c8305SRuslan Bukin #define TRACE_ZONE_EXIT (1ul << 1) /* function exit */
243*253c8305SRuslan Bukin #define TRACE_ZONE_ACTION (1ul << 2) /* for narrating major actions taken */
244*253c8305SRuslan Bukin #define TRACE_ZONE_RESULT (1ul << 3) /* for narrating results of actions */
245*253c8305SRuslan Bukin #define TRACE_ZONE_ERROR (1ul << 4) /* for reporting errors */
246*253c8305SRuslan Bukin #define TRACE_ZONE_DATA (1ul << 5) /* for dumping bus data */
247*253c8305SRuslan Bukin #define TRACE_ZONE_DETAILS (1ul << 6) /* for narrating minor actions/results */
248*253c8305SRuslan Bukin
249*253c8305SRuslan Bukin #define TRACE_ZONE_NONE 0
250*253c8305SRuslan Bukin #define TRACE_ZONE_ALL 0xffffffff
251*253c8305SRuslan Bukin
252*253c8305SRuslan Bukin #define CRC7_INITIAL 0x00
253*253c8305SRuslan Bukin #define CRC16_INITIAL 0x0000
254*253c8305SRuslan Bukin
255*253c8305SRuslan Bukin SYSCTL_NODE(_hw, OID_AUTO, mmcspi, CTLFLAG_RD, 0, "mmcspi driver");
256*253c8305SRuslan Bukin
257*253c8305SRuslan Bukin static unsigned int trace_zone_mask = TRACE_ZONE_ERROR;
258*253c8305SRuslan Bukin
259*253c8305SRuslan Bukin static uint8_t crc7tab[256];
260*253c8305SRuslan Bukin static uint16_t crc16tab[256];
261*253c8305SRuslan Bukin static uint8_t onesbuf[MMCSPI_DATA_BLOCK_LEN]; /* for driving the tx line
262*253c8305SRuslan Bukin when receiving */
263*253c8305SRuslan Bukin static uint8_t junkbuf[MMCSPI_DATA_BLOCK_LEN]; /* for receiving data when
264*253c8305SRuslan Bukin transmitting */
265*253c8305SRuslan Bukin
266*253c8305SRuslan Bukin static uint8_t
update_crc7(uint8_t crc,uint8_t * buf,unsigned int len)267*253c8305SRuslan Bukin update_crc7(uint8_t crc, uint8_t *buf, unsigned int len)
268*253c8305SRuslan Bukin {
269*253c8305SRuslan Bukin uint8_t tmp;
270*253c8305SRuslan Bukin int i;
271*253c8305SRuslan Bukin
272*253c8305SRuslan Bukin for (i = 0; i < len; i++) {
273*253c8305SRuslan Bukin tmp = (crc << 1) ^ buf[i];
274*253c8305SRuslan Bukin crc = crc7tab[tmp];
275*253c8305SRuslan Bukin }
276*253c8305SRuslan Bukin
277*253c8305SRuslan Bukin return (crc);
278*253c8305SRuslan Bukin }
279*253c8305SRuslan Bukin
280*253c8305SRuslan Bukin static uint16_t
update_crc16(uint16_t crc,uint8_t * buf,unsigned int len)281*253c8305SRuslan Bukin update_crc16(uint16_t crc, uint8_t *buf, unsigned int len)
282*253c8305SRuslan Bukin {
283*253c8305SRuslan Bukin uint16_t tmp, c16;
284*253c8305SRuslan Bukin int i;
285*253c8305SRuslan Bukin
286*253c8305SRuslan Bukin for (i = 0; i < len; i++) {
287*253c8305SRuslan Bukin c16 = 0x00ff & (uint16_t)buf[i];
288*253c8305SRuslan Bukin
289*253c8305SRuslan Bukin tmp = (crc >> 8) ^ c16;
290*253c8305SRuslan Bukin crc = (crc << 8) ^ crc16tab[tmp];
291*253c8305SRuslan Bukin }
292*253c8305SRuslan Bukin
293*253c8305SRuslan Bukin return (crc);
294*253c8305SRuslan Bukin }
295*253c8305SRuslan Bukin
296*253c8305SRuslan Bukin static void
init_crc7tab(void)297*253c8305SRuslan Bukin init_crc7tab(void)
298*253c8305SRuslan Bukin {
299*253c8305SRuslan Bukin #define P_CRC7 0x89
300*253c8305SRuslan Bukin
301*253c8305SRuslan Bukin int i, j;
302*253c8305SRuslan Bukin uint8_t crc, c;
303*253c8305SRuslan Bukin
304*253c8305SRuslan Bukin for (i = 0; i < 256; i++) {
305*253c8305SRuslan Bukin
306*253c8305SRuslan Bukin c = (uint8_t)i;
307*253c8305SRuslan Bukin crc = (c & 0x80) ? c ^ P_CRC7 : c;
308*253c8305SRuslan Bukin
309*253c8305SRuslan Bukin for (j=1; j<8; j++) {
310*253c8305SRuslan Bukin crc = crc << 1;
311*253c8305SRuslan Bukin
312*253c8305SRuslan Bukin if (crc & 0x80)
313*253c8305SRuslan Bukin crc = crc ^ P_CRC7;
314*253c8305SRuslan Bukin }
315*253c8305SRuslan Bukin
316*253c8305SRuslan Bukin crc7tab[i] = crc;
317*253c8305SRuslan Bukin }
318*253c8305SRuslan Bukin }
319*253c8305SRuslan Bukin
320*253c8305SRuslan Bukin static void
init_crc16tab(void)321*253c8305SRuslan Bukin init_crc16tab(void)
322*253c8305SRuslan Bukin {
323*253c8305SRuslan Bukin #define P_CCITT 0x1021
324*253c8305SRuslan Bukin
325*253c8305SRuslan Bukin int i, j;
326*253c8305SRuslan Bukin uint16_t crc, c;
327*253c8305SRuslan Bukin
328*253c8305SRuslan Bukin for (i = 0; i < 256; i++) {
329*253c8305SRuslan Bukin
330*253c8305SRuslan Bukin crc = 0;
331*253c8305SRuslan Bukin c = ((uint16_t) i) << 8;
332*253c8305SRuslan Bukin
333*253c8305SRuslan Bukin for (j=0; j<8; j++) {
334*253c8305SRuslan Bukin
335*253c8305SRuslan Bukin if ((crc ^ c) & 0x8000) crc = ( crc << 1 ) ^ P_CCITT;
336*253c8305SRuslan Bukin else crc = crc << 1;
337*253c8305SRuslan Bukin
338*253c8305SRuslan Bukin c = c << 1;
339*253c8305SRuslan Bukin }
340*253c8305SRuslan Bukin
341*253c8305SRuslan Bukin crc16tab[i] = crc;
342*253c8305SRuslan Bukin }
343*253c8305SRuslan Bukin }
344*253c8305SRuslan Bukin
345*253c8305SRuslan Bukin static void
mmcspi_slot_init(device_t brdev,struct mmcspi_slot * slot)346*253c8305SRuslan Bukin mmcspi_slot_init(device_t brdev, struct mmcspi_slot *slot)
347*253c8305SRuslan Bukin {
348*253c8305SRuslan Bukin struct mmcspi_softc *sc;
349*253c8305SRuslan Bukin
350*253c8305SRuslan Bukin TRACE_ENTER(brdev);
351*253c8305SRuslan Bukin
352*253c8305SRuslan Bukin sc = device_get_softc(brdev);
353*253c8305SRuslan Bukin
354*253c8305SRuslan Bukin slot->sc = sc;
355*253c8305SRuslan Bukin slot->dev = NULL; /* will get real value when card is added */
356*253c8305SRuslan Bukin slot->bus_busy = false;
357*253c8305SRuslan Bukin slot->host.f_min = 100000; /* this should be as low as we need to go
358*253c8305SRuslan Bukin for any card */
359*253c8305SRuslan Bukin slot->host.caps = 0;
360*253c8305SRuslan Bukin /* SPI mode requires 3.3V operation */
361*253c8305SRuslan Bukin slot->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
362*253c8305SRuslan Bukin
363*253c8305SRuslan Bukin MMCSPI_SLOT_LOCK_INIT(slot);
364*253c8305SRuslan Bukin
365*253c8305SRuslan Bukin TRACE_EXIT(brdev);
366*253c8305SRuslan Bukin }
367*253c8305SRuslan Bukin
368*253c8305SRuslan Bukin static void
mmcspi_slot_fini(device_t brdev,struct mmcspi_slot * slot)369*253c8305SRuslan Bukin mmcspi_slot_fini(device_t brdev, struct mmcspi_slot *slot)
370*253c8305SRuslan Bukin {
371*253c8305SRuslan Bukin TRACE_ENTER(brdev);
372*253c8305SRuslan Bukin
373*253c8305SRuslan Bukin MMCSPI_SLOT_LOCK_DESTROY(slot);
374*253c8305SRuslan Bukin
375*253c8305SRuslan Bukin TRACE_EXIT(brdev);
376*253c8305SRuslan Bukin }
377*253c8305SRuslan Bukin
378*253c8305SRuslan Bukin static void
mmcspi_card_add(struct mmcspi_slot * slot)379*253c8305SRuslan Bukin mmcspi_card_add(struct mmcspi_slot *slot)
380*253c8305SRuslan Bukin {
381*253c8305SRuslan Bukin device_t brdev;
382*253c8305SRuslan Bukin device_t child;
383*253c8305SRuslan Bukin
384*253c8305SRuslan Bukin brdev = slot->sc->dev;
385*253c8305SRuslan Bukin
386*253c8305SRuslan Bukin TRACE_ENTER(brdev);
387*253c8305SRuslan Bukin
388*253c8305SRuslan Bukin child = device_add_child(brdev, "mmc", DEVICE_UNIT_ANY);
389*253c8305SRuslan Bukin
390*253c8305SRuslan Bukin MMCSPI_LOCK_SLOT(slot);
391*253c8305SRuslan Bukin slot->dev = child;
392*253c8305SRuslan Bukin device_set_ivars(slot->dev, slot);
393*253c8305SRuslan Bukin MMCSPI_UNLOCK_SLOT(slot);
394*253c8305SRuslan Bukin
395*253c8305SRuslan Bukin device_probe_and_attach(slot->dev);
396*253c8305SRuslan Bukin
397*253c8305SRuslan Bukin TRACE_EXIT(brdev);
398*253c8305SRuslan Bukin }
399*253c8305SRuslan Bukin
400*253c8305SRuslan Bukin static void
mmcspi_card_delete(struct mmcspi_slot * slot)401*253c8305SRuslan Bukin mmcspi_card_delete(struct mmcspi_slot *slot)
402*253c8305SRuslan Bukin {
403*253c8305SRuslan Bukin device_t brdev;
404*253c8305SRuslan Bukin device_t dev;
405*253c8305SRuslan Bukin
406*253c8305SRuslan Bukin brdev = slot->sc->dev;
407*253c8305SRuslan Bukin
408*253c8305SRuslan Bukin TRACE_ENTER(brdev);
409*253c8305SRuslan Bukin
410*253c8305SRuslan Bukin MMCSPI_LOCK_SLOT(slot);
411*253c8305SRuslan Bukin dev = slot->dev;
412*253c8305SRuslan Bukin slot->dev = NULL;
413*253c8305SRuslan Bukin MMCSPI_UNLOCK_SLOT(slot);
414*253c8305SRuslan Bukin device_delete_child(brdev, dev);
415*253c8305SRuslan Bukin
416*253c8305SRuslan Bukin TRACE_EXIT(brdev);
417*253c8305SRuslan Bukin }
418*253c8305SRuslan Bukin
419*253c8305SRuslan Bukin static int
mmcspi_probe(device_t dev)420*253c8305SRuslan Bukin mmcspi_probe(device_t dev)
421*253c8305SRuslan Bukin {
422*253c8305SRuslan Bukin
423*253c8305SRuslan Bukin if (!ofw_bus_status_okay(dev))
424*253c8305SRuslan Bukin return (ENXIO);
425*253c8305SRuslan Bukin
426*253c8305SRuslan Bukin if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
427*253c8305SRuslan Bukin return (ENXIO);
428*253c8305SRuslan Bukin
429*253c8305SRuslan Bukin device_set_desc(dev, "MMC SPI mode controller");
430*253c8305SRuslan Bukin
431*253c8305SRuslan Bukin return (BUS_PROBE_DEFAULT);
432*253c8305SRuslan Bukin }
433*253c8305SRuslan Bukin
434*253c8305SRuslan Bukin static int
mmcspi_attach(device_t dev)435*253c8305SRuslan Bukin mmcspi_attach(device_t dev)
436*253c8305SRuslan Bukin {
437*253c8305SRuslan Bukin struct mmcspi_softc *sc;
438*253c8305SRuslan Bukin struct sysctl_ctx_list *ctx;
439*253c8305SRuslan Bukin struct sysctl_oid *tree;
440*253c8305SRuslan Bukin struct sysctl_oid_list *child;
441*253c8305SRuslan Bukin
442*253c8305SRuslan Bukin TRACE_ENTER(dev);
443*253c8305SRuslan Bukin
444*253c8305SRuslan Bukin sc = device_get_softc(dev);
445*253c8305SRuslan Bukin ctx = device_get_sysctl_ctx(dev);
446*253c8305SRuslan Bukin tree = device_get_sysctl_tree(dev);
447*253c8305SRuslan Bukin child = SYSCTL_CHILDREN(tree);
448*253c8305SRuslan Bukin
449*253c8305SRuslan Bukin sc->dev = dev;
450*253c8305SRuslan Bukin sc->busdev = device_get_parent(dev);
451*253c8305SRuslan Bukin sc->use_crc = 1;
452*253c8305SRuslan Bukin
453*253c8305SRuslan Bukin SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "use_crc", CTLFLAG_RW,
454*253c8305SRuslan Bukin &sc->use_crc, sizeof(sc->use_crc), "Enable/disable crc checking");
455*253c8305SRuslan Bukin
456*253c8305SRuslan Bukin SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "trace_mask", CTLFLAG_RW,
457*253c8305SRuslan Bukin &trace_zone_mask, sizeof(trace_zone_mask), "Bitmask for adjusting "
458*253c8305SRuslan Bukin "trace messages");
459*253c8305SRuslan Bukin
460*253c8305SRuslan Bukin mmcspi_slot_init(dev, &sc->slot);
461*253c8305SRuslan Bukin
462*253c8305SRuslan Bukin /* XXX trigger this from card insert detection */
463*253c8305SRuslan Bukin mmcspi_card_add(&sc->slot);
464*253c8305SRuslan Bukin
465*253c8305SRuslan Bukin TRACE_EXIT(dev);
466*253c8305SRuslan Bukin
467*253c8305SRuslan Bukin return (0);
468*253c8305SRuslan Bukin }
469*253c8305SRuslan Bukin
470*253c8305SRuslan Bukin static int
mmcspi_detach(device_t dev)471*253c8305SRuslan Bukin mmcspi_detach(device_t dev)
472*253c8305SRuslan Bukin {
473*253c8305SRuslan Bukin struct mmcspi_softc *sc;
474*253c8305SRuslan Bukin
475*253c8305SRuslan Bukin TRACE_ENTER(dev);
476*253c8305SRuslan Bukin
477*253c8305SRuslan Bukin sc = device_get_softc(dev);
478*253c8305SRuslan Bukin
479*253c8305SRuslan Bukin /* XXX trigger this from card removal detection */
480*253c8305SRuslan Bukin mmcspi_card_delete(&sc->slot);
481*253c8305SRuslan Bukin
482*253c8305SRuslan Bukin mmcspi_slot_fini(dev, &sc->slot);
483*253c8305SRuslan Bukin
484*253c8305SRuslan Bukin TRACE_EXIT(dev);
485*253c8305SRuslan Bukin
486*253c8305SRuslan Bukin return (0);
487*253c8305SRuslan Bukin }
488*253c8305SRuslan Bukin
489*253c8305SRuslan Bukin static int
mmcspi_suspend(device_t dev)490*253c8305SRuslan Bukin mmcspi_suspend(device_t dev)
491*253c8305SRuslan Bukin {
492*253c8305SRuslan Bukin int err;
493*253c8305SRuslan Bukin
494*253c8305SRuslan Bukin TRACE_ENTER(dev);
495*253c8305SRuslan Bukin err = bus_generic_suspend(dev);
496*253c8305SRuslan Bukin if (err) {
497*253c8305SRuslan Bukin TRACE_EXIT(dev);
498*253c8305SRuslan Bukin return (err);
499*253c8305SRuslan Bukin }
500*253c8305SRuslan Bukin TRACE_EXIT(dev);
501*253c8305SRuslan Bukin
502*253c8305SRuslan Bukin return (0);
503*253c8305SRuslan Bukin }
504*253c8305SRuslan Bukin
505*253c8305SRuslan Bukin static int
mmcspi_resume(device_t dev)506*253c8305SRuslan Bukin mmcspi_resume(device_t dev)
507*253c8305SRuslan Bukin {
508*253c8305SRuslan Bukin int err;
509*253c8305SRuslan Bukin
510*253c8305SRuslan Bukin TRACE_ENTER(dev);
511*253c8305SRuslan Bukin err = bus_generic_resume(dev);
512*253c8305SRuslan Bukin if (err) {
513*253c8305SRuslan Bukin TRACE_EXIT(dev);
514*253c8305SRuslan Bukin return (err);
515*253c8305SRuslan Bukin }
516*253c8305SRuslan Bukin TRACE_EXIT(dev);
517*253c8305SRuslan Bukin
518*253c8305SRuslan Bukin return (0);
519*253c8305SRuslan Bukin }
520*253c8305SRuslan Bukin
521*253c8305SRuslan Bukin static int
mmcspi_read_ivar(device_t bus,device_t child,int which,uintptr_t * result)522*253c8305SRuslan Bukin mmcspi_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
523*253c8305SRuslan Bukin {
524*253c8305SRuslan Bukin struct mmcspi_slot *slot;
525*253c8305SRuslan Bukin
526*253c8305SRuslan Bukin TRACE_ENTER(bus);
527*253c8305SRuslan Bukin
528*253c8305SRuslan Bukin slot = device_get_ivars(child);
529*253c8305SRuslan Bukin
530*253c8305SRuslan Bukin switch (which) {
531*253c8305SRuslan Bukin case MMCBR_IVAR_BUS_TYPE:
532*253c8305SRuslan Bukin *result = bus_type_spi;
533*253c8305SRuslan Bukin break;
534*253c8305SRuslan Bukin case MMCBR_IVAR_BUS_MODE:
535*253c8305SRuslan Bukin *result = slot->host.ios.bus_mode;
536*253c8305SRuslan Bukin break;
537*253c8305SRuslan Bukin case MMCBR_IVAR_BUS_WIDTH:
538*253c8305SRuslan Bukin *result = slot->host.ios.bus_width;
539*253c8305SRuslan Bukin break;
540*253c8305SRuslan Bukin case MMCBR_IVAR_CHIP_SELECT:
541*253c8305SRuslan Bukin *result = slot->host.ios.chip_select;
542*253c8305SRuslan Bukin break;
543*253c8305SRuslan Bukin case MMCBR_IVAR_CLOCK:
544*253c8305SRuslan Bukin *result = slot->host.ios.clock;
545*253c8305SRuslan Bukin break;
546*253c8305SRuslan Bukin case MMCBR_IVAR_F_MIN:
547*253c8305SRuslan Bukin *result = slot->host.f_min;
548*253c8305SRuslan Bukin break;
549*253c8305SRuslan Bukin case MMCBR_IVAR_F_MAX:
550*253c8305SRuslan Bukin *result = slot->host.f_max;
551*253c8305SRuslan Bukin break;
552*253c8305SRuslan Bukin case MMCBR_IVAR_HOST_OCR:
553*253c8305SRuslan Bukin *result = slot->host.host_ocr;
554*253c8305SRuslan Bukin break;
555*253c8305SRuslan Bukin case MMCBR_IVAR_MODE:
556*253c8305SRuslan Bukin *result = slot->host.mode;
557*253c8305SRuslan Bukin break;
558*253c8305SRuslan Bukin case MMCBR_IVAR_OCR:
559*253c8305SRuslan Bukin *result = slot->host.ocr;
560*253c8305SRuslan Bukin break;
561*253c8305SRuslan Bukin case MMCBR_IVAR_POWER_MODE:
562*253c8305SRuslan Bukin *result = slot->host.ios.power_mode;
563*253c8305SRuslan Bukin break;
564*253c8305SRuslan Bukin case MMCBR_IVAR_VDD:
565*253c8305SRuslan Bukin *result = slot->host.ios.vdd;
566*253c8305SRuslan Bukin break;
567*253c8305SRuslan Bukin case MMCBR_IVAR_VCCQ:
568*253c8305SRuslan Bukin *result = slot->host.ios.vccq;
569*253c8305SRuslan Bukin break;
570*253c8305SRuslan Bukin case MMCBR_IVAR_CAPS:
571*253c8305SRuslan Bukin *result = slot->host.caps;
572*253c8305SRuslan Bukin break;
573*253c8305SRuslan Bukin case MMCBR_IVAR_TIMING:
574*253c8305SRuslan Bukin *result = slot->host.ios.timing;
575*253c8305SRuslan Bukin break;
576*253c8305SRuslan Bukin case MMCBR_IVAR_MAX_DATA:
577*253c8305SRuslan Bukin /* seems reasonable, not dictated by anything */
578*253c8305SRuslan Bukin *result = 64 * 1024;
579*253c8305SRuslan Bukin break;
580*253c8305SRuslan Bukin default:
581*253c8305SRuslan Bukin return (EINVAL);
582*253c8305SRuslan Bukin }
583*253c8305SRuslan Bukin
584*253c8305SRuslan Bukin TRACE_EXIT(bus);
585*253c8305SRuslan Bukin
586*253c8305SRuslan Bukin return (0);
587*253c8305SRuslan Bukin }
588*253c8305SRuslan Bukin
589*253c8305SRuslan Bukin static int
mmcspi_write_ivar(device_t bus,device_t child,int which,uintptr_t value)590*253c8305SRuslan Bukin mmcspi_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
591*253c8305SRuslan Bukin {
592*253c8305SRuslan Bukin struct mmcspi_slot *slot;
593*253c8305SRuslan Bukin
594*253c8305SRuslan Bukin TRACE_ENTER(bus);
595*253c8305SRuslan Bukin
596*253c8305SRuslan Bukin slot = device_get_ivars(child);
597*253c8305SRuslan Bukin
598*253c8305SRuslan Bukin switch (which) {
599*253c8305SRuslan Bukin default:
600*253c8305SRuslan Bukin return (EINVAL);
601*253c8305SRuslan Bukin case MMCBR_IVAR_BUS_MODE:
602*253c8305SRuslan Bukin slot->host.ios.bus_mode = value;
603*253c8305SRuslan Bukin break;
604*253c8305SRuslan Bukin case MMCBR_IVAR_BUS_WIDTH:
605*253c8305SRuslan Bukin slot->host.ios.bus_width = value;
606*253c8305SRuslan Bukin break;
607*253c8305SRuslan Bukin case MMCBR_IVAR_CLOCK:
608*253c8305SRuslan Bukin slot->host.ios.clock = value;
609*253c8305SRuslan Bukin break;
610*253c8305SRuslan Bukin case MMCBR_IVAR_CHIP_SELECT:
611*253c8305SRuslan Bukin slot->host.ios.chip_select = value;
612*253c8305SRuslan Bukin break;
613*253c8305SRuslan Bukin case MMCBR_IVAR_MODE:
614*253c8305SRuslan Bukin slot->host.mode = value;
615*253c8305SRuslan Bukin break;
616*253c8305SRuslan Bukin case MMCBR_IVAR_OCR:
617*253c8305SRuslan Bukin slot->host.ocr = value;
618*253c8305SRuslan Bukin break;
619*253c8305SRuslan Bukin case MMCBR_IVAR_POWER_MODE:
620*253c8305SRuslan Bukin slot->host.ios.power_mode = value;
621*253c8305SRuslan Bukin break;
622*253c8305SRuslan Bukin case MMCBR_IVAR_VDD:
623*253c8305SRuslan Bukin slot->host.ios.vdd = value;
624*253c8305SRuslan Bukin break;
625*253c8305SRuslan Bukin case MMCBR_IVAR_VCCQ:
626*253c8305SRuslan Bukin slot->host.ios.vccq = value;
627*253c8305SRuslan Bukin break;
628*253c8305SRuslan Bukin case MMCBR_IVAR_TIMING:
629*253c8305SRuslan Bukin slot->host.ios.timing = value;
630*253c8305SRuslan Bukin break;
631*253c8305SRuslan Bukin case MMCBR_IVAR_BUS_TYPE:
632*253c8305SRuslan Bukin case MMCBR_IVAR_CAPS:
633*253c8305SRuslan Bukin case MMCBR_IVAR_HOST_OCR:
634*253c8305SRuslan Bukin case MMCBR_IVAR_F_MIN:
635*253c8305SRuslan Bukin case MMCBR_IVAR_F_MAX:
636*253c8305SRuslan Bukin case MMCBR_IVAR_MAX_DATA:
637*253c8305SRuslan Bukin return (EINVAL);
638*253c8305SRuslan Bukin }
639*253c8305SRuslan Bukin TRACE_EXIT(bus);
640*253c8305SRuslan Bukin
641*253c8305SRuslan Bukin return (0);
642*253c8305SRuslan Bukin }
643*253c8305SRuslan Bukin
644*253c8305SRuslan Bukin static unsigned int
mmcspi_do_spi_read(device_t dev,uint8_t * data,unsigned int len)645*253c8305SRuslan Bukin mmcspi_do_spi_read(device_t dev, uint8_t *data, unsigned int len)
646*253c8305SRuslan Bukin {
647*253c8305SRuslan Bukin struct spi_command spi_cmd;
648*253c8305SRuslan Bukin struct mmcspi_softc *sc;
649*253c8305SRuslan Bukin int err;
650*253c8305SRuslan Bukin
651*253c8305SRuslan Bukin TRACE_ENTER(dev);
652*253c8305SRuslan Bukin
653*253c8305SRuslan Bukin sc = device_get_softc(dev);
654*253c8305SRuslan Bukin
655*253c8305SRuslan Bukin spi_cmd.tx_cmd = onesbuf;
656*253c8305SRuslan Bukin spi_cmd.rx_cmd = data;
657*253c8305SRuslan Bukin spi_cmd.tx_cmd_sz = len;
658*253c8305SRuslan Bukin spi_cmd.rx_cmd_sz = len;
659*253c8305SRuslan Bukin spi_cmd.tx_data = NULL;
660*253c8305SRuslan Bukin spi_cmd.rx_data = NULL;
661*253c8305SRuslan Bukin spi_cmd.tx_data_sz = 0;
662*253c8305SRuslan Bukin spi_cmd.rx_data_sz = 0;
663*253c8305SRuslan Bukin
664*253c8305SRuslan Bukin err = SPIBUS_TRANSFER(sc->busdev, sc->dev, &spi_cmd);
665*253c8305SRuslan Bukin
666*253c8305SRuslan Bukin #ifdef DEBUG_RX
667*253c8305SRuslan Bukin int i;
668*253c8305SRuslan Bukin if (err == 0) {
669*253c8305SRuslan Bukin printf("rx val: ");
670*253c8305SRuslan Bukin for (i = 0; i < len; i++)
671*253c8305SRuslan Bukin printf("%x ", data[i]);
672*253c8305SRuslan Bukin printf("\n");
673*253c8305SRuslan Bukin }
674*253c8305SRuslan Bukin #endif
675*253c8305SRuslan Bukin
676*253c8305SRuslan Bukin TRACE_EXIT(dev);
677*253c8305SRuslan Bukin
678*253c8305SRuslan Bukin return (err ? MMC_ERR_FAILED : MMC_ERR_NONE);
679*253c8305SRuslan Bukin }
680*253c8305SRuslan Bukin
681*253c8305SRuslan Bukin static unsigned int
mmcspi_do_spi_write(device_t dev,uint8_t * cmd,unsigned int cmdlen,uint8_t * data,unsigned int datalen)682*253c8305SRuslan Bukin mmcspi_do_spi_write(device_t dev, uint8_t *cmd, unsigned int cmdlen,
683*253c8305SRuslan Bukin uint8_t *data, unsigned int datalen)
684*253c8305SRuslan Bukin {
685*253c8305SRuslan Bukin struct mmcspi_softc *sc;
686*253c8305SRuslan Bukin struct spi_command spi_cmd;
687*253c8305SRuslan Bukin int err;
688*253c8305SRuslan Bukin
689*253c8305SRuslan Bukin TRACE_ENTER(dev);
690*253c8305SRuslan Bukin
691*253c8305SRuslan Bukin sc = device_get_softc(dev);
692*253c8305SRuslan Bukin
693*253c8305SRuslan Bukin spi_cmd.tx_cmd = cmd;
694*253c8305SRuslan Bukin spi_cmd.rx_cmd = junkbuf;
695*253c8305SRuslan Bukin spi_cmd.tx_cmd_sz = cmdlen;
696*253c8305SRuslan Bukin spi_cmd.rx_cmd_sz = cmdlen;
697*253c8305SRuslan Bukin spi_cmd.tx_data = data;
698*253c8305SRuslan Bukin spi_cmd.rx_data = junkbuf;
699*253c8305SRuslan Bukin spi_cmd.tx_data_sz = datalen;
700*253c8305SRuslan Bukin spi_cmd.rx_data_sz = datalen;
701*253c8305SRuslan Bukin
702*253c8305SRuslan Bukin err = SPIBUS_TRANSFER(sc->busdev, sc->dev, &spi_cmd);
703*253c8305SRuslan Bukin
704*253c8305SRuslan Bukin TRACE_EXIT(dev);
705*253c8305SRuslan Bukin
706*253c8305SRuslan Bukin return (err ? MMC_ERR_FAILED : MMC_ERR_NONE);
707*253c8305SRuslan Bukin }
708*253c8305SRuslan Bukin
709*253c8305SRuslan Bukin static unsigned int
mmcspi_wait_for_not_busy(device_t dev)710*253c8305SRuslan Bukin mmcspi_wait_for_not_busy(device_t dev)
711*253c8305SRuslan Bukin {
712*253c8305SRuslan Bukin unsigned int busy_length;
713*253c8305SRuslan Bukin uint8_t pollbuf[MMCSPI_POLL_LEN];
714*253c8305SRuslan Bukin struct bintime start, elapsed;
715*253c8305SRuslan Bukin unsigned int err;
716*253c8305SRuslan Bukin int i;
717*253c8305SRuslan Bukin
718*253c8305SRuslan Bukin busy_length = 0;
719*253c8305SRuslan Bukin
720*253c8305SRuslan Bukin TRACE_ENTER(dev);
721*253c8305SRuslan Bukin TRACE(dev, ACTION, "waiting for not busy\n");
722*253c8305SRuslan Bukin
723*253c8305SRuslan Bukin getbintime(&start);
724*253c8305SRuslan Bukin do {
725*253c8305SRuslan Bukin TRACE(dev, DETAILS, "looking for end of busy\n");
726*253c8305SRuslan Bukin err = mmcspi_do_spi_read(dev, pollbuf, MMCSPI_POLL_LEN);
727*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
728*253c8305SRuslan Bukin TRACE(dev, ERROR, "spi read failed\n");
729*253c8305SRuslan Bukin TRACE_EXIT(dev);
730*253c8305SRuslan Bukin return (err);
731*253c8305SRuslan Bukin }
732*253c8305SRuslan Bukin
733*253c8305SRuslan Bukin for (i = 0; i < MMCSPI_POLL_LEN; i++) {
734*253c8305SRuslan Bukin if (pollbuf[i] != 0x00) {
735*253c8305SRuslan Bukin TRACE(dev, DETAILS,
736*253c8305SRuslan Bukin "end of busy found at %d\n", i);
737*253c8305SRuslan Bukin break;
738*253c8305SRuslan Bukin }
739*253c8305SRuslan Bukin busy_length++;
740*253c8305SRuslan Bukin }
741*253c8305SRuslan Bukin
742*253c8305SRuslan Bukin getbintime(&elapsed);
743*253c8305SRuslan Bukin bintime_sub(&elapsed, &start);
744*253c8305SRuslan Bukin
745*253c8305SRuslan Bukin if (elapsed.sec > MMCSPI_TIMEOUT_SEC) {
746*253c8305SRuslan Bukin TRACE(dev, ERROR, "card busy timeout\n");
747*253c8305SRuslan Bukin return (MMC_ERR_TIMEOUT);
748*253c8305SRuslan Bukin }
749*253c8305SRuslan Bukin } while (MMCSPI_POLL_LEN == i);
750*253c8305SRuslan Bukin
751*253c8305SRuslan Bukin TRACE(dev, RESULT, "busy for %u byte slots\n", busy_length);
752*253c8305SRuslan Bukin TRACE_EXIT(dev);
753*253c8305SRuslan Bukin
754*253c8305SRuslan Bukin return (MMC_ERR_NONE);
755*253c8305SRuslan Bukin }
756*253c8305SRuslan Bukin
757*253c8305SRuslan Bukin static int
mmcspi_update_ios(device_t brdev,device_t reqdev)758*253c8305SRuslan Bukin mmcspi_update_ios(device_t brdev, device_t reqdev)
759*253c8305SRuslan Bukin {
760*253c8305SRuslan Bukin struct mmcspi_softc *sc;
761*253c8305SRuslan Bukin struct mmcspi_slot *slot;
762*253c8305SRuslan Bukin struct spi_command spi_cmd;
763*253c8305SRuslan Bukin
764*253c8305SRuslan Bukin TRACE_ENTER(brdev);
765*253c8305SRuslan Bukin
766*253c8305SRuslan Bukin sc = device_get_softc(brdev);
767*253c8305SRuslan Bukin slot = device_get_ivars(reqdev);
768*253c8305SRuslan Bukin
769*253c8305SRuslan Bukin if (power_up == slot->host.ios.power_mode) {
770*253c8305SRuslan Bukin /*
771*253c8305SRuslan Bukin * This sequence provides the initialization steps required
772*253c8305SRuslan Bukin * by the spec after card power is applied, but before any
773*253c8305SRuslan Bukin * commands are issued. These operations are harmless if
774*253c8305SRuslan Bukin * applied at any other time (after a warm reset, for
775*253c8305SRuslan Bukin * example).
776*253c8305SRuslan Bukin */
777*253c8305SRuslan Bukin
778*253c8305SRuslan Bukin /*
779*253c8305SRuslan Bukin * XXX Power-on portion of implementation of card power
780*253c8305SRuslan Bukin * control should go here. Should probably include a power
781*253c8305SRuslan Bukin * off first to ensure card is fully reset from any previous
782*253c8305SRuslan Bukin * state.
783*253c8305SRuslan Bukin */
784*253c8305SRuslan Bukin
785*253c8305SRuslan Bukin /*
786*253c8305SRuslan Bukin * Make sure power to card has ramped up. The spec requires
787*253c8305SRuslan Bukin * power to ramp up in 35ms or less.
788*253c8305SRuslan Bukin */
789*253c8305SRuslan Bukin DELAY(35000);
790*253c8305SRuslan Bukin
791*253c8305SRuslan Bukin /*
792*253c8305SRuslan Bukin * Provide at least 74 clocks with CS and MOSI high that the
793*253c8305SRuslan Bukin * spec requires after card power stabilizes.
794*253c8305SRuslan Bukin */
795*253c8305SRuslan Bukin
796*253c8305SRuslan Bukin spi_cmd.tx_cmd = onesbuf;
797*253c8305SRuslan Bukin spi_cmd.tx_cmd_sz = 10;
798*253c8305SRuslan Bukin spi_cmd.rx_cmd = junkbuf;
799*253c8305SRuslan Bukin spi_cmd.rx_cmd_sz = 10;
800*253c8305SRuslan Bukin spi_cmd.tx_data = NULL;
801*253c8305SRuslan Bukin spi_cmd.rx_data = NULL;
802*253c8305SRuslan Bukin spi_cmd.tx_data_sz = 0;
803*253c8305SRuslan Bukin spi_cmd.rx_data_sz = 0;
804*253c8305SRuslan Bukin
805*253c8305SRuslan Bukin SPIBUS_TRANSFER(sc->busdev, sc->dev, &spi_cmd);
806*253c8305SRuslan Bukin
807*253c8305SRuslan Bukin /*
808*253c8305SRuslan Bukin * Perhaps this was a warm reset and the card is in the
809*253c8305SRuslan Bukin * middle of a long operation.
810*253c8305SRuslan Bukin */
811*253c8305SRuslan Bukin mmcspi_wait_for_not_busy(brdev);
812*253c8305SRuslan Bukin
813*253c8305SRuslan Bukin slot->last_opcode = 0xffffffff;
814*253c8305SRuslan Bukin slot->last_flags = 0;
815*253c8305SRuslan Bukin memset(slot->last_ocr, 0, MMCSPI_OCR_LEN);
816*253c8305SRuslan Bukin slot->crc_enabled = 0;
817*253c8305SRuslan Bukin slot->crc_init_done = 0;
818*253c8305SRuslan Bukin }
819*253c8305SRuslan Bukin
820*253c8305SRuslan Bukin if (power_off == slot->host.ios.power_mode) {
821*253c8305SRuslan Bukin /*
822*253c8305SRuslan Bukin * XXX Power-off portion of implementation of card power
823*253c8305SRuslan Bukin * control should go here.
824*253c8305SRuslan Bukin */
825*253c8305SRuslan Bukin }
826*253c8305SRuslan Bukin
827*253c8305SRuslan Bukin TRACE_EXIT(brdev);
828*253c8305SRuslan Bukin
829*253c8305SRuslan Bukin return (0);
830*253c8305SRuslan Bukin }
831*253c8305SRuslan Bukin
832*253c8305SRuslan Bukin static unsigned int
mmcspi_shift_copy(uint8_t * dest,uint8_t * src,unsigned int dest_len,unsigned int shift)833*253c8305SRuslan Bukin mmcspi_shift_copy(uint8_t *dest, uint8_t *src, unsigned int dest_len,
834*253c8305SRuslan Bukin unsigned int shift)
835*253c8305SRuslan Bukin {
836*253c8305SRuslan Bukin unsigned int i;
837*253c8305SRuslan Bukin
838*253c8305SRuslan Bukin if (0 == shift)
839*253c8305SRuslan Bukin memcpy(dest, src, dest_len);
840*253c8305SRuslan Bukin else {
841*253c8305SRuslan Bukin for (i = 0; i < dest_len; i++) {
842*253c8305SRuslan Bukin dest[i] =
843*253c8305SRuslan Bukin (src[i] << shift) |
844*253c8305SRuslan Bukin (src[i + 1] >> (8 - shift));
845*253c8305SRuslan Bukin }
846*253c8305SRuslan Bukin }
847*253c8305SRuslan Bukin
848*253c8305SRuslan Bukin return (dest_len);
849*253c8305SRuslan Bukin }
850*253c8305SRuslan Bukin
851*253c8305SRuslan Bukin static unsigned int
mmcspi_get_response_token(device_t dev,uint8_t mask,uint8_t value,unsigned int len,unsigned int has_busy,uint8_t * rspbuf)852*253c8305SRuslan Bukin mmcspi_get_response_token(device_t dev, uint8_t mask, uint8_t value,
853*253c8305SRuslan Bukin unsigned int len, unsigned int has_busy, uint8_t *rspbuf)
854*253c8305SRuslan Bukin {
855*253c8305SRuslan Bukin uint8_t pollbuf[2 * MMCSPI_MAX_RSP_LEN];
856*253c8305SRuslan Bukin struct bintime start, elapsed;
857*253c8305SRuslan Bukin boolean_t found;
858*253c8305SRuslan Bukin unsigned int err;
859*253c8305SRuslan Bukin unsigned int offset;
860*253c8305SRuslan Bukin unsigned int shift = 0;
861*253c8305SRuslan Bukin unsigned int remaining;
862*253c8305SRuslan Bukin uint16_t search_space;
863*253c8305SRuslan Bukin uint16_t search_mask;
864*253c8305SRuslan Bukin uint16_t search_value;
865*253c8305SRuslan Bukin int i;
866*253c8305SRuslan Bukin
867*253c8305SRuslan Bukin TRACE_ENTER(dev);
868*253c8305SRuslan Bukin
869*253c8305SRuslan Bukin /*
870*253c8305SRuslan Bukin * This loop searches data clocked out of the card for a response
871*253c8305SRuslan Bukin * token matching the given mask and value. It will locate tokens
872*253c8305SRuslan Bukin * that are not byte-aligned, as some cards send non-byte-aligned
873*253c8305SRuslan Bukin * response tokens in some situations. For example, the following
874*253c8305SRuslan Bukin * card consistently sends an unaligned response token to the stop
875*253c8305SRuslan Bukin * command used to terminate multi-block reads:
876*253c8305SRuslan Bukin *
877*253c8305SRuslan Bukin * Transcend 2GB SDSC card, cid:
878*253c8305SRuslan Bukin * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=00.2000
879*253c8305SRuslan Bukin */
880*253c8305SRuslan Bukin
881*253c8305SRuslan Bukin offset = 0;
882*253c8305SRuslan Bukin found = false;
883*253c8305SRuslan Bukin getbintime(&start);
884*253c8305SRuslan Bukin do {
885*253c8305SRuslan Bukin TRACE(dev, DETAILS, "looking for response token with "
886*253c8305SRuslan Bukin "mask 0x%02x, value 0x%02x\n", mask, value);
887*253c8305SRuslan Bukin err = mmcspi_do_spi_read(dev, &pollbuf[offset], len);
888*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
889*253c8305SRuslan Bukin TRACE(dev, ERROR, "spi read of resp token failed\n");
890*253c8305SRuslan Bukin TRACE_EXIT(dev);
891*253c8305SRuslan Bukin return (err);
892*253c8305SRuslan Bukin }
893*253c8305SRuslan Bukin
894*253c8305SRuslan Bukin for (i = 0; i < len + offset; i++) {
895*253c8305SRuslan Bukin if ((pollbuf[i] & mask) == value) {
896*253c8305SRuslan Bukin TRACE(dev, DETAILS, "response token found at "
897*253c8305SRuslan Bukin "%d (0x%02x)\n", i, pollbuf[i]);
898*253c8305SRuslan Bukin shift = 0;
899*253c8305SRuslan Bukin found = true;
900*253c8305SRuslan Bukin break;
901*253c8305SRuslan Bukin } else if (i < len + offset - 1) {
902*253c8305SRuslan Bukin /*
903*253c8305SRuslan Bukin * Not the last byte in the buffer, so check
904*253c8305SRuslan Bukin * for a non-aligned response.
905*253c8305SRuslan Bukin */
906*253c8305SRuslan Bukin search_space = ((uint16_t)pollbuf[i] << 8) |
907*253c8305SRuslan Bukin pollbuf[i + 1];
908*253c8305SRuslan Bukin search_mask = (uint16_t)mask << 8;
909*253c8305SRuslan Bukin search_value = (uint16_t)value << 8;
910*253c8305SRuslan Bukin
911*253c8305SRuslan Bukin TRACE(dev, DETAILS, "search: space=0x%04x "
912*253c8305SRuslan Bukin " mask=0x%04x val=0x%04x\n", search_space,
913*253c8305SRuslan Bukin search_mask, search_value);
914*253c8305SRuslan Bukin
915*253c8305SRuslan Bukin for (shift = 1; shift < 8; shift++) {
916*253c8305SRuslan Bukin search_space <<= 1;
917*253c8305SRuslan Bukin if ((search_space & search_mask) ==
918*253c8305SRuslan Bukin search_value) {
919*253c8305SRuslan Bukin found = true;
920*253c8305SRuslan Bukin TRACE(dev, DETAILS, "Found mat"
921*253c8305SRuslan Bukin "ch at shift %u\n", shift);
922*253c8305SRuslan Bukin break;
923*253c8305SRuslan Bukin }
924*253c8305SRuslan Bukin }
925*253c8305SRuslan Bukin
926*253c8305SRuslan Bukin if (shift < 8)
927*253c8305SRuslan Bukin break;
928*253c8305SRuslan Bukin } else {
929*253c8305SRuslan Bukin /*
930*253c8305SRuslan Bukin * Move the last byte to the first position
931*253c8305SRuslan Bukin * and go 'round again.
932*253c8305SRuslan Bukin */
933*253c8305SRuslan Bukin pollbuf[0] = pollbuf[i];
934*253c8305SRuslan Bukin }
935*253c8305SRuslan Bukin }
936*253c8305SRuslan Bukin
937*253c8305SRuslan Bukin if (!found) {
938*253c8305SRuslan Bukin offset = 1;
939*253c8305SRuslan Bukin
940*253c8305SRuslan Bukin getbintime(&elapsed);
941*253c8305SRuslan Bukin bintime_sub(&elapsed, &start);
942*253c8305SRuslan Bukin
943*253c8305SRuslan Bukin if (elapsed.sec > MMCSPI_TIMEOUT_SEC) {
944*253c8305SRuslan Bukin TRACE(dev, ERROR, "timeout while looking for "
945*253c8305SRuslan Bukin "response token\n");
946*253c8305SRuslan Bukin return (MMC_ERR_TIMEOUT);
947*253c8305SRuslan Bukin }
948*253c8305SRuslan Bukin }
949*253c8305SRuslan Bukin } while (!found);
950*253c8305SRuslan Bukin
951*253c8305SRuslan Bukin /*
952*253c8305SRuslan Bukin * Note that if i == 0 and offset == 1, shift is always greater than
953*253c8305SRuslan Bukin * zero.
954*253c8305SRuslan Bukin */
955*253c8305SRuslan Bukin remaining = i - offset + (shift ? 1 : 0);
956*253c8305SRuslan Bukin
957*253c8305SRuslan Bukin TRACE(dev, DETAILS, "len=%u i=%u rem=%u shift=%u\n",
958*253c8305SRuslan Bukin len, i, remaining, shift);
959*253c8305SRuslan Bukin
960*253c8305SRuslan Bukin if (remaining) {
961*253c8305SRuslan Bukin err = mmcspi_do_spi_read(dev, &pollbuf[len + offset],
962*253c8305SRuslan Bukin remaining);
963*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
964*253c8305SRuslan Bukin TRACE(dev, ERROR, "spi read of remainder of response "
965*253c8305SRuslan Bukin "token failed\n");
966*253c8305SRuslan Bukin TRACE_EXIT(dev);
967*253c8305SRuslan Bukin return (err);
968*253c8305SRuslan Bukin }
969*253c8305SRuslan Bukin }
970*253c8305SRuslan Bukin
971*253c8305SRuslan Bukin mmcspi_shift_copy(rspbuf, &pollbuf[i], len, shift);
972*253c8305SRuslan Bukin
973*253c8305SRuslan Bukin if (TRACE_ZONE_ENABLED(RESULT)) {
974*253c8305SRuslan Bukin TRACE(dev, RESULT, "response =");
975*253c8305SRuslan Bukin for (i = 0; i < len; i++)
976*253c8305SRuslan Bukin printf(" 0x%02x", rspbuf[i]);
977*253c8305SRuslan Bukin printf("\n");
978*253c8305SRuslan Bukin }
979*253c8305SRuslan Bukin
980*253c8305SRuslan Bukin if (has_busy) {
981*253c8305SRuslan Bukin err = mmcspi_wait_for_not_busy(dev);
982*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
983*253c8305SRuslan Bukin TRACE_EXIT(dev);
984*253c8305SRuslan Bukin return (err);
985*253c8305SRuslan Bukin }
986*253c8305SRuslan Bukin }
987*253c8305SRuslan Bukin
988*253c8305SRuslan Bukin TRACE_EXIT(dev);
989*253c8305SRuslan Bukin
990*253c8305SRuslan Bukin return (MMC_ERR_NONE);
991*253c8305SRuslan Bukin }
992*253c8305SRuslan Bukin
993*253c8305SRuslan Bukin static unsigned int
mmcspi_set_up_command(device_t dev,struct mmcspi_command * mmcspi_cmd,struct mmc_command * mmc_cmd)994*253c8305SRuslan Bukin mmcspi_set_up_command(device_t dev, struct mmcspi_command *mmcspi_cmd,
995*253c8305SRuslan Bukin struct mmc_command *mmc_cmd)
996*253c8305SRuslan Bukin {
997*253c8305SRuslan Bukin struct mmcspi_softc *sc;
998*253c8305SRuslan Bukin struct mmcspi_slot *slot;
999*253c8305SRuslan Bukin uint32_t opcode;
1000*253c8305SRuslan Bukin uint32_t arg;
1001*253c8305SRuslan Bukin uint32_t flags;
1002*253c8305SRuslan Bukin uint32_t retries;
1003*253c8305SRuslan Bukin unsigned char rsp_type;
1004*253c8305SRuslan Bukin unsigned char rsp_len;
1005*253c8305SRuslan Bukin unsigned char mmc_rsp_type;
1006*253c8305SRuslan Bukin unsigned int ldata_len = 0;
1007*253c8305SRuslan Bukin unsigned int use_crc;
1008*253c8305SRuslan Bukin
1009*253c8305SRuslan Bukin sc = device_get_softc(dev);
1010*253c8305SRuslan Bukin slot = &sc->slot;
1011*253c8305SRuslan Bukin use_crc = slot->crc_enabled;
1012*253c8305SRuslan Bukin
1013*253c8305SRuslan Bukin opcode = mmc_cmd->opcode;
1014*253c8305SRuslan Bukin arg = mmc_cmd->arg;
1015*253c8305SRuslan Bukin flags = mmc_cmd->flags;
1016*253c8305SRuslan Bukin retries = mmc_cmd->retries;
1017*253c8305SRuslan Bukin
1018*253c8305SRuslan Bukin if (flags & MMC_CMD_IS_APP) {
1019*253c8305SRuslan Bukin switch (opcode) {
1020*253c8305SRuslan Bukin case ACMD_SD_STATUS:
1021*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R2;
1022*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R1;
1023*253c8305SRuslan Bukin break;
1024*253c8305SRuslan Bukin case ACMD_SEND_NUM_WR_BLOCKS:
1025*253c8305SRuslan Bukin case ACMD_SET_WR_BLK_ERASE_COUNT:
1026*253c8305SRuslan Bukin case ACMD_SET_CLR_CARD_DETECT:
1027*253c8305SRuslan Bukin case ACMD_SEND_SCR:
1028*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1029*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R1;
1030*253c8305SRuslan Bukin break;
1031*253c8305SRuslan Bukin case ACMD_SD_SEND_OP_COND:
1032*253c8305SRuslan Bukin /* only HCS bit is valid in spi mode */
1033*253c8305SRuslan Bukin arg &= 0x40000000;
1034*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1035*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R3;
1036*253c8305SRuslan Bukin break;
1037*253c8305SRuslan Bukin default:
1038*253c8305SRuslan Bukin TRACE(dev, ERROR, "Invalid app command opcode %u\n",
1039*253c8305SRuslan Bukin opcode);
1040*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1041*253c8305SRuslan Bukin }
1042*253c8305SRuslan Bukin } else {
1043*253c8305SRuslan Bukin switch (opcode) {
1044*253c8305SRuslan Bukin case MMC_GO_IDLE_STATE:
1045*253c8305SRuslan Bukin use_crc = 1;
1046*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1047*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_NONE;
1048*253c8305SRuslan Bukin break;
1049*253c8305SRuslan Bukin
1050*253c8305SRuslan Bukin case MMC_SEND_OP_COND:
1051*253c8305SRuslan Bukin case MMC_SWITCH_FUNC: /* also SD_SWITCH_FUNC */
1052*253c8305SRuslan Bukin case MMC_SET_BLOCKLEN:
1053*253c8305SRuslan Bukin case MMC_READ_SINGLE_BLOCK:
1054*253c8305SRuslan Bukin case MMC_READ_MULTIPLE_BLOCK:
1055*253c8305SRuslan Bukin case MMC_WRITE_BLOCK:
1056*253c8305SRuslan Bukin case MMC_WRITE_MULTIPLE_BLOCK:
1057*253c8305SRuslan Bukin case MMC_PROGRAM_CSD:
1058*253c8305SRuslan Bukin case MMC_SEND_WRITE_PROT:
1059*253c8305SRuslan Bukin case SD_ERASE_WR_BLK_START:
1060*253c8305SRuslan Bukin case SD_ERASE_WR_BLK_END:
1061*253c8305SRuslan Bukin case MMC_LOCK_UNLOCK:
1062*253c8305SRuslan Bukin case MMC_GEN_CMD:
1063*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1064*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R1;
1065*253c8305SRuslan Bukin break;
1066*253c8305SRuslan Bukin case MMCSPI_CRC_ON_OFF:
1067*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1068*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_NONE;
1069*253c8305SRuslan Bukin break;
1070*253c8305SRuslan Bukin
1071*253c8305SRuslan Bukin case MMC_SEND_CSD:
1072*253c8305SRuslan Bukin case MMC_SEND_CID:
1073*253c8305SRuslan Bukin arg = 0; /* no rca in spi mode */
1074*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1075*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R2;
1076*253c8305SRuslan Bukin ldata_len = 16;
1077*253c8305SRuslan Bukin break;
1078*253c8305SRuslan Bukin
1079*253c8305SRuslan Bukin case MMC_APP_CMD:
1080*253c8305SRuslan Bukin arg = 0; /* no rca in spi mode */
1081*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1082*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R1;
1083*253c8305SRuslan Bukin break;
1084*253c8305SRuslan Bukin
1085*253c8305SRuslan Bukin case MMC_STOP_TRANSMISSION:
1086*253c8305SRuslan Bukin case MMC_SET_WRITE_PROT:
1087*253c8305SRuslan Bukin case MMC_CLR_WRITE_PROT:
1088*253c8305SRuslan Bukin case MMC_ERASE:
1089*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1B;
1090*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R1B;
1091*253c8305SRuslan Bukin break;
1092*253c8305SRuslan Bukin
1093*253c8305SRuslan Bukin case MMC_ALL_SEND_CID:
1094*253c8305SRuslan Bukin /* handle MMC_ALL_SEND_CID as MMC_SEND_CID */
1095*253c8305SRuslan Bukin opcode = MMC_SEND_CID;
1096*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R1;
1097*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R2;
1098*253c8305SRuslan Bukin ldata_len = 16;
1099*253c8305SRuslan Bukin break;
1100*253c8305SRuslan Bukin
1101*253c8305SRuslan Bukin case MMC_SEND_STATUS:
1102*253c8305SRuslan Bukin arg = 0; /* no rca in spi mode */
1103*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R2;
1104*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R1;
1105*253c8305SRuslan Bukin break;
1106*253c8305SRuslan Bukin
1107*253c8305SRuslan Bukin
1108*253c8305SRuslan Bukin case MMCSPI_READ_OCR:
1109*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R3;
1110*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_NONE;
1111*253c8305SRuslan Bukin break;
1112*253c8305SRuslan Bukin
1113*253c8305SRuslan Bukin case SD_SEND_RELATIVE_ADDR:
1114*253c8305SRuslan Bukin /*
1115*253c8305SRuslan Bukin * Handle SD_SEND_RELATIVE_ADDR as MMC_SEND_STATUS -
1116*253c8305SRuslan Bukin * the rca returned to the caller will always be 0.
1117*253c8305SRuslan Bukin */
1118*253c8305SRuslan Bukin opcode = MMC_SEND_STATUS;
1119*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R2;
1120*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R6;
1121*253c8305SRuslan Bukin break;
1122*253c8305SRuslan Bukin
1123*253c8305SRuslan Bukin case SD_SEND_IF_COND:
1124*253c8305SRuslan Bukin use_crc = 1;
1125*253c8305SRuslan Bukin rsp_type = MMCSPI_RSP_R7;
1126*253c8305SRuslan Bukin mmc_rsp_type = MMCSPI_TO_MMC_RSP_R7;
1127*253c8305SRuslan Bukin break;
1128*253c8305SRuslan Bukin
1129*253c8305SRuslan Bukin default:
1130*253c8305SRuslan Bukin TRACE(dev, ERROR, "Invalid cmd opcode %u\n", opcode);
1131*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1132*253c8305SRuslan Bukin }
1133*253c8305SRuslan Bukin }
1134*253c8305SRuslan Bukin
1135*253c8305SRuslan Bukin switch (rsp_type) {
1136*253c8305SRuslan Bukin case MMCSPI_RSP_R1:
1137*253c8305SRuslan Bukin case MMCSPI_RSP_R1B:
1138*253c8305SRuslan Bukin rsp_len = 1;
1139*253c8305SRuslan Bukin break;
1140*253c8305SRuslan Bukin case MMCSPI_RSP_R2:
1141*253c8305SRuslan Bukin rsp_len = 2;
1142*253c8305SRuslan Bukin break;
1143*253c8305SRuslan Bukin case MMCSPI_RSP_R3:
1144*253c8305SRuslan Bukin case MMCSPI_RSP_R7:
1145*253c8305SRuslan Bukin rsp_len = 5;
1146*253c8305SRuslan Bukin break;
1147*253c8305SRuslan Bukin default:
1148*253c8305SRuslan Bukin TRACE(dev, ERROR, "Unknown response type %u\n", rsp_type);
1149*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1150*253c8305SRuslan Bukin }
1151*253c8305SRuslan Bukin
1152*253c8305SRuslan Bukin mmcspi_cmd->mmc_cmd = mmc_cmd;
1153*253c8305SRuslan Bukin mmcspi_cmd->opcode = opcode;
1154*253c8305SRuslan Bukin mmcspi_cmd->arg = arg;
1155*253c8305SRuslan Bukin mmcspi_cmd->flags = flags;
1156*253c8305SRuslan Bukin mmcspi_cmd->retries = retries;
1157*253c8305SRuslan Bukin mmcspi_cmd->use_crc = use_crc;
1158*253c8305SRuslan Bukin mmcspi_cmd->error_mask = MMCSPI_R1_ERR_MASK;
1159*253c8305SRuslan Bukin if (!mmcspi_cmd->use_crc)
1160*253c8305SRuslan Bukin mmcspi_cmd->error_mask &= ~MMCSPI_R1_CRC_ERR;
1161*253c8305SRuslan Bukin mmcspi_cmd->rsp_type = rsp_type;
1162*253c8305SRuslan Bukin mmcspi_cmd->rsp_len = rsp_len;
1163*253c8305SRuslan Bukin mmcspi_cmd->mmc_rsp_type = mmc_rsp_type;
1164*253c8305SRuslan Bukin
1165*253c8305SRuslan Bukin memset(&mmcspi_cmd->ldata, 0, sizeof(struct mmc_data));
1166*253c8305SRuslan Bukin mmcspi_cmd->ldata.len = ldata_len;
1167*253c8305SRuslan Bukin if (ldata_len) {
1168*253c8305SRuslan Bukin mmcspi_cmd->ldata.data = sc->slot.ldata_buf;
1169*253c8305SRuslan Bukin mmcspi_cmd->ldata.flags = MMC_DATA_READ;
1170*253c8305SRuslan Bukin
1171*253c8305SRuslan Bukin mmcspi_cmd->data = &mmcspi_cmd->ldata;
1172*253c8305SRuslan Bukin } else
1173*253c8305SRuslan Bukin mmcspi_cmd->data = mmc_cmd->data;
1174*253c8305SRuslan Bukin
1175*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1176*253c8305SRuslan Bukin }
1177*253c8305SRuslan Bukin
1178*253c8305SRuslan Bukin static unsigned int
mmcspi_send_cmd(device_t dev,struct mmcspi_command * cmd,uint8_t * rspbuf)1179*253c8305SRuslan Bukin mmcspi_send_cmd(device_t dev, struct mmcspi_command *cmd, uint8_t *rspbuf)
1180*253c8305SRuslan Bukin {
1181*253c8305SRuslan Bukin unsigned int err;
1182*253c8305SRuslan Bukin uint32_t opcode;
1183*253c8305SRuslan Bukin uint32_t arg;
1184*253c8305SRuslan Bukin uint8_t txbuf[8];
1185*253c8305SRuslan Bukin uint8_t crc;
1186*253c8305SRuslan Bukin
1187*253c8305SRuslan Bukin TRACE_ENTER(dev);
1188*253c8305SRuslan Bukin
1189*253c8305SRuslan Bukin opcode = cmd->opcode;
1190*253c8305SRuslan Bukin arg = cmd->arg;
1191*253c8305SRuslan Bukin
1192*253c8305SRuslan Bukin TRACE(dev, ACTION, "sending %sMD%u(0x%08x)\n",
1193*253c8305SRuslan Bukin cmd->flags & MMC_CMD_IS_APP ? "AC": "C", opcode, arg);
1194*253c8305SRuslan Bukin
1195*253c8305SRuslan Bukin /*
1196*253c8305SRuslan Bukin * Sending this byte ahead of each command prevents some cards from
1197*253c8305SRuslan Bukin * responding with unaligned data, and doesn't bother the others.
1198*253c8305SRuslan Bukin * Examples:
1199*253c8305SRuslan Bukin *
1200*253c8305SRuslan Bukin * Sandisk 32GB SDHC card, cid:
1201*253c8305SRuslan Bukin * mid=0x03 oid=0x5344 pnm="SU32G" prv=8.0 mdt=00.2000
1202*253c8305SRuslan Bukin */
1203*253c8305SRuslan Bukin txbuf[0] = 0xff;
1204*253c8305SRuslan Bukin
1205*253c8305SRuslan Bukin txbuf[1] = 0x40 | (opcode & 0x3f);
1206*253c8305SRuslan Bukin txbuf[2] = arg >> 24;
1207*253c8305SRuslan Bukin txbuf[3] = (arg >> 16) & 0xff;
1208*253c8305SRuslan Bukin txbuf[4] = (arg >> 8) & 0xff;
1209*253c8305SRuslan Bukin txbuf[5] = arg & 0xff;
1210*253c8305SRuslan Bukin
1211*253c8305SRuslan Bukin if (cmd->use_crc)
1212*253c8305SRuslan Bukin crc = update_crc7(CRC7_INITIAL, &txbuf[1], 5);
1213*253c8305SRuslan Bukin else
1214*253c8305SRuslan Bukin crc = 0;
1215*253c8305SRuslan Bukin
1216*253c8305SRuslan Bukin txbuf[6] = (crc << 1) | 0x01;
1217*253c8305SRuslan Bukin
1218*253c8305SRuslan Bukin /*
1219*253c8305SRuslan Bukin * Some cards have garbage on the bus in the first byte slot after
1220*253c8305SRuslan Bukin * the last command byte. This seems to be common with the stop
1221*253c8305SRuslan Bukin * command. Clocking out an extra byte with the command will
1222*253c8305SRuslan Bukin * result in that data not being searched for the response token,
1223*253c8305SRuslan Bukin * which is ok, because no cards respond that fast.
1224*253c8305SRuslan Bukin */
1225*253c8305SRuslan Bukin txbuf[7] = 0xff;
1226*253c8305SRuslan Bukin
1227*253c8305SRuslan Bukin err = mmcspi_do_spi_write(dev, txbuf, sizeof(txbuf), NULL, 0);
1228*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1229*253c8305SRuslan Bukin TRACE(dev, ERROR, "spi write of command failed\n");
1230*253c8305SRuslan Bukin TRACE_EXIT(dev);
1231*253c8305SRuslan Bukin return (err);
1232*253c8305SRuslan Bukin }
1233*253c8305SRuslan Bukin
1234*253c8305SRuslan Bukin TRACE(dev, DETAILS,
1235*253c8305SRuslan Bukin "rx cmd bytes 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
1236*253c8305SRuslan Bukin junkbuf[0], junkbuf[1], junkbuf[2], junkbuf[3], junkbuf[4],
1237*253c8305SRuslan Bukin junkbuf[5] );
1238*253c8305SRuslan Bukin TRACE(dev, DETAILS, "skipped response byte is 0x%02x\n", junkbuf[6]);
1239*253c8305SRuslan Bukin
1240*253c8305SRuslan Bukin err = mmcspi_get_response_token(dev, MMCSPI_R1_MASK, MMCSPI_R1_VALUE,
1241*253c8305SRuslan Bukin cmd->rsp_len, MMCSPI_RSP_R1B == cmd->rsp_type, rspbuf);
1242*253c8305SRuslan Bukin
1243*253c8305SRuslan Bukin if (MMC_ERR_NONE == err) {
1244*253c8305SRuslan Bukin if (rspbuf[0] & cmd->error_mask & MMCSPI_R1_CRC_ERR)
1245*253c8305SRuslan Bukin err = MMC_ERR_BADCRC;
1246*253c8305SRuslan Bukin else if (rspbuf[0] & cmd->error_mask)
1247*253c8305SRuslan Bukin err = MMC_ERR_INVALID;
1248*253c8305SRuslan Bukin }
1249*253c8305SRuslan Bukin
1250*253c8305SRuslan Bukin TRACE_EXIT(dev);
1251*253c8305SRuslan Bukin
1252*253c8305SRuslan Bukin return (err);
1253*253c8305SRuslan Bukin }
1254*253c8305SRuslan Bukin
1255*253c8305SRuslan Bukin static unsigned int
mmcspi_read_block(device_t dev,uint8_t * data,unsigned int len,unsigned int check_crc16,unsigned int check_crc7)1256*253c8305SRuslan Bukin mmcspi_read_block(device_t dev, uint8_t *data, unsigned int len,
1257*253c8305SRuslan Bukin unsigned int check_crc16, unsigned int check_crc7)
1258*253c8305SRuslan Bukin {
1259*253c8305SRuslan Bukin struct bintime start;
1260*253c8305SRuslan Bukin struct bintime elapsed;
1261*253c8305SRuslan Bukin unsigned int non_token_bytes;
1262*253c8305SRuslan Bukin unsigned int data_captured;
1263*253c8305SRuslan Bukin unsigned int crc_captured;
1264*253c8305SRuslan Bukin unsigned int pollbufpos;
1265*253c8305SRuslan Bukin unsigned int crc16_mismatch;
1266*253c8305SRuslan Bukin unsigned int err;
1267*253c8305SRuslan Bukin uint16_t crc16, computed_crc16;
1268*253c8305SRuslan Bukin uint8_t crc7, computed_crc7;
1269*253c8305SRuslan Bukin uint8_t pollbuf[MMCSPI_POLL_LEN];
1270*253c8305SRuslan Bukin uint8_t crcbuf[MMCSPI_DATA_CRC_LEN];
1271*253c8305SRuslan Bukin int i;
1272*253c8305SRuslan Bukin
1273*253c8305SRuslan Bukin crc16_mismatch = 0;
1274*253c8305SRuslan Bukin
1275*253c8305SRuslan Bukin TRACE_ENTER(dev);
1276*253c8305SRuslan Bukin TRACE(dev, ACTION, "read block(%u)\n", len);
1277*253c8305SRuslan Bukin
1278*253c8305SRuslan Bukin /*
1279*253c8305SRuslan Bukin * With this approach, we could pointlessly read up to
1280*253c8305SRuslan Bukin * (MMCSPI_POLL_LEN - 3 - len) bytes from the spi bus, but only in
1281*253c8305SRuslan Bukin * the odd situation where MMCSPI_POLL_LEN is greater than len + 3.
1282*253c8305SRuslan Bukin */
1283*253c8305SRuslan Bukin getbintime(&start);
1284*253c8305SRuslan Bukin do {
1285*253c8305SRuslan Bukin TRACE(dev, DETAILS, "looking for read token\n");
1286*253c8305SRuslan Bukin err = mmcspi_do_spi_read(dev, pollbuf, MMCSPI_POLL_LEN);
1287*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1288*253c8305SRuslan Bukin TRACE(dev, ERROR, "token read on spi failed\n");
1289*253c8305SRuslan Bukin TRACE_EXIT(dev);
1290*253c8305SRuslan Bukin return (err);
1291*253c8305SRuslan Bukin }
1292*253c8305SRuslan Bukin
1293*253c8305SRuslan Bukin for (i = 0; i < MMCSPI_POLL_LEN; i++) {
1294*253c8305SRuslan Bukin if (MMCSPI_TOKEN_SB == pollbuf[i]) {
1295*253c8305SRuslan Bukin TRACE(dev, RESULT,
1296*253c8305SRuslan Bukin "found start block token at %d\n", i);
1297*253c8305SRuslan Bukin break;
1298*253c8305SRuslan Bukin } else if (MMCSPI_IS_DE_TOKEN(pollbuf[i])) {
1299*253c8305SRuslan Bukin TRACE(dev, ERROR,
1300*253c8305SRuslan Bukin "found data error token at %d\n", i);
1301*253c8305SRuslan Bukin TRACE_EXIT(dev);
1302*253c8305SRuslan Bukin return (MMC_ERR_FAILED);
1303*253c8305SRuslan Bukin }
1304*253c8305SRuslan Bukin }
1305*253c8305SRuslan Bukin
1306*253c8305SRuslan Bukin getbintime(&elapsed);
1307*253c8305SRuslan Bukin bintime_sub(&elapsed, &start);
1308*253c8305SRuslan Bukin
1309*253c8305SRuslan Bukin if (elapsed.sec > MMCSPI_TIMEOUT_SEC) {
1310*253c8305SRuslan Bukin TRACE(dev, ERROR, "timeout while looking for read "
1311*253c8305SRuslan Bukin "token\n");
1312*253c8305SRuslan Bukin return (MMC_ERR_TIMEOUT);
1313*253c8305SRuslan Bukin }
1314*253c8305SRuslan Bukin } while (MMCSPI_POLL_LEN == i);
1315*253c8305SRuslan Bukin
1316*253c8305SRuslan Bukin /* copy any data captured in tail of poll buf to data buf */
1317*253c8305SRuslan Bukin non_token_bytes = MMCSPI_POLL_LEN - i - 1;
1318*253c8305SRuslan Bukin data_captured = min(non_token_bytes, len);
1319*253c8305SRuslan Bukin crc_captured = non_token_bytes - data_captured;
1320*253c8305SRuslan Bukin pollbufpos = i + 1;
1321*253c8305SRuslan Bukin
1322*253c8305SRuslan Bukin TRACE(dev, DETAILS, "data bytes captured in pollbuf = %u\n",
1323*253c8305SRuslan Bukin data_captured);
1324*253c8305SRuslan Bukin
1325*253c8305SRuslan Bukin memcpy(data, &pollbuf[pollbufpos], data_captured);
1326*253c8305SRuslan Bukin pollbufpos += data_captured;
1327*253c8305SRuslan Bukin
1328*253c8305SRuslan Bukin TRACE(dev, DETAILS, "data bytes to read = %u, crc_captured = %u\n",
1329*253c8305SRuslan Bukin len - data_captured, crc_captured);
1330*253c8305SRuslan Bukin
1331*253c8305SRuslan Bukin /* get any remaining data from the spi bus */
1332*253c8305SRuslan Bukin if (data_captured < len) {
1333*253c8305SRuslan Bukin err = mmcspi_do_spi_read(dev, &data[data_captured],
1334*253c8305SRuslan Bukin len - data_captured);
1335*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1336*253c8305SRuslan Bukin TRACE(dev, ERROR,
1337*253c8305SRuslan Bukin "spi read of remainder of block failed\n");
1338*253c8305SRuslan Bukin TRACE_EXIT(dev);
1339*253c8305SRuslan Bukin return (err);
1340*253c8305SRuslan Bukin }
1341*253c8305SRuslan Bukin }
1342*253c8305SRuslan Bukin
1343*253c8305SRuslan Bukin /* copy any crc captured in the poll buf to the crc buf */
1344*253c8305SRuslan Bukin memcpy(crcbuf, &pollbuf[pollbufpos], crc_captured);
1345*253c8305SRuslan Bukin
1346*253c8305SRuslan Bukin /* get any remaining crc */
1347*253c8305SRuslan Bukin if (crc_captured < MMCSPI_DATA_CRC_LEN) {
1348*253c8305SRuslan Bukin TRACE(dev, DETAILS, "crc bytes to read = %u\n",
1349*253c8305SRuslan Bukin MMCSPI_DATA_CRC_LEN - crc_captured);
1350*253c8305SRuslan Bukin
1351*253c8305SRuslan Bukin err = mmcspi_do_spi_read(dev, &crcbuf[crc_captured],
1352*253c8305SRuslan Bukin MMCSPI_DATA_CRC_LEN - crc_captured);
1353*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1354*253c8305SRuslan Bukin TRACE(dev, ERROR, "spi read of crc failed\n");
1355*253c8305SRuslan Bukin TRACE_EXIT(dev);
1356*253c8305SRuslan Bukin return (err);
1357*253c8305SRuslan Bukin }
1358*253c8305SRuslan Bukin }
1359*253c8305SRuslan Bukin
1360*253c8305SRuslan Bukin /*
1361*253c8305SRuslan Bukin * The following crc checking code is deliberately structured to
1362*253c8305SRuslan Bukin * allow a passing crc-7 check to override a failing crc-16 check
1363*253c8305SRuslan Bukin * when both are enabled.
1364*253c8305SRuslan Bukin */
1365*253c8305SRuslan Bukin if (check_crc16) {
1366*253c8305SRuslan Bukin crc16 = ((uint16_t)crcbuf[0] << 8) | crcbuf[1];
1367*253c8305SRuslan Bukin computed_crc16 = update_crc16(CRC16_INITIAL, data, len);
1368*253c8305SRuslan Bukin TRACE(dev, RESULT, "sent_crc16=0x%04x computed_crc16=0x%04x\n",
1369*253c8305SRuslan Bukin crc16, computed_crc16);
1370*253c8305SRuslan Bukin
1371*253c8305SRuslan Bukin if (computed_crc16 != crc16) {
1372*253c8305SRuslan Bukin crc16_mismatch = 1;
1373*253c8305SRuslan Bukin
1374*253c8305SRuslan Bukin TRACE(dev, ERROR, "crc16 mismatch, should be 0x%04x, "
1375*253c8305SRuslan Bukin " is 0x%04x\n", crc16, computed_crc16);
1376*253c8305SRuslan Bukin
1377*253c8305SRuslan Bukin if (!check_crc7) {
1378*253c8305SRuslan Bukin TRACE_EXIT(dev);
1379*253c8305SRuslan Bukin return (MMC_ERR_BADCRC);
1380*253c8305SRuslan Bukin }
1381*253c8305SRuslan Bukin }
1382*253c8305SRuslan Bukin }
1383*253c8305SRuslan Bukin
1384*253c8305SRuslan Bukin if (check_crc7) {
1385*253c8305SRuslan Bukin if (crc16_mismatch) {
1386*253c8305SRuslan Bukin /*
1387*253c8305SRuslan Bukin * Let the user know something else is being checked
1388*253c8305SRuslan Bukin * after announcing an error above.
1389*253c8305SRuslan Bukin */
1390*253c8305SRuslan Bukin TRACE(dev, ERROR, "checking crc7\n");
1391*253c8305SRuslan Bukin }
1392*253c8305SRuslan Bukin
1393*253c8305SRuslan Bukin crc7 = data[len - 1] >> 1;
1394*253c8305SRuslan Bukin computed_crc7 = update_crc7(CRC7_INITIAL, data, len - 1);
1395*253c8305SRuslan Bukin TRACE(dev, RESULT, "sent_crc7=0x%02x computed_crc7=0x%02x\n",
1396*253c8305SRuslan Bukin crc7, computed_crc7);
1397*253c8305SRuslan Bukin
1398*253c8305SRuslan Bukin if (computed_crc7 != crc7) {
1399*253c8305SRuslan Bukin TRACE(dev, ERROR,
1400*253c8305SRuslan Bukin "crc7 mismatch, should be 0x%02x, is 0x%02x\n",
1401*253c8305SRuslan Bukin crc7, computed_crc7);
1402*253c8305SRuslan Bukin
1403*253c8305SRuslan Bukin TRACE_EXIT(dev);
1404*253c8305SRuslan Bukin return (MMC_ERR_BADCRC);
1405*253c8305SRuslan Bukin }
1406*253c8305SRuslan Bukin }
1407*253c8305SRuslan Bukin
1408*253c8305SRuslan Bukin TRACE_EXIT(dev);
1409*253c8305SRuslan Bukin
1410*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1411*253c8305SRuslan Bukin }
1412*253c8305SRuslan Bukin
1413*253c8305SRuslan Bukin static unsigned int
mmcspi_send_stop(device_t dev,unsigned int retries)1414*253c8305SRuslan Bukin mmcspi_send_stop(device_t dev, unsigned int retries)
1415*253c8305SRuslan Bukin {
1416*253c8305SRuslan Bukin struct mmcspi_command stop;
1417*253c8305SRuslan Bukin struct mmc_command mmc_stop;
1418*253c8305SRuslan Bukin uint8_t stop_response;
1419*253c8305SRuslan Bukin unsigned int err;
1420*253c8305SRuslan Bukin int i;
1421*253c8305SRuslan Bukin
1422*253c8305SRuslan Bukin TRACE_ENTER(dev);
1423*253c8305SRuslan Bukin
1424*253c8305SRuslan Bukin memset(&mmc_stop, 0, sizeof(mmc_stop));
1425*253c8305SRuslan Bukin mmc_stop.opcode = MMC_STOP_TRANSMISSION;
1426*253c8305SRuslan Bukin mmc_stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
1427*253c8305SRuslan Bukin
1428*253c8305SRuslan Bukin err = mmcspi_set_up_command(dev, &stop, &mmc_stop);
1429*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1430*253c8305SRuslan Bukin TRACE_EXIT(dev);
1431*253c8305SRuslan Bukin return (err);
1432*253c8305SRuslan Bukin }
1433*253c8305SRuslan Bukin
1434*253c8305SRuslan Bukin /*
1435*253c8305SRuslan Bukin * Retry stop commands that fail due to bad crc here because having
1436*253c8305SRuslan Bukin * the caller retry the entire read/write command due to such a
1437*253c8305SRuslan Bukin * failure is pointlessly expensive.
1438*253c8305SRuslan Bukin */
1439*253c8305SRuslan Bukin for (i = 0; i <= retries; i++) {
1440*253c8305SRuslan Bukin TRACE(dev, ACTION, "sending stop message\n");
1441*253c8305SRuslan Bukin
1442*253c8305SRuslan Bukin err = mmcspi_send_cmd(dev, &stop, &stop_response);
1443*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1444*253c8305SRuslan Bukin TRACE_EXIT(dev);
1445*253c8305SRuslan Bukin return (err);
1446*253c8305SRuslan Bukin }
1447*253c8305SRuslan Bukin
1448*253c8305SRuslan Bukin TRACE(dev, RESULT, "stop response=0x%02x\n", stop_response);
1449*253c8305SRuslan Bukin
1450*253c8305SRuslan Bukin /* retry on crc error */
1451*253c8305SRuslan Bukin if (stop_response & stop.error_mask & MMCSPI_R1_CRC_ERR) {
1452*253c8305SRuslan Bukin continue;
1453*253c8305SRuslan Bukin }
1454*253c8305SRuslan Bukin }
1455*253c8305SRuslan Bukin
1456*253c8305SRuslan Bukin if (stop_response & stop.error_mask) {
1457*253c8305SRuslan Bukin TRACE_EXIT(dev);
1458*253c8305SRuslan Bukin
1459*253c8305SRuslan Bukin /*
1460*253c8305SRuslan Bukin * Don't return MMC_ERR_BADCRC here, even if
1461*253c8305SRuslan Bukin * MMCSPI_R1_CRC_ERR is set, because that would trigger the
1462*253c8305SRuslan Bukin * caller's retry-on-crc-error mechanism, effectively
1463*253c8305SRuslan Bukin * squaring the maximum number of retries of the stop
1464*253c8305SRuslan Bukin * command.
1465*253c8305SRuslan Bukin */
1466*253c8305SRuslan Bukin return (MMC_ERR_FAILED);
1467*253c8305SRuslan Bukin }
1468*253c8305SRuslan Bukin TRACE_EXIT(dev);
1469*253c8305SRuslan Bukin
1470*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1471*253c8305SRuslan Bukin }
1472*253c8305SRuslan Bukin
1473*253c8305SRuslan Bukin static unsigned int
mmcspi_read_phase(device_t dev,struct mmcspi_command * cmd)1474*253c8305SRuslan Bukin mmcspi_read_phase(device_t dev, struct mmcspi_command *cmd)
1475*253c8305SRuslan Bukin {
1476*253c8305SRuslan Bukin struct mmc_data *data;
1477*253c8305SRuslan Bukin unsigned int data_offset;
1478*253c8305SRuslan Bukin unsigned int num_blocks;
1479*253c8305SRuslan Bukin unsigned int len;
1480*253c8305SRuslan Bukin unsigned int err;
1481*253c8305SRuslan Bukin uint8_t *data8;
1482*253c8305SRuslan Bukin int i;
1483*253c8305SRuslan Bukin
1484*253c8305SRuslan Bukin TRACE_ENTER(dev);
1485*253c8305SRuslan Bukin
1486*253c8305SRuslan Bukin data = cmd->data;
1487*253c8305SRuslan Bukin data8 = (uint8_t *)data->data;
1488*253c8305SRuslan Bukin data_offset = 0;
1489*253c8305SRuslan Bukin
1490*253c8305SRuslan Bukin if (data->len < MMCSPI_DATA_BLOCK_LEN) {
1491*253c8305SRuslan Bukin num_blocks = 1;
1492*253c8305SRuslan Bukin len = data->len;
1493*253c8305SRuslan Bukin } else {
1494*253c8305SRuslan Bukin num_blocks = data->len / MMCSPI_DATA_BLOCK_LEN;
1495*253c8305SRuslan Bukin len = MMCSPI_DATA_BLOCK_LEN;
1496*253c8305SRuslan Bukin }
1497*253c8305SRuslan Bukin
1498*253c8305SRuslan Bukin for (i = 0; i < num_blocks; i++) {
1499*253c8305SRuslan Bukin /*
1500*253c8305SRuslan Bukin * The CID and CSD data blocks contain both a trailing crc-7
1501*253c8305SRuslan Bukin * inside the data block and the standard crc-16 following
1502*253c8305SRuslan Bukin * the data block, so both are checked when use_crc is true.
1503*253c8305SRuslan Bukin *
1504*253c8305SRuslan Bukin * When crc checking has been enabled via CMD59, some cards
1505*253c8305SRuslan Bukin * send CID and CSD data blocks with correct crc-7 values
1506*253c8305SRuslan Bukin * but incorrect crc-16 values. read_block will accept
1507*253c8305SRuslan Bukin * those responses as valid as long as the crc-7 is correct.
1508*253c8305SRuslan Bukin *
1509*253c8305SRuslan Bukin * Examples:
1510*253c8305SRuslan Bukin *
1511*253c8305SRuslan Bukin * Super Talent 1GB SDSC card, cid:
1512*253c8305SRuslan Bukin * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=02.2010
1513*253c8305SRuslan Bukin */
1514*253c8305SRuslan Bukin err = mmcspi_read_block(dev, &data8[data_offset], len,
1515*253c8305SRuslan Bukin cmd->use_crc, cmd->use_crc && ((MMC_SEND_CID == cmd->opcode)
1516*253c8305SRuslan Bukin || (MMC_SEND_CSD == cmd->opcode)));
1517*253c8305SRuslan Bukin
1518*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1519*253c8305SRuslan Bukin TRACE_EXIT(dev);
1520*253c8305SRuslan Bukin return (err);
1521*253c8305SRuslan Bukin }
1522*253c8305SRuslan Bukin
1523*253c8305SRuslan Bukin data_offset += MMCSPI_DATA_BLOCK_LEN;
1524*253c8305SRuslan Bukin }
1525*253c8305SRuslan Bukin
1526*253c8305SRuslan Bukin /* multi-block read commands require a stop */
1527*253c8305SRuslan Bukin if (num_blocks > 1) {
1528*253c8305SRuslan Bukin err = mmcspi_send_stop(dev, cmd->retries);
1529*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1530*253c8305SRuslan Bukin TRACE_EXIT(dev);
1531*253c8305SRuslan Bukin return (err);
1532*253c8305SRuslan Bukin }
1533*253c8305SRuslan Bukin }
1534*253c8305SRuslan Bukin
1535*253c8305SRuslan Bukin TRACE_EXIT(dev);
1536*253c8305SRuslan Bukin
1537*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1538*253c8305SRuslan Bukin }
1539*253c8305SRuslan Bukin
1540*253c8305SRuslan Bukin static unsigned int
mmcspi_write_block(device_t dev,uint8_t * data,unsigned int is_multi,unsigned char use_crc,uint8_t * status)1541*253c8305SRuslan Bukin mmcspi_write_block(device_t dev, uint8_t *data, unsigned int is_multi,
1542*253c8305SRuslan Bukin unsigned char use_crc, uint8_t *status)
1543*253c8305SRuslan Bukin {
1544*253c8305SRuslan Bukin uint8_t txbuf[max(MMCSPI_POLL_LEN, 2)];
1545*253c8305SRuslan Bukin uint8_t response_token;
1546*253c8305SRuslan Bukin unsigned int err;
1547*253c8305SRuslan Bukin uint16_t crc;
1548*253c8305SRuslan Bukin
1549*253c8305SRuslan Bukin TRACE_ENTER(dev);
1550*253c8305SRuslan Bukin
1551*253c8305SRuslan Bukin if (use_crc)
1552*253c8305SRuslan Bukin crc = update_crc16(CRC16_INITIAL, data, MMCSPI_DATA_BLOCK_LEN);
1553*253c8305SRuslan Bukin else
1554*253c8305SRuslan Bukin crc = 0;
1555*253c8305SRuslan Bukin
1556*253c8305SRuslan Bukin TRACE(dev, ACTION, "write block(512) crc=0x%04x\n", crc);
1557*253c8305SRuslan Bukin
1558*253c8305SRuslan Bukin txbuf[0] = is_multi ? MMCSPI_TOKEN_SB_WM : MMCSPI_TOKEN_SB;
1559*253c8305SRuslan Bukin err = mmcspi_do_spi_write(dev, txbuf, 1, data, MMCSPI_DATA_BLOCK_LEN);
1560*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1561*253c8305SRuslan Bukin TRACE_EXIT(dev);
1562*253c8305SRuslan Bukin return (err);
1563*253c8305SRuslan Bukin }
1564*253c8305SRuslan Bukin
1565*253c8305SRuslan Bukin txbuf[0] = crc >> 8;
1566*253c8305SRuslan Bukin txbuf[1] = crc & 0xff;
1567*253c8305SRuslan Bukin err = mmcspi_do_spi_write(dev, txbuf, 2, NULL, 0);
1568*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1569*253c8305SRuslan Bukin TRACE_EXIT(dev);
1570*253c8305SRuslan Bukin return (err);
1571*253c8305SRuslan Bukin }
1572*253c8305SRuslan Bukin
1573*253c8305SRuslan Bukin err = mmcspi_get_response_token(dev, MMCSPI_DR_MASK, MMCSPI_DR_VALUE,
1574*253c8305SRuslan Bukin 1, 1, &response_token);
1575*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1576*253c8305SRuslan Bukin TRACE_EXIT(dev);
1577*253c8305SRuslan Bukin return (err);
1578*253c8305SRuslan Bukin }
1579*253c8305SRuslan Bukin
1580*253c8305SRuslan Bukin *status = response_token & MMCSPI_DR_ERR_MASK;
1581*253c8305SRuslan Bukin
1582*253c8305SRuslan Bukin TRACE_EXIT(dev);
1583*253c8305SRuslan Bukin
1584*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1585*253c8305SRuslan Bukin }
1586*253c8305SRuslan Bukin
1587*253c8305SRuslan Bukin static unsigned int
mmcspi_write_phase(device_t dev,struct mmcspi_command * cmd)1588*253c8305SRuslan Bukin mmcspi_write_phase(device_t dev, struct mmcspi_command *cmd)
1589*253c8305SRuslan Bukin {
1590*253c8305SRuslan Bukin
1591*253c8305SRuslan Bukin struct mmc_data *data;
1592*253c8305SRuslan Bukin unsigned int data_offset;
1593*253c8305SRuslan Bukin unsigned int num_blocks;
1594*253c8305SRuslan Bukin unsigned int err;
1595*253c8305SRuslan Bukin uint8_t *data8;
1596*253c8305SRuslan Bukin uint8_t token[2];
1597*253c8305SRuslan Bukin uint8_t status;
1598*253c8305SRuslan Bukin int i;
1599*253c8305SRuslan Bukin
1600*253c8305SRuslan Bukin TRACE_ENTER(dev);
1601*253c8305SRuslan Bukin
1602*253c8305SRuslan Bukin data = cmd->data;
1603*253c8305SRuslan Bukin
1604*253c8305SRuslan Bukin data8 = (uint8_t *)data->data;
1605*253c8305SRuslan Bukin data_offset = 0;
1606*253c8305SRuslan Bukin num_blocks = data->len / MMCSPI_DATA_BLOCK_LEN;
1607*253c8305SRuslan Bukin for (i = 0; i < num_blocks; i++) {
1608*253c8305SRuslan Bukin err = mmcspi_write_block(dev, &data8[data_offset],
1609*253c8305SRuslan Bukin num_blocks > 1, cmd->use_crc, &status);
1610*253c8305SRuslan Bukin
1611*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1612*253c8305SRuslan Bukin TRACE_EXIT(dev);
1613*253c8305SRuslan Bukin return (err);
1614*253c8305SRuslan Bukin }
1615*253c8305SRuslan Bukin
1616*253c8305SRuslan Bukin if (MMCSPI_DR_ERR_NONE != status) {
1617*253c8305SRuslan Bukin if (num_blocks > 1) {
1618*253c8305SRuslan Bukin /*
1619*253c8305SRuslan Bukin * Ignore any failure reported for the stop
1620*253c8305SRuslan Bukin * command, as the return status for the
1621*253c8305SRuslan Bukin * write phase will be whatever error was
1622*253c8305SRuslan Bukin * indicated in the data respone token.
1623*253c8305SRuslan Bukin */
1624*253c8305SRuslan Bukin mmcspi_send_stop(dev, cmd->retries);
1625*253c8305SRuslan Bukin }
1626*253c8305SRuslan Bukin
1627*253c8305SRuslan Bukin /*
1628*253c8305SRuslan Bukin * A CRC error can't be ignored here, even if crc
1629*253c8305SRuslan Bukin * use is disabled, as there is no way to simply
1630*253c8305SRuslan Bukin * carry on when a data error token has been sent.
1631*253c8305SRuslan Bukin */
1632*253c8305SRuslan Bukin if (MMCSPI_DR_ERR_CRC == status) {
1633*253c8305SRuslan Bukin TRACE_EXIT(dev);
1634*253c8305SRuslan Bukin return (MMC_ERR_BADCRC);
1635*253c8305SRuslan Bukin } else {
1636*253c8305SRuslan Bukin TRACE_EXIT(dev);
1637*253c8305SRuslan Bukin return (MMC_ERR_FAILED);
1638*253c8305SRuslan Bukin }
1639*253c8305SRuslan Bukin }
1640*253c8305SRuslan Bukin
1641*253c8305SRuslan Bukin data_offset += MMCSPI_DATA_BLOCK_LEN;
1642*253c8305SRuslan Bukin }
1643*253c8305SRuslan Bukin
1644*253c8305SRuslan Bukin /* successful multi-block write commands require a stop token */
1645*253c8305SRuslan Bukin if (num_blocks > 1) {
1646*253c8305SRuslan Bukin TRACE(dev, ACTION, "Sending stop token\n");
1647*253c8305SRuslan Bukin
1648*253c8305SRuslan Bukin /*
1649*253c8305SRuslan Bukin * Most/all cards are a bit sluggish in assserting busy
1650*253c8305SRuslan Bukin * after receipt of the STOP_TRAN token. Clocking out an
1651*253c8305SRuslan Bukin * extra byte here provides a byte of dead time before
1652*253c8305SRuslan Bukin * looking for not busy, avoiding a premature not-busy
1653*253c8305SRuslan Bukin * determination with such cards.
1654*253c8305SRuslan Bukin */
1655*253c8305SRuslan Bukin token[0] = MMCSPI_TOKEN_ST;
1656*253c8305SRuslan Bukin token[1] = 0xff;
1657*253c8305SRuslan Bukin
1658*253c8305SRuslan Bukin err = mmcspi_do_spi_write(dev, token, sizeof(token), NULL, 0);
1659*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1660*253c8305SRuslan Bukin TRACE_EXIT(dev);
1661*253c8305SRuslan Bukin return (err);
1662*253c8305SRuslan Bukin }
1663*253c8305SRuslan Bukin
1664*253c8305SRuslan Bukin err = mmcspi_wait_for_not_busy(dev);
1665*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1666*253c8305SRuslan Bukin TRACE_EXIT(dev);
1667*253c8305SRuslan Bukin return (err);
1668*253c8305SRuslan Bukin }
1669*253c8305SRuslan Bukin }
1670*253c8305SRuslan Bukin
1671*253c8305SRuslan Bukin TRACE_EXIT(dev);
1672*253c8305SRuslan Bukin
1673*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1674*253c8305SRuslan Bukin }
1675*253c8305SRuslan Bukin
1676*253c8305SRuslan Bukin static unsigned int
mmcspi_translate_response(device_t dev,struct mmcspi_command * cmd,uint8_t * rspbuf)1677*253c8305SRuslan Bukin mmcspi_translate_response(device_t dev, struct mmcspi_command *cmd,
1678*253c8305SRuslan Bukin uint8_t *rspbuf)
1679*253c8305SRuslan Bukin {
1680*253c8305SRuslan Bukin struct mmc_command *mmc_cmd;
1681*253c8305SRuslan Bukin uint32_t mmc_rsp_type;
1682*253c8305SRuslan Bukin uint8_t *ldata;
1683*253c8305SRuslan Bukin
1684*253c8305SRuslan Bukin mmc_cmd = cmd->mmc_cmd;
1685*253c8305SRuslan Bukin mmc_rsp_type = cmd->mmc_rsp_type;
1686*253c8305SRuslan Bukin ldata = cmd->ldata.data;
1687*253c8305SRuslan Bukin
1688*253c8305SRuslan Bukin TRACE_ENTER(dev);
1689*253c8305SRuslan Bukin
1690*253c8305SRuslan Bukin TRACE(dev, ACTION, "translating SPI rsp %u to SD rsp %u\n",
1691*253c8305SRuslan Bukin cmd->rsp_type, mmc_rsp_type);
1692*253c8305SRuslan Bukin
1693*253c8305SRuslan Bukin if ((MMCSPI_TO_MMC_RSP_R1 == mmc_rsp_type) ||
1694*253c8305SRuslan Bukin (MMCSPI_TO_MMC_RSP_R1B == mmc_rsp_type)) {
1695*253c8305SRuslan Bukin
1696*253c8305SRuslan Bukin TRACE(dev, ACTION, "translating SPI-R1/2 to SD-R1\n");
1697*253c8305SRuslan Bukin
1698*253c8305SRuslan Bukin if ((MMCSPI_RSP_R1 == cmd->rsp_type) ||
1699*253c8305SRuslan Bukin (MMCSPI_RSP_R1B == cmd->rsp_type) ||
1700*253c8305SRuslan Bukin (MMCSPI_RSP_R2 == cmd->rsp_type)) {
1701*253c8305SRuslan Bukin mmc_cmd->resp[0] = 0;
1702*253c8305SRuslan Bukin
1703*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_PARAM_ERR)
1704*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_OUT_OF_RANGE;
1705*253c8305SRuslan Bukin
1706*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_ADDR_ERR)
1707*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_ADDRESS_ERROR;
1708*253c8305SRuslan Bukin
1709*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_ERASE_ERR)
1710*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_ERASE_SEQ_ERROR;
1711*253c8305SRuslan Bukin
1712*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_CRC_ERR)
1713*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_COM_CRC_ERROR;
1714*253c8305SRuslan Bukin
1715*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_ILL_CMD)
1716*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_ILLEGAL_COMMAND;
1717*253c8305SRuslan Bukin
1718*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_ERASE_RST)
1719*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_ERASE_RESET;
1720*253c8305SRuslan Bukin
1721*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_IDLE)
1722*253c8305SRuslan Bukin mmc_cmd->resp[0] |=
1723*253c8305SRuslan Bukin (uint32_t)R1_STATE_IDLE << 9;
1724*253c8305SRuslan Bukin else
1725*253c8305SRuslan Bukin mmc_cmd->resp[0] |=
1726*253c8305SRuslan Bukin (uint32_t)R1_STATE_READY << 9;
1727*253c8305SRuslan Bukin
1728*253c8305SRuslan Bukin /* When MMC_CMD_IS_APP is sent, emulate R1_APP_CMD
1729*253c8305SRuslan Bukin SD-bus status bit. */
1730*253c8305SRuslan Bukin if (!(cmd->flags & MMC_CMD_IS_APP) &&
1731*253c8305SRuslan Bukin (MMC_APP_CMD == cmd->opcode))
1732*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_APP_CMD;
1733*253c8305SRuslan Bukin
1734*253c8305SRuslan Bukin if (MMCSPI_RSP_R2 == cmd->rsp_type) {
1735*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_OOR_CSD_OW)
1736*253c8305SRuslan Bukin mmc_cmd->resp[0] |=
1737*253c8305SRuslan Bukin R1_OUT_OF_RANGE |
1738*253c8305SRuslan Bukin R1_CSD_OVERWRITE;
1739*253c8305SRuslan Bukin
1740*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_ERASE_PARAM)
1741*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_ERASE_PARAM;
1742*253c8305SRuslan Bukin
1743*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_WP_VIOLATE)
1744*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_WP_VIOLATION;
1745*253c8305SRuslan Bukin
1746*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_ECC_FAIL)
1747*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_CARD_ECC_FAILED;
1748*253c8305SRuslan Bukin
1749*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_CC_ERR)
1750*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_CC_ERROR;
1751*253c8305SRuslan Bukin
1752*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_ERR)
1753*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_ERROR;
1754*253c8305SRuslan Bukin
1755*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_WP_ER_LCK)
1756*253c8305SRuslan Bukin mmc_cmd->resp[0] |=
1757*253c8305SRuslan Bukin R1_LOCK_UNLOCK_FAILED |
1758*253c8305SRuslan Bukin R1_WP_ERASE_SKIP;
1759*253c8305SRuslan Bukin
1760*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_LOCKED)
1761*253c8305SRuslan Bukin mmc_cmd->resp[0] |= R1_CARD_IS_LOCKED;
1762*253c8305SRuslan Bukin
1763*253c8305SRuslan Bukin }
1764*253c8305SRuslan Bukin } else
1765*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1766*253c8305SRuslan Bukin
1767*253c8305SRuslan Bukin } else if (MMCSPI_TO_MMC_RSP_R2 == mmc_rsp_type) {
1768*253c8305SRuslan Bukin
1769*253c8305SRuslan Bukin if (16 == cmd->ldata.len) {
1770*253c8305SRuslan Bukin
1771*253c8305SRuslan Bukin TRACE(dev, ACTION, "translating SPI-R1/ldata(16) "
1772*253c8305SRuslan Bukin "to SD-R2\n");
1773*253c8305SRuslan Bukin
1774*253c8305SRuslan Bukin /* ldata contains bits 127:0 of the spi response */
1775*253c8305SRuslan Bukin
1776*253c8305SRuslan Bukin mmc_cmd->resp[0] =
1777*253c8305SRuslan Bukin (uint32_t)ldata[0] << 24 |
1778*253c8305SRuslan Bukin (uint32_t)ldata[1] << 16 |
1779*253c8305SRuslan Bukin (uint32_t)ldata[2] << 8 |
1780*253c8305SRuslan Bukin (uint32_t)ldata[3];
1781*253c8305SRuslan Bukin
1782*253c8305SRuslan Bukin mmc_cmd->resp[1] =
1783*253c8305SRuslan Bukin (uint32_t)ldata[4] << 24 |
1784*253c8305SRuslan Bukin (uint32_t)ldata[5] << 16 |
1785*253c8305SRuslan Bukin (uint32_t)ldata[6] << 8 |
1786*253c8305SRuslan Bukin (uint32_t)ldata[7];
1787*253c8305SRuslan Bukin
1788*253c8305SRuslan Bukin mmc_cmd->resp[2] =
1789*253c8305SRuslan Bukin (uint32_t)ldata[8] << 24 |
1790*253c8305SRuslan Bukin (uint32_t)ldata[9] << 16 |
1791*253c8305SRuslan Bukin (uint32_t)ldata[10] << 8 |
1792*253c8305SRuslan Bukin (uint32_t)ldata[11];
1793*253c8305SRuslan Bukin
1794*253c8305SRuslan Bukin mmc_cmd->resp[3] =
1795*253c8305SRuslan Bukin (uint32_t)ldata[12] << 24 |
1796*253c8305SRuslan Bukin (uint32_t)ldata[13] << 16 |
1797*253c8305SRuslan Bukin (uint32_t)ldata[14] << 8;
1798*253c8305SRuslan Bukin
1799*253c8305SRuslan Bukin } else
1800*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1801*253c8305SRuslan Bukin
1802*253c8305SRuslan Bukin } else if (MMCSPI_TO_MMC_RSP_R3 == mmc_rsp_type) {
1803*253c8305SRuslan Bukin
1804*253c8305SRuslan Bukin if (MMCSPI_RSP_R3 == cmd->rsp_type) {
1805*253c8305SRuslan Bukin
1806*253c8305SRuslan Bukin TRACE(dev, ACTION, "translating SPI-R3 to SD-R3\n");
1807*253c8305SRuslan Bukin
1808*253c8305SRuslan Bukin /* rspbuf contains a 40-bit spi-R3 from the
1809*253c8305SRuslan Bukin MMCSPI_READ_OCR response, of which bits 31:0 are
1810*253c8305SRuslan Bukin the OCR value */
1811*253c8305SRuslan Bukin
1812*253c8305SRuslan Bukin /* spi response bits 31:0 mapped to
1813*253c8305SRuslan Bukin sdhc register bits 31:0 */
1814*253c8305SRuslan Bukin mmc_cmd->resp[0] =
1815*253c8305SRuslan Bukin (uint32_t)rspbuf[1] << 24 |
1816*253c8305SRuslan Bukin (uint32_t)rspbuf[2] << 16 |
1817*253c8305SRuslan Bukin (uint32_t)rspbuf[3] << 8 |
1818*253c8305SRuslan Bukin (uint32_t)rspbuf[4];
1819*253c8305SRuslan Bukin
1820*253c8305SRuslan Bukin /* Clear card busy bit (indicating busy) if the
1821*253c8305SRuslan Bukin SPI-R1 idle bit is set. */
1822*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_IDLE) {
1823*253c8305SRuslan Bukin mmc_cmd->resp[0] &= ~MMC_OCR_CARD_BUSY;
1824*253c8305SRuslan Bukin } else {
1825*253c8305SRuslan Bukin mmc_cmd->resp[0] |= MMC_OCR_CARD_BUSY;
1826*253c8305SRuslan Bukin }
1827*253c8305SRuslan Bukin
1828*253c8305SRuslan Bukin TRACE(dev, DETAILS, "ocr=0x%08x\n", mmc_cmd->resp[0]);
1829*253c8305SRuslan Bukin } else
1830*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1831*253c8305SRuslan Bukin
1832*253c8305SRuslan Bukin } else if (MMCSPI_TO_MMC_RSP_R6 == mmc_rsp_type) {
1833*253c8305SRuslan Bukin if (MMCSPI_RSP_R2 == cmd->rsp_type) {
1834*253c8305SRuslan Bukin
1835*253c8305SRuslan Bukin TRACE(dev, ACTION, "translating SPI-R2 to SD-R6\n");
1836*253c8305SRuslan Bukin
1837*253c8305SRuslan Bukin /* rca returned will always be zero */
1838*253c8305SRuslan Bukin mmc_cmd->resp[0] = 0;
1839*253c8305SRuslan Bukin
1840*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_CRC_ERR)
1841*253c8305SRuslan Bukin mmc_cmd->resp[0] |= 0x8000;
1842*253c8305SRuslan Bukin
1843*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_ILL_CMD)
1844*253c8305SRuslan Bukin mmc_cmd->resp[0] |= 0x4000;
1845*253c8305SRuslan Bukin
1846*253c8305SRuslan Bukin if (rspbuf[1] & MMCSPI_R2_ERR)
1847*253c8305SRuslan Bukin mmc_cmd->resp[0] |= 0x2000;
1848*253c8305SRuslan Bukin
1849*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_IDLE)
1850*253c8305SRuslan Bukin mmc_cmd->resp[0] |=
1851*253c8305SRuslan Bukin (uint32_t)R1_STATE_IDLE << 9;
1852*253c8305SRuslan Bukin else
1853*253c8305SRuslan Bukin mmc_cmd->resp[0] |=
1854*253c8305SRuslan Bukin (uint32_t)R1_STATE_READY << 9;
1855*253c8305SRuslan Bukin } else
1856*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1857*253c8305SRuslan Bukin
1858*253c8305SRuslan Bukin } else if (MMCSPI_TO_MMC_RSP_R7 == mmc_rsp_type) {
1859*253c8305SRuslan Bukin if (MMCSPI_RSP_R7 == cmd->rsp_type) {
1860*253c8305SRuslan Bukin
1861*253c8305SRuslan Bukin TRACE(dev, ACTION, "translating SPI-R7 to SD-R7\n");
1862*253c8305SRuslan Bukin
1863*253c8305SRuslan Bukin /* rsp buf contains a 40-bit spi-R7, of which bits
1864*253c8305SRuslan Bukin 11:0 need to be transferred */
1865*253c8305SRuslan Bukin
1866*253c8305SRuslan Bukin /* spi response bits 11:0 mapped to
1867*253c8305SRuslan Bukin sdhc register bits 11:0 */
1868*253c8305SRuslan Bukin mmc_cmd->resp[0] =
1869*253c8305SRuslan Bukin (uint32_t)(rspbuf[3] & 0xf) << 8 |
1870*253c8305SRuslan Bukin (uint32_t)rspbuf[4];
1871*253c8305SRuslan Bukin } else
1872*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1873*253c8305SRuslan Bukin
1874*253c8305SRuslan Bukin } else if (MMCSPI_TO_MMC_RSP_NONE != mmc_rsp_type)
1875*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
1876*253c8305SRuslan Bukin
1877*253c8305SRuslan Bukin TRACE_EXIT(dev);
1878*253c8305SRuslan Bukin
1879*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1880*253c8305SRuslan Bukin }
1881*253c8305SRuslan Bukin
1882*253c8305SRuslan Bukin static unsigned int
mmcspi_get_ocr(device_t dev,uint8_t * ocrbuf)1883*253c8305SRuslan Bukin mmcspi_get_ocr(device_t dev, uint8_t *ocrbuf)
1884*253c8305SRuslan Bukin {
1885*253c8305SRuslan Bukin struct mmc_command mmc_cmd;
1886*253c8305SRuslan Bukin struct mmcspi_command cmd;
1887*253c8305SRuslan Bukin unsigned int err;
1888*253c8305SRuslan Bukin uint8_t r1_status;
1889*253c8305SRuslan Bukin uint8_t rspbuf[MMCSPI_MAX_RSP_LEN];
1890*253c8305SRuslan Bukin
1891*253c8305SRuslan Bukin TRACE_ENTER(dev);
1892*253c8305SRuslan Bukin
1893*253c8305SRuslan Bukin memset(&mmc_cmd, 0, sizeof(struct mmc_command));
1894*253c8305SRuslan Bukin mmc_cmd.opcode = MMCSPI_READ_OCR;
1895*253c8305SRuslan Bukin mmc_cmd.flags = MMC_RSP_R3 | MMC_CMD_AC;
1896*253c8305SRuslan Bukin
1897*253c8305SRuslan Bukin err = mmcspi_set_up_command(dev, &cmd, &mmc_cmd);
1898*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1899*253c8305SRuslan Bukin TRACE_EXIT(dev);
1900*253c8305SRuslan Bukin return (err);
1901*253c8305SRuslan Bukin }
1902*253c8305SRuslan Bukin
1903*253c8305SRuslan Bukin err = mmcspi_send_cmd(dev, &cmd, rspbuf);
1904*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1905*253c8305SRuslan Bukin TRACE_EXIT(dev);
1906*253c8305SRuslan Bukin return (err);
1907*253c8305SRuslan Bukin }
1908*253c8305SRuslan Bukin
1909*253c8305SRuslan Bukin r1_status = rspbuf[0] & cmd.error_mask;
1910*253c8305SRuslan Bukin if (r1_status) {
1911*253c8305SRuslan Bukin if (r1_status & MMCSPI_R1_CRC_ERR)
1912*253c8305SRuslan Bukin err = MMC_ERR_BADCRC;
1913*253c8305SRuslan Bukin else
1914*253c8305SRuslan Bukin err = MMC_ERR_INVALID;
1915*253c8305SRuslan Bukin
1916*253c8305SRuslan Bukin TRACE_EXIT(dev);
1917*253c8305SRuslan Bukin return (err);
1918*253c8305SRuslan Bukin }
1919*253c8305SRuslan Bukin
1920*253c8305SRuslan Bukin memcpy(ocrbuf, &rspbuf[1], MMCSPI_OCR_LEN);
1921*253c8305SRuslan Bukin
1922*253c8305SRuslan Bukin TRACE_EXIT(dev);
1923*253c8305SRuslan Bukin
1924*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1925*253c8305SRuslan Bukin }
1926*253c8305SRuslan Bukin
1927*253c8305SRuslan Bukin static unsigned int
mmcspi_set_crc_on_off(device_t dev,unsigned int crc_on)1928*253c8305SRuslan Bukin mmcspi_set_crc_on_off(device_t dev, unsigned int crc_on)
1929*253c8305SRuslan Bukin {
1930*253c8305SRuslan Bukin struct mmc_command mmc_cmd;
1931*253c8305SRuslan Bukin struct mmcspi_command cmd;
1932*253c8305SRuslan Bukin unsigned int err;
1933*253c8305SRuslan Bukin uint8_t r1_status;
1934*253c8305SRuslan Bukin uint8_t rspbuf[MMCSPI_MAX_RSP_LEN];
1935*253c8305SRuslan Bukin
1936*253c8305SRuslan Bukin TRACE_ENTER(dev);
1937*253c8305SRuslan Bukin
1938*253c8305SRuslan Bukin memset(&mmc_cmd, 0, sizeof(struct mmc_command));
1939*253c8305SRuslan Bukin mmc_cmd.opcode = MMCSPI_CRC_ON_OFF;
1940*253c8305SRuslan Bukin mmc_cmd.arg = crc_on ? 1 : 0;
1941*253c8305SRuslan Bukin mmc_cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
1942*253c8305SRuslan Bukin
1943*253c8305SRuslan Bukin err = mmcspi_set_up_command(dev, &cmd, &mmc_cmd);
1944*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1945*253c8305SRuslan Bukin TRACE_EXIT(dev);
1946*253c8305SRuslan Bukin return (err);
1947*253c8305SRuslan Bukin }
1948*253c8305SRuslan Bukin
1949*253c8305SRuslan Bukin err = mmcspi_send_cmd(dev, &cmd, rspbuf);
1950*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1951*253c8305SRuslan Bukin TRACE_EXIT(dev);
1952*253c8305SRuslan Bukin return (err);
1953*253c8305SRuslan Bukin }
1954*253c8305SRuslan Bukin
1955*253c8305SRuslan Bukin r1_status = rspbuf[0] & cmd.error_mask;
1956*253c8305SRuslan Bukin if (r1_status) {
1957*253c8305SRuslan Bukin if (r1_status & MMCSPI_R1_CRC_ERR)
1958*253c8305SRuslan Bukin err = MMC_ERR_BADCRC;
1959*253c8305SRuslan Bukin else
1960*253c8305SRuslan Bukin err = MMC_ERR_INVALID;
1961*253c8305SRuslan Bukin
1962*253c8305SRuslan Bukin TRACE_EXIT(dev);
1963*253c8305SRuslan Bukin return (err);
1964*253c8305SRuslan Bukin }
1965*253c8305SRuslan Bukin
1966*253c8305SRuslan Bukin TRACE_EXIT(dev);
1967*253c8305SRuslan Bukin return (MMC_ERR_NONE);
1968*253c8305SRuslan Bukin }
1969*253c8305SRuslan Bukin
1970*253c8305SRuslan Bukin static unsigned int
mmcspi_update_crc_setting(device_t dev,unsigned int crc_on)1971*253c8305SRuslan Bukin mmcspi_update_crc_setting(device_t dev, unsigned int crc_on)
1972*253c8305SRuslan Bukin {
1973*253c8305SRuslan Bukin struct mmcspi_softc *sc;
1974*253c8305SRuslan Bukin struct mmcspi_slot *slot;
1975*253c8305SRuslan Bukin unsigned int err;
1976*253c8305SRuslan Bukin int i;
1977*253c8305SRuslan Bukin
1978*253c8305SRuslan Bukin TRACE_ENTER(dev);
1979*253c8305SRuslan Bukin
1980*253c8305SRuslan Bukin sc = device_get_softc(dev);
1981*253c8305SRuslan Bukin slot = &sc->slot;
1982*253c8305SRuslan Bukin
1983*253c8305SRuslan Bukin for (i = 0; i <= MMCSPI_RETRIES; i++) {
1984*253c8305SRuslan Bukin err = mmcspi_set_crc_on_off(dev, crc_on);
1985*253c8305SRuslan Bukin if (MMC_ERR_BADCRC != err)
1986*253c8305SRuslan Bukin break;
1987*253c8305SRuslan Bukin }
1988*253c8305SRuslan Bukin
1989*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
1990*253c8305SRuslan Bukin TRACE_EXIT(dev);
1991*253c8305SRuslan Bukin return (err);
1992*253c8305SRuslan Bukin }
1993*253c8305SRuslan Bukin
1994*253c8305SRuslan Bukin if (crc_on)
1995*253c8305SRuslan Bukin slot->crc_enabled = 1;
1996*253c8305SRuslan Bukin else
1997*253c8305SRuslan Bukin slot->crc_enabled = 0;
1998*253c8305SRuslan Bukin
1999*253c8305SRuslan Bukin TRACE_EXIT(dev);
2000*253c8305SRuslan Bukin
2001*253c8305SRuslan Bukin return (MMC_ERR_NONE);
2002*253c8305SRuslan Bukin }
2003*253c8305SRuslan Bukin
2004*253c8305SRuslan Bukin static int
mmcspi_request(device_t brdev,device_t reqdev,struct mmc_request * req)2005*253c8305SRuslan Bukin mmcspi_request(device_t brdev, device_t reqdev, struct mmc_request *req)
2006*253c8305SRuslan Bukin {
2007*253c8305SRuslan Bukin TRACE_ENTER(brdev);
2008*253c8305SRuslan Bukin
2009*253c8305SRuslan Bukin struct mmcspi_softc *sc = device_get_softc(brdev);
2010*253c8305SRuslan Bukin struct mmcspi_slot *slot = &sc->slot;
2011*253c8305SRuslan Bukin struct mmcspi_command cmd;
2012*253c8305SRuslan Bukin struct mmc_command *mmc_cmd = req->cmd;
2013*253c8305SRuslan Bukin struct mmc_data *data;
2014*253c8305SRuslan Bukin unsigned int err;
2015*253c8305SRuslan Bukin unsigned int use_crc_sample;
2016*253c8305SRuslan Bukin int i, j;
2017*253c8305SRuslan Bukin uint32_t opcode;
2018*253c8305SRuslan Bukin uint32_t flags;
2019*253c8305SRuslan Bukin uint32_t last_opcode;
2020*253c8305SRuslan Bukin uint32_t last_flags;
2021*253c8305SRuslan Bukin uint8_t rspbuf[MMCSPI_MAX_RSP_LEN];
2022*253c8305SRuslan Bukin
2023*253c8305SRuslan Bukin #define IS_CMD(code, cmd, flags) \
2024*253c8305SRuslan Bukin (!((flags) & MMC_CMD_IS_APP) && ((code) == (cmd)))
2025*253c8305SRuslan Bukin #define IS_ACMD(code, cmd, flags) \
2026*253c8305SRuslan Bukin (((flags) & MMC_CMD_IS_APP) && ((code) == (cmd)))
2027*253c8305SRuslan Bukin
2028*253c8305SRuslan Bukin if (power_on != slot->host.ios.power_mode)
2029*253c8305SRuslan Bukin return (MMC_ERR_INVALID);
2030*253c8305SRuslan Bukin
2031*253c8305SRuslan Bukin /*
2032*253c8305SRuslan Bukin * Sample use_crc sysctl and adjust card setting if required and
2033*253c8305SRuslan Bukin * appropriate.
2034*253c8305SRuslan Bukin */
2035*253c8305SRuslan Bukin use_crc_sample = sc->use_crc;
2036*253c8305SRuslan Bukin if (slot->crc_init_done &&
2037*253c8305SRuslan Bukin (use_crc_sample != slot->crc_enabled)) {
2038*253c8305SRuslan Bukin err = mmcspi_update_crc_setting(brdev, use_crc_sample);
2039*253c8305SRuslan Bukin if (MMC_ERR_NONE != err)
2040*253c8305SRuslan Bukin goto out;
2041*253c8305SRuslan Bukin slot->crc_init_done = 1;
2042*253c8305SRuslan Bukin }
2043*253c8305SRuslan Bukin
2044*253c8305SRuslan Bukin err = mmcspi_set_up_command(brdev, &cmd, mmc_cmd);
2045*253c8305SRuslan Bukin if (MMC_ERR_NONE != err)
2046*253c8305SRuslan Bukin goto out;
2047*253c8305SRuslan Bukin
2048*253c8305SRuslan Bukin opcode = cmd.opcode;
2049*253c8305SRuslan Bukin flags = cmd.flags;
2050*253c8305SRuslan Bukin data = cmd.data;
2051*253c8305SRuslan Bukin
2052*253c8305SRuslan Bukin last_opcode = slot->last_opcode;
2053*253c8305SRuslan Bukin last_flags = slot->last_flags;
2054*253c8305SRuslan Bukin
2055*253c8305SRuslan Bukin /* enforce restrictions on request parameters */
2056*253c8305SRuslan Bukin if (data) {
2057*253c8305SRuslan Bukin /*
2058*253c8305SRuslan Bukin * All writes must be a multiple of the block length. All
2059*253c8305SRuslan Bukin * reads greater than the block length must be a multiple of
2060*253c8305SRuslan Bukin * the block length.
2061*253c8305SRuslan Bukin */
2062*253c8305SRuslan Bukin if ((data->len % MMCSPI_DATA_BLOCK_LEN) &&
2063*253c8305SRuslan Bukin !((data->flags & MMC_DATA_READ) &&
2064*253c8305SRuslan Bukin (data->len < MMCSPI_DATA_BLOCK_LEN))) {
2065*253c8305SRuslan Bukin TRACE(brdev, ERROR,
2066*253c8305SRuslan Bukin "requested data phase not a multiple of %u\n",
2067*253c8305SRuslan Bukin MMCSPI_DATA_BLOCK_LEN);
2068*253c8305SRuslan Bukin err = MMC_ERR_INVALID;
2069*253c8305SRuslan Bukin goto out;
2070*253c8305SRuslan Bukin }
2071*253c8305SRuslan Bukin
2072*253c8305SRuslan Bukin if (((data->flags & MMC_DATA_READ) &&
2073*253c8305SRuslan Bukin (data->flags & MMC_DATA_WRITE)) ||
2074*253c8305SRuslan Bukin (data->flags & MMC_DATA_STREAM)) {
2075*253c8305SRuslan Bukin TRACE(brdev, ERROR, "illegal data phase flags 0x%02x\n",
2076*253c8305SRuslan Bukin data->flags);
2077*253c8305SRuslan Bukin err = MMC_ERR_INVALID;
2078*253c8305SRuslan Bukin goto out;
2079*253c8305SRuslan Bukin }
2080*253c8305SRuslan Bukin }
2081*253c8305SRuslan Bukin
2082*253c8305SRuslan Bukin for (i = 0; i <= cmd.retries; i++) {
2083*253c8305SRuslan Bukin /*
2084*253c8305SRuslan Bukin * On the next command following a CMD8, collect the OCR and
2085*253c8305SRuslan Bukin * save it off for use in the next ACMD41.
2086*253c8305SRuslan Bukin */
2087*253c8305SRuslan Bukin if (IS_CMD(SD_SEND_IF_COND, last_opcode, last_flags)) {
2088*253c8305SRuslan Bukin err = mmcspi_get_ocr(brdev, slot->last_ocr);
2089*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
2090*253c8305SRuslan Bukin if (MMC_ERR_BADCRC == err)
2091*253c8305SRuslan Bukin continue;
2092*253c8305SRuslan Bukin goto out;
2093*253c8305SRuslan Bukin }
2094*253c8305SRuslan Bukin }
2095*253c8305SRuslan Bukin
2096*253c8305SRuslan Bukin err = mmcspi_send_cmd(brdev, &cmd, rspbuf);
2097*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
2098*253c8305SRuslan Bukin if (MMC_ERR_BADCRC == err)
2099*253c8305SRuslan Bukin continue;
2100*253c8305SRuslan Bukin goto out;
2101*253c8305SRuslan Bukin }
2102*253c8305SRuslan Bukin
2103*253c8305SRuslan Bukin if (data) {
2104*253c8305SRuslan Bukin if (data->flags & MMC_DATA_READ)
2105*253c8305SRuslan Bukin err = mmcspi_read_phase(brdev, &cmd);
2106*253c8305SRuslan Bukin else /* MMC_DATA_WRITE */
2107*253c8305SRuslan Bukin err = mmcspi_write_phase(brdev, &cmd);
2108*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
2109*253c8305SRuslan Bukin if (MMC_ERR_BADCRC == err)
2110*253c8305SRuslan Bukin continue;
2111*253c8305SRuslan Bukin goto out;
2112*253c8305SRuslan Bukin }
2113*253c8305SRuslan Bukin }
2114*253c8305SRuslan Bukin break;
2115*253c8305SRuslan Bukin }
2116*253c8305SRuslan Bukin
2117*253c8305SRuslan Bukin if (MMC_ERR_NONE != err)
2118*253c8305SRuslan Bukin goto out;
2119*253c8305SRuslan Bukin
2120*253c8305SRuslan Bukin /*
2121*253c8305SRuslan Bukin * If this was an ACMD_SD_SEND_OP_COND or MMC_SEND_OP_COND, we need
2122*253c8305SRuslan Bukin * to return an OCR value in the result. If the response from the
2123*253c8305SRuslan Bukin * card indicates it is still in the IDLE state, supply the OCR
2124*253c8305SRuslan Bukin * value obtained after the last CMD8, otherwise issue an
2125*253c8305SRuslan Bukin * MMCSPI_READ_OCR to get the current value, which will have a valid
2126*253c8305SRuslan Bukin * CCS bit.
2127*253c8305SRuslan Bukin *
2128*253c8305SRuslan Bukin * This dance is required under this emulation approach because the
2129*253c8305SRuslan Bukin * spec stipulates that no other commands should be sent while
2130*253c8305SRuslan Bukin * ACMD_SD_SEND_OP_COND is being used to poll for the end of the
2131*253c8305SRuslan Bukin * IDLE state, and some cards do enforce that requirement.
2132*253c8305SRuslan Bukin */
2133*253c8305SRuslan Bukin if (IS_ACMD(ACMD_SD_SEND_OP_COND, opcode, flags) ||
2134*253c8305SRuslan Bukin IS_CMD(MMC_SEND_OP_COND, opcode, flags)) {
2135*253c8305SRuslan Bukin
2136*253c8305SRuslan Bukin if (rspbuf[0] & MMCSPI_R1_IDLE)
2137*253c8305SRuslan Bukin memcpy(&rspbuf[1], slot->last_ocr, MMCSPI_OCR_LEN);
2138*253c8305SRuslan Bukin else {
2139*253c8305SRuslan Bukin
2140*253c8305SRuslan Bukin /*
2141*253c8305SRuslan Bukin * Some cards won't accept the MMCSPI_CRC_ON_OFF
2142*253c8305SRuslan Bukin * command until initialization is complete.
2143*253c8305SRuslan Bukin *
2144*253c8305SRuslan Bukin * Examples:
2145*253c8305SRuslan Bukin *
2146*253c8305SRuslan Bukin * Super Talent 1GB SDSC card, cid:
2147*253c8305SRuslan Bukin * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=02.2010
2148*253c8305SRuslan Bukin */
2149*253c8305SRuslan Bukin if (!slot->crc_init_done) {
2150*253c8305SRuslan Bukin err = mmcspi_update_crc_setting(brdev,
2151*253c8305SRuslan Bukin sc->use_crc);
2152*253c8305SRuslan Bukin if (MMC_ERR_NONE != err)
2153*253c8305SRuslan Bukin goto out;
2154*253c8305SRuslan Bukin slot->crc_init_done = 1;
2155*253c8305SRuslan Bukin }
2156*253c8305SRuslan Bukin
2157*253c8305SRuslan Bukin for (j = 0; j <= cmd.retries; j++) {
2158*253c8305SRuslan Bukin /*
2159*253c8305SRuslan Bukin * Note that in this case, we pass on the R1
2160*253c8305SRuslan Bukin * from READ_OCR.
2161*253c8305SRuslan Bukin */
2162*253c8305SRuslan Bukin err = mmcspi_get_ocr(brdev, rspbuf);
2163*253c8305SRuslan Bukin if (MMC_ERR_NONE != err) {
2164*253c8305SRuslan Bukin if (MMC_ERR_BADCRC == err)
2165*253c8305SRuslan Bukin continue;
2166*253c8305SRuslan Bukin
2167*253c8305SRuslan Bukin goto out;
2168*253c8305SRuslan Bukin }
2169*253c8305SRuslan Bukin
2170*253c8305SRuslan Bukin }
2171*253c8305SRuslan Bukin
2172*253c8305SRuslan Bukin if (MMC_ERR_NONE != err)
2173*253c8305SRuslan Bukin goto out;
2174*253c8305SRuslan Bukin
2175*253c8305SRuslan Bukin }
2176*253c8305SRuslan Bukin
2177*253c8305SRuslan Bukin /* adjust the SPI response type to include the OCR */
2178*253c8305SRuslan Bukin cmd.rsp_type = MMCSPI_RSP_R3;
2179*253c8305SRuslan Bukin }
2180*253c8305SRuslan Bukin
2181*253c8305SRuslan Bukin err = mmcspi_translate_response(brdev, &cmd, rspbuf);
2182*253c8305SRuslan Bukin if (MMC_ERR_NONE != err)
2183*253c8305SRuslan Bukin goto out;
2184*253c8305SRuslan Bukin
2185*253c8305SRuslan Bukin out:
2186*253c8305SRuslan Bukin slot->last_opcode = mmc_cmd->opcode;
2187*253c8305SRuslan Bukin slot->last_flags = mmc_cmd->flags;
2188*253c8305SRuslan Bukin
2189*253c8305SRuslan Bukin mmc_cmd->error = err;
2190*253c8305SRuslan Bukin
2191*253c8305SRuslan Bukin if (req->done)
2192*253c8305SRuslan Bukin req->done(req);
2193*253c8305SRuslan Bukin
2194*253c8305SRuslan Bukin TRACE_EXIT(brdev);
2195*253c8305SRuslan Bukin
2196*253c8305SRuslan Bukin return (err);
2197*253c8305SRuslan Bukin }
2198*253c8305SRuslan Bukin
2199*253c8305SRuslan Bukin static int
mmcspi_get_ro(device_t brdev,device_t reqdev)2200*253c8305SRuslan Bukin mmcspi_get_ro(device_t brdev, device_t reqdev)
2201*253c8305SRuslan Bukin {
2202*253c8305SRuslan Bukin
2203*253c8305SRuslan Bukin TRACE_ENTER(brdev);
2204*253c8305SRuslan Bukin TRACE_EXIT(brdev);
2205*253c8305SRuslan Bukin
2206*253c8305SRuslan Bukin /* XXX no support for this currently */
2207*253c8305SRuslan Bukin return (0);
2208*253c8305SRuslan Bukin }
2209*253c8305SRuslan Bukin
2210*253c8305SRuslan Bukin static int
mmcspi_acquire_host(device_t brdev,device_t reqdev)2211*253c8305SRuslan Bukin mmcspi_acquire_host(device_t brdev, device_t reqdev)
2212*253c8305SRuslan Bukin {
2213*253c8305SRuslan Bukin struct mmcspi_slot *slot;
2214*253c8305SRuslan Bukin int err;
2215*253c8305SRuslan Bukin
2216*253c8305SRuslan Bukin TRACE_ENTER(brdev);
2217*253c8305SRuslan Bukin err = 0;
2218*253c8305SRuslan Bukin
2219*253c8305SRuslan Bukin slot = device_get_ivars(reqdev);
2220*253c8305SRuslan Bukin
2221*253c8305SRuslan Bukin MMCSPI_LOCK_SLOT(slot);
2222*253c8305SRuslan Bukin while (slot->bus_busy)
2223*253c8305SRuslan Bukin mtx_sleep(slot, &slot->mtx, 0, "mmcspiah", 0);
2224*253c8305SRuslan Bukin slot->bus_busy++;
2225*253c8305SRuslan Bukin MMCSPI_UNLOCK_SLOT(slot);
2226*253c8305SRuslan Bukin
2227*253c8305SRuslan Bukin TRACE_EXIT(brdev);
2228*253c8305SRuslan Bukin
2229*253c8305SRuslan Bukin return (err);
2230*253c8305SRuslan Bukin }
2231*253c8305SRuslan Bukin
2232*253c8305SRuslan Bukin static int
mmcspi_release_host(device_t brdev,device_t reqdev)2233*253c8305SRuslan Bukin mmcspi_release_host(device_t brdev, device_t reqdev)
2234*253c8305SRuslan Bukin {
2235*253c8305SRuslan Bukin struct mmcspi_slot *slot;
2236*253c8305SRuslan Bukin
2237*253c8305SRuslan Bukin TRACE_ENTER(brdev);
2238*253c8305SRuslan Bukin
2239*253c8305SRuslan Bukin slot = device_get_ivars(reqdev);
2240*253c8305SRuslan Bukin
2241*253c8305SRuslan Bukin MMCSPI_LOCK_SLOT(slot);
2242*253c8305SRuslan Bukin slot->bus_busy--;
2243*253c8305SRuslan Bukin MMCSPI_UNLOCK_SLOT(slot);
2244*253c8305SRuslan Bukin
2245*253c8305SRuslan Bukin wakeup(slot);
2246*253c8305SRuslan Bukin
2247*253c8305SRuslan Bukin TRACE_EXIT(brdev);
2248*253c8305SRuslan Bukin
2249*253c8305SRuslan Bukin return (0);
2250*253c8305SRuslan Bukin }
2251*253c8305SRuslan Bukin
2252*253c8305SRuslan Bukin static int
mmcspi_modevent_handler(module_t mod,int what,void * arg)2253*253c8305SRuslan Bukin mmcspi_modevent_handler(module_t mod, int what, void *arg)
2254*253c8305SRuslan Bukin {
2255*253c8305SRuslan Bukin
2256*253c8305SRuslan Bukin switch (what) {
2257*253c8305SRuslan Bukin case MOD_LOAD:
2258*253c8305SRuslan Bukin init_crc7tab();
2259*253c8305SRuslan Bukin init_crc16tab();
2260*253c8305SRuslan Bukin memset(onesbuf, 0xff, sizeof(onesbuf));
2261*253c8305SRuslan Bukin break;
2262*253c8305SRuslan Bukin default:
2263*253c8305SRuslan Bukin return (EOPNOTSUPP);
2264*253c8305SRuslan Bukin }
2265*253c8305SRuslan Bukin
2266*253c8305SRuslan Bukin return (0);
2267*253c8305SRuslan Bukin }
2268*253c8305SRuslan Bukin
2269*253c8305SRuslan Bukin static int
mmcspi_switch_vccq(device_t bus,device_t child)2270*253c8305SRuslan Bukin mmcspi_switch_vccq(device_t bus, device_t child)
2271*253c8305SRuslan Bukin {
2272*253c8305SRuslan Bukin
2273*253c8305SRuslan Bukin return (0);
2274*253c8305SRuslan Bukin }
2275*253c8305SRuslan Bukin
2276*253c8305SRuslan Bukin #if defined(MMCSPI_ENABLE_DEBUG_FUNCS)
2277*253c8305SRuslan Bukin static void
mmcspi_dump_data(device_t dev,const char * label,uint8_t * data,unsigned int len)2278*253c8305SRuslan Bukin mmcspi_dump_data(device_t dev, const char *label, uint8_t *data,
2279*253c8305SRuslan Bukin unsigned int len)
2280*253c8305SRuslan Bukin {
2281*253c8305SRuslan Bukin unsigned int i, j;
2282*253c8305SRuslan Bukin unsigned int num_lines;
2283*253c8305SRuslan Bukin unsigned int residual;
2284*253c8305SRuslan Bukin
2285*253c8305SRuslan Bukin TRACE_ENTER(dev);
2286*253c8305SRuslan Bukin
2287*253c8305SRuslan Bukin num_lines = len / 16;
2288*253c8305SRuslan Bukin residual = len - 16 * num_lines;
2289*253c8305SRuslan Bukin
2290*253c8305SRuslan Bukin for(i = 0; i < num_lines; i++) {
2291*253c8305SRuslan Bukin device_printf(dev, "%s:", label);
2292*253c8305SRuslan Bukin for(j = 0; j < 16; j++)
2293*253c8305SRuslan Bukin printf(" %02x", data[i * 16 + j]);
2294*253c8305SRuslan Bukin printf("\n");
2295*253c8305SRuslan Bukin }
2296*253c8305SRuslan Bukin
2297*253c8305SRuslan Bukin if (residual) {
2298*253c8305SRuslan Bukin device_printf(dev, "%s:", label);
2299*253c8305SRuslan Bukin for(j = 0; j < residual; j++)
2300*253c8305SRuslan Bukin printf(" %02x", data[num_lines * 16 + j]);
2301*253c8305SRuslan Bukin printf("\n");
2302*253c8305SRuslan Bukin }
2303*253c8305SRuslan Bukin
2304*253c8305SRuslan Bukin TRACE_EXIT(dev);
2305*253c8305SRuslan Bukin }
2306*253c8305SRuslan Bukin
2307*253c8305SRuslan Bukin static void
mmcspi_dump_spi_bus(device_t dev,unsigned int len)2308*253c8305SRuslan Bukin mmcspi_dump_spi_bus(device_t dev, unsigned int len)
2309*253c8305SRuslan Bukin {
2310*253c8305SRuslan Bukin unsigned int num_blocks;
2311*253c8305SRuslan Bukin unsigned int residual;
2312*253c8305SRuslan Bukin unsigned int i;
2313*253c8305SRuslan Bukin
2314*253c8305SRuslan Bukin TRACE_ENTER(dev);
2315*253c8305SRuslan Bukin
2316*253c8305SRuslan Bukin num_blocks = len / MMCSPI_DATA_BLOCK_LEN;
2317*253c8305SRuslan Bukin residual = len - num_blocks * MMCSPI_DATA_BLOCK_LEN;
2318*253c8305SRuslan Bukin
2319*253c8305SRuslan Bukin for (i = 0; i < num_blocks; i++) {
2320*253c8305SRuslan Bukin if (MMC_ERR_NONE != mmcspi_do_spi_read(dev, junkbuf,
2321*253c8305SRuslan Bukin MMCSPI_DATA_BLOCK_LEN)) {
2322*253c8305SRuslan Bukin device_printf(dev, "spi read failed\n");
2323*253c8305SRuslan Bukin return;
2324*253c8305SRuslan Bukin }
2325*253c8305SRuslan Bukin
2326*253c8305SRuslan Bukin mmcspi_dump_data(dev, "bus_data", junkbuf,
2327*253c8305SRuslan Bukin MMCSPI_DATA_BLOCK_LEN);
2328*253c8305SRuslan Bukin }
2329*253c8305SRuslan Bukin
2330*253c8305SRuslan Bukin if (residual) {
2331*253c8305SRuslan Bukin if (MMC_ERR_NONE != mmcspi_do_spi_read(dev, junkbuf,
2332*253c8305SRuslan Bukin residual)) {
2333*253c8305SRuslan Bukin device_printf(dev, "spi read failed\n");
2334*253c8305SRuslan Bukin return;
2335*253c8305SRuslan Bukin }
2336*253c8305SRuslan Bukin
2337*253c8305SRuslan Bukin mmcspi_dump_data(dev, "bus_data", junkbuf, residual);
2338*253c8305SRuslan Bukin }
2339*253c8305SRuslan Bukin
2340*253c8305SRuslan Bukin TRACE_EXIT(dev);
2341*253c8305SRuslan Bukin }
2342*253c8305SRuslan Bukin #endif
2343*253c8305SRuslan Bukin
2344*253c8305SRuslan Bukin static device_method_t mmcspi_methods[] = {
2345*253c8305SRuslan Bukin /* device_if */
2346*253c8305SRuslan Bukin DEVMETHOD(device_probe, mmcspi_probe),
2347*253c8305SRuslan Bukin DEVMETHOD(device_attach, mmcspi_attach),
2348*253c8305SRuslan Bukin DEVMETHOD(device_detach, mmcspi_detach),
2349*253c8305SRuslan Bukin DEVMETHOD(device_suspend, mmcspi_suspend),
2350*253c8305SRuslan Bukin DEVMETHOD(device_resume, mmcspi_resume),
2351*253c8305SRuslan Bukin
2352*253c8305SRuslan Bukin /* Bus interface */
2353*253c8305SRuslan Bukin DEVMETHOD(bus_read_ivar, mmcspi_read_ivar),
2354*253c8305SRuslan Bukin DEVMETHOD(bus_write_ivar, mmcspi_write_ivar),
2355*253c8305SRuslan Bukin
2356*253c8305SRuslan Bukin /* mmcbr_if */
2357*253c8305SRuslan Bukin DEVMETHOD(mmcbr_update_ios, mmcspi_update_ios),
2358*253c8305SRuslan Bukin DEVMETHOD(mmcbr_request, mmcspi_request),
2359*253c8305SRuslan Bukin DEVMETHOD(mmcbr_get_ro, mmcspi_get_ro),
2360*253c8305SRuslan Bukin DEVMETHOD(mmcbr_acquire_host, mmcspi_acquire_host),
2361*253c8305SRuslan Bukin DEVMETHOD(mmcbr_release_host, mmcspi_release_host),
2362*253c8305SRuslan Bukin DEVMETHOD(mmcbr_switch_vccq, mmcspi_switch_vccq),
2363*253c8305SRuslan Bukin
2364*253c8305SRuslan Bukin {0, 0},
2365*253c8305SRuslan Bukin };
2366*253c8305SRuslan Bukin
2367*253c8305SRuslan Bukin static driver_t mmcspi_driver = {
2368*253c8305SRuslan Bukin "mmcspi",
2369*253c8305SRuslan Bukin mmcspi_methods,
2370*253c8305SRuslan Bukin sizeof(struct mmcspi_softc),
2371*253c8305SRuslan Bukin };
2372*253c8305SRuslan Bukin
2373*253c8305SRuslan Bukin DRIVER_MODULE(mmcspi, spibus, mmcspi_driver, mmcspi_modevent_handler, NULL);
2374*253c8305SRuslan Bukin MODULE_DEPEND(mmcspi, spibus, 1, 1, 1);
2375*253c8305SRuslan Bukin MMC_DECLARE_BRIDGE(mmcspi);
2376*253c8305SRuslan Bukin #ifdef FDT
2377*253c8305SRuslan Bukin SPIBUS_FDT_PNP_INFO(compat_data);
2378*253c8305SRuslan Bukin #endif
2379