1*7f6f7fd3Scheloha /* $OpenBSD: rtsx.c,v 1.22 2020/02/18 00:06:56 cheloha Exp $ */
2f615cd67Sstsp
3f615cd67Sstsp /*
4f615cd67Sstsp * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
5f615cd67Sstsp * Copyright (c) 2012 Stefan Sperling <stsp@openbsd.org>
6f615cd67Sstsp *
7f615cd67Sstsp * Permission to use, copy, modify, and distribute this software for any
8f615cd67Sstsp * purpose with or without fee is hereby granted, provided that the above
9f615cd67Sstsp * copyright notice and this permission notice appear in all copies.
10f615cd67Sstsp *
11f615cd67Sstsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12f615cd67Sstsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13f615cd67Sstsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14f615cd67Sstsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15f615cd67Sstsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16f615cd67Sstsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17f615cd67Sstsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18f615cd67Sstsp */
19f615cd67Sstsp
20f615cd67Sstsp /*
21ae1f177aSstsp * Realtek RTS52xx/RTL84xx Card Reader driver.
22f615cd67Sstsp */
23f615cd67Sstsp
24f615cd67Sstsp #include <sys/param.h>
25f615cd67Sstsp #include <sys/device.h>
26f615cd67Sstsp #include <sys/kernel.h>
27f615cd67Sstsp #include <sys/systm.h>
28f615cd67Sstsp
29f615cd67Sstsp #include <dev/ic/rtsxreg.h>
30f615cd67Sstsp #include <dev/ic/rtsxvar.h>
31f615cd67Sstsp #include <dev/sdmmc/sdmmcvar.h>
32f615cd67Sstsp #include <dev/sdmmc/sdmmc_ioreg.h>
33f615cd67Sstsp
34f615cd67Sstsp /*
35e49248d7Sstsp * We use three DMA buffers: a command buffer, a data buffer, and a buffer for
36e49248d7Sstsp * ADMA transfer descriptors which describe scatter-gather (SG) I/O operations.
37f615cd67Sstsp *
38f615cd67Sstsp * The command buffer contains a command queue for the host controller,
39f615cd67Sstsp * which describes SD/MMC commands to run, and other parameters. The chip
40e49248d7Sstsp * runs the command queue when a special bit in the RTSX_HCBAR register is
41e49248d7Sstsp * set and signals completion with the TRANS_OK interrupt.
42f615cd67Sstsp * Each command is encoded as a 4 byte sequence containing command number
43f615cd67Sstsp * (read, write, or check a host controller register), a register address,
44f615cd67Sstsp * and a data bit-mask and value.
45f615cd67Sstsp * SD/MMC commands which do not transfer any data from/to the card only use
46f615cd67Sstsp * the command buffer.
47e49248d7Sstsp *
48e49248d7Sstsp * The smmmc stack provides DMA-safe buffers with data transfer commands.
49e49248d7Sstsp * In this case we write a list of descriptors to the ADMA descriptor buffer,
50e49248d7Sstsp * instructing the chip to transfer data directly from/to sdmmc DMA buffers.
51e49248d7Sstsp *
52e49248d7Sstsp * However, some sdmmc commands used during card initialization also carry
53e49248d7Sstsp * data, and these don't come with DMA-safe buffers. In this case, we transfer
54e49248d7Sstsp * data from/to the SD card via a DMA data bounce buffer.
55e49248d7Sstsp *
56e49248d7Sstsp * In both cases, data transfer is controlled via the RTSX_HDBAR register
57e49248d7Sstsp * and completion is signalled by the TRANS_OK interrupt.
58e49248d7Sstsp *
59e49248d7Sstsp * The chip is unable to perform DMA above 4GB.
60f615cd67Sstsp */
61f615cd67Sstsp
62f615cd67Sstsp #define RTSX_DMA_MAX_SEGSIZE 0x80000
63f615cd67Sstsp #define RTSX_HOSTCMD_MAX 256
64f615cd67Sstsp #define RTSX_HOSTCMD_BUFSIZE (sizeof(u_int32_t) * RTSX_HOSTCMD_MAX)
65f615cd67Sstsp #define RTSX_DMA_DATA_BUFSIZE MAXPHYS
66e49248d7Sstsp #define RTSX_ADMA_DESC_SIZE (sizeof(uint64_t) * SDMMC_MAXNSEGS)
67f615cd67Sstsp
68f615cd67Sstsp #define READ4(sc, reg) \
69f615cd67Sstsp (bus_space_read_4((sc)->iot, (sc)->ioh, (reg)))
70f615cd67Sstsp #define WRITE4(sc, reg, val) \
71f615cd67Sstsp bus_space_write_4((sc)->iot, (sc)->ioh, (reg), (val))
72f615cd67Sstsp
73f615cd67Sstsp #define RTSX_READ(sc, reg, val) \
74f615cd67Sstsp do { \
75f615cd67Sstsp int err = rtsx_read((sc), (reg), (val)); \
76f615cd67Sstsp if (err) \
77f615cd67Sstsp return (err); \
78f615cd67Sstsp } while (0)
79f615cd67Sstsp
80f615cd67Sstsp #define RTSX_WRITE(sc, reg, val) \
81f615cd67Sstsp do { \
82f615cd67Sstsp int err = rtsx_write((sc), (reg), 0xff, (val)); \
83f615cd67Sstsp if (err) \
84f615cd67Sstsp return (err); \
85f615cd67Sstsp } while (0)
86f615cd67Sstsp
87f615cd67Sstsp #define RTSX_CLR(sc, reg, bits) \
88f615cd67Sstsp do { \
89f615cd67Sstsp int err = rtsx_write((sc), (reg), (bits), 0); \
90f615cd67Sstsp if (err) \
91f615cd67Sstsp return (err); \
92f615cd67Sstsp } while (0)
93f615cd67Sstsp
94f615cd67Sstsp #define RTSX_SET(sc, reg, bits) \
95f615cd67Sstsp do { \
96f615cd67Sstsp int err = rtsx_write((sc), (reg), (bits), 0xff);\
97f615cd67Sstsp if (err) \
98f615cd67Sstsp return (err); \
99f615cd67Sstsp } while (0)
100f615cd67Sstsp
101f615cd67Sstsp int rtsx_host_reset(sdmmc_chipset_handle_t);
102f615cd67Sstsp u_int32_t rtsx_host_ocr(sdmmc_chipset_handle_t);
103f615cd67Sstsp int rtsx_host_maxblklen(sdmmc_chipset_handle_t);
104f615cd67Sstsp int rtsx_card_detect(sdmmc_chipset_handle_t);
105f615cd67Sstsp int rtsx_bus_power(sdmmc_chipset_handle_t, u_int32_t);
106820e06f1Skettenis int rtsx_bus_clock(sdmmc_chipset_handle_t, int, int);
10778d81128Skettenis int rtsx_bus_width(sdmmc_chipset_handle_t, int);
108f615cd67Sstsp void rtsx_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
109f615cd67Sstsp int rtsx_init(struct rtsx_softc *, int);
110f615cd67Sstsp void rtsx_soft_reset(struct rtsx_softc *);
111f615cd67Sstsp int rtsx_bus_power_off(struct rtsx_softc *);
112f615cd67Sstsp int rtsx_bus_power_on(struct rtsx_softc *);
113f615cd67Sstsp int rtsx_set_bus_width(struct rtsx_softc *, int);
114f615cd67Sstsp int rtsx_stop_sd_clock(struct rtsx_softc *);
115f615cd67Sstsp int rtsx_switch_sd_clock(struct rtsx_softc *, u_int8_t, int, int);
116f615cd67Sstsp int rtsx_wait_intr(struct rtsx_softc *, int, int);
117f615cd67Sstsp int rtsx_read(struct rtsx_softc *, u_int16_t, u_int8_t *);
118f615cd67Sstsp int rtsx_write(struct rtsx_softc *, u_int16_t, u_int8_t, u_int8_t);
119f615cd67Sstsp #ifdef notyet
120f615cd67Sstsp int rtsx_read_phy(struct rtsx_softc *, u_int8_t, u_int16_t *);
121f615cd67Sstsp #endif
122f615cd67Sstsp int rtsx_write_phy(struct rtsx_softc *, u_int8_t, u_int16_t);
123f615cd67Sstsp int rtsx_read_cfg(struct rtsx_softc *, u_int8_t, u_int16_t, u_int32_t *);
124f615cd67Sstsp #ifdef notyet
125f615cd67Sstsp int rtsx_write_cfg(struct rtsx_softc *, u_int8_t, u_int16_t, u_int32_t,
126f615cd67Sstsp u_int32_t);
127f615cd67Sstsp #endif
128f615cd67Sstsp void rtsx_hostcmd(u_int32_t *, int *, u_int8_t, u_int16_t, u_int8_t,
129f615cd67Sstsp u_int8_t);
130b36d9b34Sstsp int rtsx_hostcmd_send(struct rtsx_softc *, int);
131f615cd67Sstsp u_int8_t rtsx_response_type(u_int16_t);
132e49248d7Sstsp int rtsx_xfer_exec(struct rtsx_softc *, bus_dmamap_t, int);
133f615cd67Sstsp int rtsx_xfer(struct rtsx_softc *, struct sdmmc_command *, u_int32_t *);
134e49248d7Sstsp int rtsx_xfer_bounce(struct rtsx_softc *, struct sdmmc_command *);
135e49248d7Sstsp int rtsx_xfer_adma(struct rtsx_softc *, struct sdmmc_command *);
136f615cd67Sstsp void rtsx_card_insert(struct rtsx_softc *);
137f615cd67Sstsp void rtsx_card_eject(struct rtsx_softc *);
138f615cd67Sstsp int rtsx_led_enable(struct rtsx_softc *);
139f615cd67Sstsp int rtsx_led_disable(struct rtsx_softc *);
140f615cd67Sstsp void rtsx_save_regs(struct rtsx_softc *);
141f615cd67Sstsp void rtsx_restore_regs(struct rtsx_softc *);
142f615cd67Sstsp
143f615cd67Sstsp #ifdef RTSX_DEBUG
144f615cd67Sstsp int rtsxdebug = 0;
145f615cd67Sstsp #define DPRINTF(n,s) do { if ((n) <= rtsxdebug) printf s; } while (0)
146f615cd67Sstsp #else
147f615cd67Sstsp #define DPRINTF(n,s) do {} while(0)
148f615cd67Sstsp #endif
149f615cd67Sstsp
150f615cd67Sstsp struct sdmmc_chip_functions rtsx_functions = {
151f615cd67Sstsp /* host controller reset */
152f615cd67Sstsp rtsx_host_reset,
153f615cd67Sstsp /* host controller capabilities */
154f615cd67Sstsp rtsx_host_ocr,
155f615cd67Sstsp rtsx_host_maxblklen,
156f615cd67Sstsp /* card detection */
157f615cd67Sstsp rtsx_card_detect,
158f615cd67Sstsp /* bus power and clock frequency */
159f615cd67Sstsp rtsx_bus_power,
160f615cd67Sstsp rtsx_bus_clock,
16178d81128Skettenis rtsx_bus_width,
162f615cd67Sstsp /* command execution */
163f615cd67Sstsp rtsx_exec_command,
164f615cd67Sstsp /* card interrupt */
165f615cd67Sstsp NULL, NULL
166f615cd67Sstsp };
167f615cd67Sstsp
168f615cd67Sstsp struct cfdriver rtsx_cd = {
169f615cd67Sstsp NULL, "rtsx", DV_DULL
170f615cd67Sstsp };
171f615cd67Sstsp
172f615cd67Sstsp /*
173f615cd67Sstsp * Called by attachment driver.
174f615cd67Sstsp */
175f615cd67Sstsp int
rtsx_attach(struct rtsx_softc * sc,bus_space_tag_t iot,bus_space_handle_t ioh,bus_size_t iosize,bus_dma_tag_t dmat,int flags)176f615cd67Sstsp rtsx_attach(struct rtsx_softc *sc, bus_space_tag_t iot,
1770cd9a838Sstsp bus_space_handle_t ioh, bus_size_t iosize, bus_dma_tag_t dmat, int flags)
178f615cd67Sstsp {
179f615cd67Sstsp struct sdmmcbus_attach_args saa;
180f615cd67Sstsp u_int32_t sdio_cfg;
181e49248d7Sstsp int rsegs;
182f615cd67Sstsp
183f615cd67Sstsp sc->iot = iot;
184f615cd67Sstsp sc->ioh = ioh;
185f615cd67Sstsp sc->dmat = dmat;
1860cd9a838Sstsp sc->flags = flags;
187f615cd67Sstsp
188f615cd67Sstsp if (rtsx_init(sc, 1))
189f615cd67Sstsp return 1;
190f615cd67Sstsp
19120d41c9bSstsp if (rtsx_read_cfg(sc, 0, RTSX_SDIOCFG_REG, &sdio_cfg) == 0) {
192f615cd67Sstsp if ((sdio_cfg & RTSX_SDIOCFG_SDIO_ONLY) ||
193f615cd67Sstsp (sdio_cfg & RTSX_SDIOCFG_HAVE_SDIO))
194f615cd67Sstsp sc->flags |= RTSX_F_SDIO_SUPPORT;
195f615cd67Sstsp }
196f615cd67Sstsp
197f615cd67Sstsp if (bus_dmamap_create(sc->dmat, RTSX_HOSTCMD_BUFSIZE, 1,
198f615cd67Sstsp RTSX_DMA_MAX_SEGSIZE, 0, BUS_DMA_NOWAIT,
199f615cd67Sstsp &sc->dmap_cmd) != 0)
200f615cd67Sstsp return 1;
201f615cd67Sstsp if (bus_dmamap_create(sc->dmat, RTSX_DMA_DATA_BUFSIZE, 1,
202f615cd67Sstsp RTSX_DMA_MAX_SEGSIZE, 0, BUS_DMA_NOWAIT,
203f615cd67Sstsp &sc->dmap_data) != 0)
204e49248d7Sstsp goto destroy_cmd;
205e49248d7Sstsp if (bus_dmamap_create(sc->dmat, RTSX_ADMA_DESC_SIZE, 1,
206e49248d7Sstsp RTSX_DMA_MAX_SEGSIZE, 0, BUS_DMA_NOWAIT,
207e49248d7Sstsp &sc->dmap_adma) != 0)
208e49248d7Sstsp goto destroy_data;
209e49248d7Sstsp if (bus_dmamem_alloc(sc->dmat, RTSX_ADMA_DESC_SIZE, 0, 0,
210e49248d7Sstsp sc->adma_segs, 1, &rsegs, BUS_DMA_WAITOK|BUS_DMA_ZERO))
211e49248d7Sstsp goto destroy_adma;
212e49248d7Sstsp if (bus_dmamem_map(sc->dmat, sc->adma_segs, rsegs, RTSX_ADMA_DESC_SIZE,
213e49248d7Sstsp &sc->admabuf, BUS_DMA_WAITOK|BUS_DMA_COHERENT))
214e49248d7Sstsp goto free_adma;
215f615cd67Sstsp
216f615cd67Sstsp /*
217f615cd67Sstsp * Attach the generic SD/MMC bus driver. (The bus driver must
218f615cd67Sstsp * not invoke any chipset functions before it is attached.)
219f615cd67Sstsp */
220f615cd67Sstsp bzero(&saa, sizeof(saa));
221f615cd67Sstsp saa.saa_busname = "sdmmc";
222f615cd67Sstsp saa.sct = &rtsx_functions;
223f615cd67Sstsp saa.sch = sc;
224f615cd67Sstsp saa.flags = SMF_STOP_AFTER_MULTIPLE;
225e49248d7Sstsp saa.caps = SMC_CAPS_4BIT_MODE | SMC_CAPS_DMA;
226e49248d7Sstsp saa.dmat = sc->dmat;
227f615cd67Sstsp
228f615cd67Sstsp sc->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
229f615cd67Sstsp if (sc->sdmmc == NULL)
230e49248d7Sstsp goto unmap_adma;
231f615cd67Sstsp
232f615cd67Sstsp /* Now handle cards discovered during attachment. */
233f615cd67Sstsp if (ISSET(sc->flags, RTSX_F_CARD_PRESENT))
234f615cd67Sstsp rtsx_card_insert(sc);
235f615cd67Sstsp
236f615cd67Sstsp return 0;
237e49248d7Sstsp
238e49248d7Sstsp unmap_adma:
239e49248d7Sstsp bus_dmamem_unmap(sc->dmat, sc->admabuf, RTSX_ADMA_DESC_SIZE);
240e49248d7Sstsp free_adma:
241e49248d7Sstsp bus_dmamem_free(sc->dmat, sc->adma_segs, rsegs);
242e49248d7Sstsp destroy_adma:
243e49248d7Sstsp bus_dmamap_destroy(sc->dmat, sc->dmap_adma);
244e49248d7Sstsp destroy_data:
245e49248d7Sstsp bus_dmamap_destroy(sc->dmat, sc->dmap_data);
246e49248d7Sstsp destroy_cmd:
247e49248d7Sstsp bus_dmamap_destroy(sc->dmat, sc->dmap_cmd);
248e49248d7Sstsp return 1;
249f615cd67Sstsp }
250f615cd67Sstsp
251f615cd67Sstsp int
rtsx_init(struct rtsx_softc * sc,int attaching)252f615cd67Sstsp rtsx_init(struct rtsx_softc *sc, int attaching)
253f615cd67Sstsp {
254f615cd67Sstsp u_int32_t status;
2550cd9a838Sstsp u_int8_t version;
2560cd9a838Sstsp int error;
2570cd9a838Sstsp
2580cd9a838Sstsp /* Read IC version from dummy register. */
2590cd9a838Sstsp if (sc->flags & RTSX_F_5229) {
2600cd9a838Sstsp RTSX_READ(sc, RTSX_DUMMY_REG, &version);
2610cd9a838Sstsp switch (version & 0x0F) {
2620cd9a838Sstsp case RTSX_IC_VERSION_A:
2630cd9a838Sstsp case RTSX_IC_VERSION_B:
2640cd9a838Sstsp case RTSX_IC_VERSION_D:
2650cd9a838Sstsp break;
2660cd9a838Sstsp case RTSX_IC_VERSION_C:
2670cd9a838Sstsp sc->flags |= RTSX_F_5229_TYPE_C;
2680cd9a838Sstsp break;
2690cd9a838Sstsp default:
2700cd9a838Sstsp printf("rtsx_init: unknown ic %02x\n", version);
2710cd9a838Sstsp return (1);
2720cd9a838Sstsp }
2730cd9a838Sstsp }
274f615cd67Sstsp
275f615cd67Sstsp /* Enable interrupt write-clear (default is read-clear). */
276f615cd67Sstsp RTSX_CLR(sc, RTSX_NFTS_TX_CTRL, RTSX_INT_READ_CLR);
277f615cd67Sstsp
278f615cd67Sstsp /* Clear any pending interrupts. */
279f615cd67Sstsp status = READ4(sc, RTSX_BIPR);
280f615cd67Sstsp WRITE4(sc, RTSX_BIPR, status);
281f615cd67Sstsp
2821a8ef7caSstsp /* Check for cards already inserted at attach time. */
2831a8ef7caSstsp if (attaching && (status & RTSX_SD_EXIST))
2841a8ef7caSstsp sc->flags |= RTSX_F_CARD_PRESENT;
2851a8ef7caSstsp
2861a8ef7caSstsp /* Enable interrupts. */
2871a8ef7caSstsp WRITE4(sc, RTSX_BIER,
2881a8ef7caSstsp RTSX_TRANS_OK_INT_EN | RTSX_TRANS_FAIL_INT_EN | RTSX_SD_INT_EN);
2891a8ef7caSstsp
290f615cd67Sstsp /* Power on SSC clock. */
291f615cd67Sstsp RTSX_CLR(sc, RTSX_FPDCTL, RTSX_SSC_POWER_DOWN);
292f615cd67Sstsp delay(200);
293f615cd67Sstsp
294f615cd67Sstsp /* XXX magic numbers from linux driver */
2950cd9a838Sstsp if (sc->flags & RTSX_F_5209)
2960cd9a838Sstsp error = rtsx_write_phy(sc, 0x00, 0xB966);
2970cd9a838Sstsp else
2980cd9a838Sstsp error = rtsx_write_phy(sc, 0x00, 0xBA42);
2990cd9a838Sstsp if (error) {
300f615cd67Sstsp printf("%s: cannot write phy register\n", DEVNAME(sc));
301f615cd67Sstsp return (1);
302f615cd67Sstsp }
303f615cd67Sstsp
304f615cd67Sstsp RTSX_SET(sc, RTSX_CLK_DIV, 0x07);
305f615cd67Sstsp
306f615cd67Sstsp /* Disable sleep mode. */
307f615cd67Sstsp RTSX_CLR(sc, RTSX_HOST_SLEEP_STATE,
308f615cd67Sstsp RTSX_HOST_ENTER_S1 | RTSX_HOST_ENTER_S3);
309f615cd67Sstsp
310f615cd67Sstsp /* Disable card clock. */
311f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_CLK_EN, RTSX_CARD_CLK_EN_ALL);
312f615cd67Sstsp
313f615cd67Sstsp RTSX_CLR(sc, RTSX_CHANGE_LINK_STATE,
314f615cd67Sstsp RTSX_FORCE_RST_CORE_EN | RTSX_NON_STICKY_RST_N_DBG | 0x04);
315f615cd67Sstsp RTSX_WRITE(sc, RTSX_SD30_DRIVE_SEL, RTSX_SD30_DRIVE_SEL_3V3);
316f615cd67Sstsp
317f615cd67Sstsp /* Enable SSC clock. */
318f615cd67Sstsp RTSX_WRITE(sc, RTSX_SSC_CTL1, RTSX_SSC_8X_EN | RTSX_SSC_SEL_4M);
319f615cd67Sstsp RTSX_WRITE(sc, RTSX_SSC_CTL2, 0x12);
320f615cd67Sstsp
321f615cd67Sstsp RTSX_SET(sc, RTSX_CHANGE_LINK_STATE, RTSX_MAC_PHY_RST_N_DBG);
322f615cd67Sstsp RTSX_SET(sc, RTSX_IRQSTAT0, RTSX_LINK_READY_INT);
323f615cd67Sstsp
324f615cd67Sstsp RTSX_WRITE(sc, RTSX_PERST_GLITCH_WIDTH, 0x80);
325f615cd67Sstsp
326f615cd67Sstsp /* Set RC oscillator to 400K. */
327f615cd67Sstsp RTSX_CLR(sc, RTSX_RCCTL, RTSX_RCCTL_F_2M);
328f615cd67Sstsp
329f615cd67Sstsp /* Request clock by driving CLKREQ pin to zero. */
330f615cd67Sstsp RTSX_SET(sc, RTSX_PETXCFG, RTSX_PETXCFG_CLKREQ_PIN);
331f615cd67Sstsp
332f615cd67Sstsp /* Set up LED GPIO. */
3330cd9a838Sstsp if (sc->flags & RTSX_F_5209) {
334f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_GPIO, 0x03);
335f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_GPIO_DIR, 0x03);
3360cd9a838Sstsp } else {
3370cd9a838Sstsp RTSX_SET(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
3380cd9a838Sstsp /* Switch LDO3318 source from DV33 to 3V3. */
3390cd9a838Sstsp RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33);
3400cd9a838Sstsp RTSX_SET(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_3V3);
3410cd9a838Sstsp /* Set default OLT blink period. */
3420cd9a838Sstsp RTSX_SET(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_PERIOD);
3430cd9a838Sstsp }
344f615cd67Sstsp
345f615cd67Sstsp return (0);
346f615cd67Sstsp }
347f615cd67Sstsp
348f615cd67Sstsp int
rtsx_activate(struct device * self,int act)349f615cd67Sstsp rtsx_activate(struct device *self, int act)
350f615cd67Sstsp {
351f615cd67Sstsp struct rtsx_softc *sc = (struct rtsx_softc *)self;
352f615cd67Sstsp int rv = 0;
353f615cd67Sstsp
354f615cd67Sstsp switch (act) {
355f615cd67Sstsp case DVACT_SUSPEND:
356f615cd67Sstsp rv = config_activate_children(self, act);
35700c76a70Sderaadt rtsx_save_regs(sc);
358f615cd67Sstsp break;
359f615cd67Sstsp case DVACT_RESUME:
360f615cd67Sstsp rtsx_restore_regs(sc);
361f615cd67Sstsp
362f615cd67Sstsp /* Handle cards ejected/inserted during suspend. */
363f615cd67Sstsp if (READ4(sc, RTSX_BIPR) & RTSX_SD_EXIST)
364f615cd67Sstsp rtsx_card_insert(sc);
365f615cd67Sstsp else
366f615cd67Sstsp rtsx_card_eject(sc);
367f615cd67Sstsp
368f615cd67Sstsp rv = config_activate_children(self, act);
369f615cd67Sstsp break;
37037ecb596Sderaadt default:
37137ecb596Sderaadt rv = config_activate_children(self, act);
37237ecb596Sderaadt break;
373f615cd67Sstsp }
374f615cd67Sstsp return (rv);
375f615cd67Sstsp }
376f615cd67Sstsp
377f615cd67Sstsp int
rtsx_led_enable(struct rtsx_softc * sc)378f615cd67Sstsp rtsx_led_enable(struct rtsx_softc *sc)
379f615cd67Sstsp {
3800cd9a838Sstsp if (sc->flags & RTSX_F_5209) {
381f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
382f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_AUTO_BLINK,
383f615cd67Sstsp RTSX_LED_BLINK_EN | RTSX_LED_BLINK_SPEED);
3840cd9a838Sstsp } else {
3850cd9a838Sstsp RTSX_SET(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
3860cd9a838Sstsp RTSX_SET(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK);
3870cd9a838Sstsp }
3880cd9a838Sstsp
389f615cd67Sstsp return 0;
390f615cd67Sstsp }
391f615cd67Sstsp
392f615cd67Sstsp int
rtsx_led_disable(struct rtsx_softc * sc)393f615cd67Sstsp rtsx_led_disable(struct rtsx_softc *sc)
394f615cd67Sstsp {
3950cd9a838Sstsp if (sc->flags & RTSX_F_5209) {
396f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_AUTO_BLINK, RTSX_LED_BLINK_EN);
397f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
3980cd9a838Sstsp } else {
3990cd9a838Sstsp RTSX_CLR(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK);
4000cd9a838Sstsp RTSX_CLR(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
4010cd9a838Sstsp }
4020cd9a838Sstsp
403f615cd67Sstsp return 0;
404f615cd67Sstsp }
405f615cd67Sstsp
406f615cd67Sstsp /*
407f615cd67Sstsp * Reset the host controller. Called during initialization, when
408f615cd67Sstsp * cards are removed, upon resume, and during error recovery.
409f615cd67Sstsp */
410f615cd67Sstsp int
rtsx_host_reset(sdmmc_chipset_handle_t sch)411f615cd67Sstsp rtsx_host_reset(sdmmc_chipset_handle_t sch)
412f615cd67Sstsp {
413f615cd67Sstsp struct rtsx_softc *sc = sch;
414f615cd67Sstsp int s;
415f615cd67Sstsp
416f615cd67Sstsp DPRINTF(1,("%s: host reset\n", DEVNAME(sc)));
417f615cd67Sstsp
418f615cd67Sstsp s = splsdmmc();
419f615cd67Sstsp
420f615cd67Sstsp if (ISSET(sc->flags, RTSX_F_CARD_PRESENT))
421f615cd67Sstsp rtsx_soft_reset(sc);
422f615cd67Sstsp
423f615cd67Sstsp if (rtsx_init(sc, 0)) {
424f615cd67Sstsp splx(s);
425f615cd67Sstsp return 1;
426f615cd67Sstsp }
427f615cd67Sstsp
428f615cd67Sstsp splx(s);
429f615cd67Sstsp return 0;
430f615cd67Sstsp }
431f615cd67Sstsp
432f615cd67Sstsp u_int32_t
rtsx_host_ocr(sdmmc_chipset_handle_t sch)433f615cd67Sstsp rtsx_host_ocr(sdmmc_chipset_handle_t sch)
434f615cd67Sstsp {
435f615cd67Sstsp return RTSX_SUPPORT_VOLTAGE;
436f615cd67Sstsp }
437f615cd67Sstsp
438f615cd67Sstsp int
rtsx_host_maxblklen(sdmmc_chipset_handle_t sch)439f615cd67Sstsp rtsx_host_maxblklen(sdmmc_chipset_handle_t sch)
440f615cd67Sstsp {
441f615cd67Sstsp return 512;
442f615cd67Sstsp }
443f615cd67Sstsp
444f615cd67Sstsp /*
445f615cd67Sstsp * Return non-zero if the card is currently inserted.
446f615cd67Sstsp */
447f615cd67Sstsp int
rtsx_card_detect(sdmmc_chipset_handle_t sch)448f615cd67Sstsp rtsx_card_detect(sdmmc_chipset_handle_t sch)
449f615cd67Sstsp {
450f615cd67Sstsp struct rtsx_softc *sc = sch;
451f615cd67Sstsp
452f615cd67Sstsp return ISSET(sc->flags, RTSX_F_CARD_PRESENT);
453f615cd67Sstsp }
454f615cd67Sstsp
4550cd9a838Sstsp /*
4560cd9a838Sstsp * Notice that the meaning of RTSX_PWR_GATE_CTRL changes between RTS5209 and
4570cd9a838Sstsp * RTS5229. In RTS5209 it is a mask of disabled power gates, while in RTS5229
4580cd9a838Sstsp * it is a mask of *enabled* gates.
4590cd9a838Sstsp */
4600cd9a838Sstsp
461f615cd67Sstsp int
rtsx_bus_power_off(struct rtsx_softc * sc)462f615cd67Sstsp rtsx_bus_power_off(struct rtsx_softc *sc)
463f615cd67Sstsp {
464f615cd67Sstsp int error;
4650cd9a838Sstsp u_int8_t disable3;
466f615cd67Sstsp
467f615cd67Sstsp error = rtsx_stop_sd_clock(sc);
468f615cd67Sstsp if (error)
469f615cd67Sstsp return error;
470f615cd67Sstsp
471f615cd67Sstsp /* Disable SD output. */
472f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_OE, RTSX_CARD_OUTPUT_EN);
473f615cd67Sstsp
474f615cd67Sstsp /* Turn off power. */
4750cd9a838Sstsp disable3 = RTSX_PULL_CTL_DISABLE3;
4760cd9a838Sstsp if (sc->flags & RTSX_F_5209)
477f615cd67Sstsp RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF);
4780cd9a838Sstsp else {
4790cd9a838Sstsp RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1 |
4800cd9a838Sstsp RTSX_LDO3318_VCC2);
4810cd9a838Sstsp if (sc->flags & RTSX_F_5229_TYPE_C)
4820cd9a838Sstsp disable3 = RTSX_PULL_CTL_DISABLE3_TYPE_C;
4830cd9a838Sstsp }
4840cd9a838Sstsp
485f615cd67Sstsp RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF);
486f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_PMOS_STRG_800mA);
487f615cd67Sstsp
488f615cd67Sstsp /* Disable pull control. */
489f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, RTSX_PULL_CTL_DISABLE12);
490f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_DISABLE12);
4910cd9a838Sstsp RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, disable3);
492f615cd67Sstsp
493f615cd67Sstsp return 0;
494f615cd67Sstsp }
495f615cd67Sstsp
496f615cd67Sstsp int
rtsx_bus_power_on(struct rtsx_softc * sc)497f615cd67Sstsp rtsx_bus_power_on(struct rtsx_softc *sc)
498f615cd67Sstsp {
4990cd9a838Sstsp u_int8_t enable3;
500adc32ee9Sjcs int err;
5010cd9a838Sstsp
502adc32ee9Sjcs if (sc->flags & RTSX_F_525A) {
503adc32ee9Sjcs err = rtsx_write(sc, RTSX_LDO_VCC_CFG1, RTSX_LDO_VCC_TUNE_MASK,
5042c295eddSjcs RTSX_LDO_VCC_3V3);
505adc32ee9Sjcs if (err)
506adc32ee9Sjcs return (err);
507adc32ee9Sjcs }
5082c295eddSjcs
509f615cd67Sstsp /* Select SD card. */
510f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_SELECT, RTSX_SD_MOD_SEL);
511f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_SHARE_MODE, RTSX_CARD_SHARE_48_SD);
512f615cd67Sstsp RTSX_SET(sc, RTSX_CARD_CLK_EN, RTSX_SD_CLK_EN);
513f615cd67Sstsp
514f615cd67Sstsp /* Enable pull control. */
515f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, RTSX_PULL_CTL_ENABLE12);
516f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_ENABLE12);
5170cd9a838Sstsp if (sc->flags & RTSX_F_5229_TYPE_C)
5180cd9a838Sstsp enable3 = RTSX_PULL_CTL_ENABLE3_TYPE_C;
5190cd9a838Sstsp else
5200cd9a838Sstsp enable3 = RTSX_PULL_CTL_ENABLE3;
5210cd9a838Sstsp RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, enable3);
522f615cd67Sstsp
5230cd9a838Sstsp /*
5240cd9a838Sstsp * To avoid a current peak, enable card power in two phases with a
5250cd9a838Sstsp * delay in between.
5260cd9a838Sstsp */
5270cd9a838Sstsp
5280cd9a838Sstsp /* Partial power. */
529f615cd67Sstsp RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PARTIAL_PWR_ON);
530e518625aSphessler if (sc->flags & RTSX_F_5209)
531f615cd67Sstsp RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_SUSPEND);
532e518625aSphessler else
533e518625aSphessler RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1);
5340cd9a838Sstsp
535f615cd67Sstsp delay(200);
5360cd9a838Sstsp
5370cd9a838Sstsp /* Full power. */
538f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF);
5390cd9a838Sstsp if (sc->flags & RTSX_F_5209)
540f615cd67Sstsp RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF);
5410cd9a838Sstsp else
5420cd9a838Sstsp RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC2);
543f615cd67Sstsp
544f615cd67Sstsp /* Enable SD card output. */
545f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_OE, RTSX_SD_OUTPUT_EN);
546f615cd67Sstsp
547f615cd67Sstsp return 0;
548f615cd67Sstsp }
549f615cd67Sstsp
550f615cd67Sstsp int
rtsx_set_bus_width(struct rtsx_softc * sc,int w)551f615cd67Sstsp rtsx_set_bus_width(struct rtsx_softc *sc, int w)
552f615cd67Sstsp {
553f615cd67Sstsp u_int32_t bus_width;
55478d81128Skettenis int error;
555f615cd67Sstsp
556f615cd67Sstsp switch (w) {
557f615cd67Sstsp case 8:
558f615cd67Sstsp bus_width = RTSX_BUS_WIDTH_8;
559f615cd67Sstsp break;
560f615cd67Sstsp case 4:
561f615cd67Sstsp bus_width = RTSX_BUS_WIDTH_4;
562f615cd67Sstsp break;
563f615cd67Sstsp case 1:
564f615cd67Sstsp default:
565f615cd67Sstsp bus_width = RTSX_BUS_WIDTH_1;
566f615cd67Sstsp break;
567f615cd67Sstsp }
568f615cd67Sstsp
56978d81128Skettenis error = rtsx_write(sc, RTSX_SD_CFG1, RTSX_BUS_WIDTH_MASK, bus_width);
57078d81128Skettenis return error;
571f615cd67Sstsp }
572f615cd67Sstsp
573f615cd67Sstsp int
rtsx_stop_sd_clock(struct rtsx_softc * sc)574f615cd67Sstsp rtsx_stop_sd_clock(struct rtsx_softc *sc)
575f615cd67Sstsp {
576f615cd67Sstsp RTSX_CLR(sc, RTSX_CARD_CLK_EN, RTSX_CARD_CLK_EN_ALL);
577f615cd67Sstsp RTSX_SET(sc, RTSX_SD_BUS_STAT, RTSX_SD_CLK_FORCE_STOP);
578f615cd67Sstsp
579f615cd67Sstsp return 0;
580f615cd67Sstsp }
581f615cd67Sstsp
582f615cd67Sstsp int
rtsx_switch_sd_clock(struct rtsx_softc * sc,u_int8_t n,int div,int mcu)583f615cd67Sstsp rtsx_switch_sd_clock(struct rtsx_softc *sc, u_int8_t n, int div, int mcu)
584f615cd67Sstsp {
585f615cd67Sstsp /* Enable SD 2.0 mode. */
586f615cd67Sstsp RTSX_CLR(sc, RTSX_SD_CFG1, RTSX_SD_MODE_MASK);
587f615cd67Sstsp
588f615cd67Sstsp RTSX_SET(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ);
589f615cd67Sstsp
590f615cd67Sstsp RTSX_WRITE(sc, RTSX_CARD_CLK_SOURCE,
591f615cd67Sstsp RTSX_CRC_FIX_CLK | RTSX_SD30_VAR_CLK0 | RTSX_SAMPLE_VAR_CLK1);
592f615cd67Sstsp RTSX_CLR(sc, RTSX_SD_SAMPLE_POINT_CTL, RTSX_SD20_RX_SEL_MASK);
593f615cd67Sstsp RTSX_WRITE(sc, RTSX_SD_PUSH_POINT_CTL, RTSX_SD20_TX_NEG_EDGE);
594f615cd67Sstsp RTSX_WRITE(sc, RTSX_CLK_DIV, (div << 4) | mcu);
595f615cd67Sstsp RTSX_CLR(sc, RTSX_SSC_CTL1, RTSX_RSTB);
596f615cd67Sstsp RTSX_CLR(sc, RTSX_SSC_CTL2, RTSX_SSC_DEPTH_MASK);
597f615cd67Sstsp RTSX_WRITE(sc, RTSX_SSC_DIV_N_0, n);
598f615cd67Sstsp RTSX_SET(sc, RTSX_SSC_CTL1, RTSX_RSTB);
599f615cd67Sstsp delay(100);
600f615cd67Sstsp
601f615cd67Sstsp RTSX_CLR(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ);
602f615cd67Sstsp
603f615cd67Sstsp return 0;
604f615cd67Sstsp }
605f615cd67Sstsp
606f615cd67Sstsp /*
607f615cd67Sstsp * Set or change SD bus voltage and enable or disable SD bus power.
608f615cd67Sstsp * Return zero on success.
609f615cd67Sstsp */
610f615cd67Sstsp int
rtsx_bus_power(sdmmc_chipset_handle_t sch,u_int32_t ocr)611f615cd67Sstsp rtsx_bus_power(sdmmc_chipset_handle_t sch, u_int32_t ocr)
612f615cd67Sstsp {
613f615cd67Sstsp struct rtsx_softc *sc = sch;
614f615cd67Sstsp int s, error = 0;
615f615cd67Sstsp
616f615cd67Sstsp DPRINTF(1,("%s: voltage change ocr=0x%x\n", DEVNAME(sc), ocr));
617f615cd67Sstsp
618f615cd67Sstsp s = splsdmmc();
619f615cd67Sstsp
620f615cd67Sstsp /*
621f615cd67Sstsp * Disable bus power before voltage change.
622f615cd67Sstsp */
623f615cd67Sstsp error = rtsx_bus_power_off(sc);
624f615cd67Sstsp if (error)
625f615cd67Sstsp goto ret;
626f615cd67Sstsp
627f615cd67Sstsp delay(200);
628f615cd67Sstsp
629f615cd67Sstsp /* If power is disabled, reset the host and return now. */
630f615cd67Sstsp if (ocr == 0) {
631f615cd67Sstsp splx(s);
632f615cd67Sstsp (void)rtsx_host_reset(sc);
633f615cd67Sstsp return 0;
634f615cd67Sstsp }
635f615cd67Sstsp
636f615cd67Sstsp if (!ISSET(ocr, RTSX_SUPPORT_VOLTAGE)) {
637f615cd67Sstsp /* Unsupported voltage level requested. */
638f615cd67Sstsp DPRINTF(1,("%s: unsupported voltage ocr=0x%x\n",
639f615cd67Sstsp DEVNAME(sc), ocr));
640f615cd67Sstsp error = EINVAL;
641f615cd67Sstsp goto ret;
642f615cd67Sstsp }
643f615cd67Sstsp
64478d81128Skettenis error = rtsx_bus_power_on(sc);
645f615cd67Sstsp if (error)
646f615cd67Sstsp goto ret;
647f615cd67Sstsp
64878d81128Skettenis error = rtsx_set_bus_width(sc, 1);
649f615cd67Sstsp ret:
650f615cd67Sstsp splx(s);
651f615cd67Sstsp return error;
652f615cd67Sstsp }
653f615cd67Sstsp
654f615cd67Sstsp /*
655f615cd67Sstsp * Set or change SDCLK frequency or disable the SD clock.
656f615cd67Sstsp * Return zero on success.
657f615cd67Sstsp */
658f615cd67Sstsp int
rtsx_bus_clock(sdmmc_chipset_handle_t sch,int freq,int timing)659820e06f1Skettenis rtsx_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing)
660f615cd67Sstsp {
661f615cd67Sstsp struct rtsx_softc *sc = sch;
662f615cd67Sstsp int s;
663f615cd67Sstsp u_int8_t n;
664f615cd67Sstsp int div;
665f615cd67Sstsp int mcu;
666f615cd67Sstsp int error = 0;
667f615cd67Sstsp
668f615cd67Sstsp s = splsdmmc();
669f615cd67Sstsp
670f615cd67Sstsp if (freq == SDMMC_SDCLK_OFF) {
671f615cd67Sstsp error = rtsx_stop_sd_clock(sc);
672f615cd67Sstsp goto ret;
673f615cd67Sstsp }
674f615cd67Sstsp
675dcd4253dSkettenis /* Round down to a supported frequency. */
676dcd4253dSkettenis if (freq >= SDMMC_SDCLK_50MHZ)
677dcd4253dSkettenis freq = SDMMC_SDCLK_50MHZ;
678dcd4253dSkettenis else if (freq >= SDMMC_SDCLK_25MHZ)
679dcd4253dSkettenis freq = SDMMC_SDCLK_25MHZ;
680dcd4253dSkettenis else
681dcd4253dSkettenis freq = SDMMC_SDCLK_400KHZ;
682dcd4253dSkettenis
683f615cd67Sstsp /*
684f615cd67Sstsp * Configure the clock frequency.
685f615cd67Sstsp */
686f615cd67Sstsp switch (freq) {
687f615cd67Sstsp case SDMMC_SDCLK_400KHZ:
688f615cd67Sstsp n = 80; /* minimum */
689f615cd67Sstsp div = RTSX_CLK_DIV_8;
690f615cd67Sstsp mcu = 7;
691f615cd67Sstsp RTSX_SET(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_128);
692f615cd67Sstsp break;
693f615cd67Sstsp case SDMMC_SDCLK_25MHZ:
694f615cd67Sstsp n = 100;
695f615cd67Sstsp div = RTSX_CLK_DIV_4;
696f615cd67Sstsp mcu = 7;
697f615cd67Sstsp RTSX_CLR(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_MASK);
698f615cd67Sstsp break;
699dcd4253dSkettenis case SDMMC_SDCLK_50MHZ:
700dcd4253dSkettenis n = 100;
701dcd4253dSkettenis div = RTSX_CLK_DIV_2;
702dcd4253dSkettenis mcu = 7;
703dcd4253dSkettenis RTSX_CLR(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_MASK);
704dcd4253dSkettenis break;
705f615cd67Sstsp default:
706f615cd67Sstsp error = EINVAL;
707f615cd67Sstsp goto ret;
708f615cd67Sstsp }
709f615cd67Sstsp
710f615cd67Sstsp /*
711f615cd67Sstsp * Enable SD clock.
712f615cd67Sstsp */
713f615cd67Sstsp error = rtsx_switch_sd_clock(sc, n, div, mcu);
714f615cd67Sstsp ret:
715f615cd67Sstsp splx(s);
716f615cd67Sstsp return error;
717f615cd67Sstsp }
718f615cd67Sstsp
719f615cd67Sstsp int
rtsx_bus_width(sdmmc_chipset_handle_t sch,int width)72078d81128Skettenis rtsx_bus_width(sdmmc_chipset_handle_t sch, int width)
72178d81128Skettenis {
72278d81128Skettenis struct rtsx_softc *sc = sch;
72378d81128Skettenis
72478d81128Skettenis return rtsx_set_bus_width(sc, width);
72578d81128Skettenis }
72678d81128Skettenis
72778d81128Skettenis int
rtsx_read(struct rtsx_softc * sc,u_int16_t addr,u_int8_t * val)728f615cd67Sstsp rtsx_read(struct rtsx_softc *sc, u_int16_t addr, u_int8_t *val)
729f615cd67Sstsp {
730f615cd67Sstsp int tries = 1024;
731f615cd67Sstsp u_int32_t reg;
732f615cd67Sstsp
733f615cd67Sstsp WRITE4(sc, RTSX_HAIMR, RTSX_HAIMR_BUSY |
734f615cd67Sstsp (u_int32_t)((addr & 0x3FFF) << 16));
735f615cd67Sstsp
736f615cd67Sstsp while (tries--) {
737f615cd67Sstsp reg = READ4(sc, RTSX_HAIMR);
738f615cd67Sstsp if (!(reg & RTSX_HAIMR_BUSY))
739f615cd67Sstsp break;
740f615cd67Sstsp }
741f615cd67Sstsp
742f615cd67Sstsp *val = (reg & 0xff);
743f615cd67Sstsp return (tries == 0) ? ETIMEDOUT : 0;
744f615cd67Sstsp }
745f615cd67Sstsp
746f615cd67Sstsp int
rtsx_write(struct rtsx_softc * sc,u_int16_t addr,u_int8_t mask,u_int8_t val)747f615cd67Sstsp rtsx_write(struct rtsx_softc *sc, u_int16_t addr, u_int8_t mask, u_int8_t val)
748f615cd67Sstsp {
749f615cd67Sstsp int tries = 1024;
750f615cd67Sstsp u_int32_t reg;
751f615cd67Sstsp
752f615cd67Sstsp WRITE4(sc, RTSX_HAIMR,
753f615cd67Sstsp RTSX_HAIMR_BUSY | RTSX_HAIMR_WRITE |
754f615cd67Sstsp (u_int32_t)(((addr & 0x3FFF) << 16) |
755f615cd67Sstsp (mask << 8) | val));
756f615cd67Sstsp
757f615cd67Sstsp while (tries--) {
758f615cd67Sstsp reg = READ4(sc, RTSX_HAIMR);
759f615cd67Sstsp if (!(reg & RTSX_HAIMR_BUSY)) {
760f615cd67Sstsp if (val != (reg & 0xff))
761f615cd67Sstsp return EIO;
762f615cd67Sstsp return 0;
763f615cd67Sstsp }
764f615cd67Sstsp }
765f615cd67Sstsp
766f615cd67Sstsp return ETIMEDOUT;
767f615cd67Sstsp }
768f615cd67Sstsp
769f615cd67Sstsp #ifdef notyet
770f615cd67Sstsp int
rtsx_read_phy(struct rtsx_softc * sc,u_int8_t addr,u_int16_t * val)771f615cd67Sstsp rtsx_read_phy(struct rtsx_softc *sc, u_int8_t addr, u_int16_t *val)
772f615cd67Sstsp {
773f615cd67Sstsp int timeout = 100000;
774f615cd67Sstsp u_int8_t data0;
775f615cd67Sstsp u_int8_t data1;
776f615cd67Sstsp u_int8_t rwctl;
777f615cd67Sstsp
778f615cd67Sstsp RTSX_WRITE(sc, RTSX_PHY_ADDR, addr);
779f615cd67Sstsp RTSX_WRITE(sc, RTSX_PHY_RWCTL, RTSX_PHY_BUSY|RTSX_PHY_READ);
780f615cd67Sstsp
781f615cd67Sstsp while (timeout--) {
782f615cd67Sstsp RTSX_READ(sc, RTSX_PHY_RWCTL, &rwctl);
783f615cd67Sstsp if (!(rwctl & RTSX_PHY_BUSY))
784f615cd67Sstsp break;
785f615cd67Sstsp }
786f615cd67Sstsp
787f615cd67Sstsp if (timeout == 0)
788f615cd67Sstsp return ETIMEDOUT;
789f615cd67Sstsp
790f615cd67Sstsp RTSX_READ(sc, RTSX_PHY_DATA0, &data0);
791f615cd67Sstsp RTSX_READ(sc, RTSX_PHY_DATA1, &data1);
792f615cd67Sstsp *val = data0 | (data1 << 8);
793f615cd67Sstsp
794f615cd67Sstsp return 0;
795f615cd67Sstsp }
796f615cd67Sstsp #endif
797f615cd67Sstsp
798f615cd67Sstsp int
rtsx_write_phy(struct rtsx_softc * sc,u_int8_t addr,u_int16_t val)799f615cd67Sstsp rtsx_write_phy(struct rtsx_softc *sc, u_int8_t addr, u_int16_t val)
800f615cd67Sstsp {
801f615cd67Sstsp int timeout = 100000;
802f615cd67Sstsp u_int8_t rwctl;
803f615cd67Sstsp
804f615cd67Sstsp RTSX_WRITE(sc, RTSX_PHY_DATA0, val);
805f615cd67Sstsp RTSX_WRITE(sc, RTSX_PHY_DATA1, val >> 8);
806f615cd67Sstsp RTSX_WRITE(sc, RTSX_PHY_ADDR, addr);
807f615cd67Sstsp RTSX_WRITE(sc, RTSX_PHY_RWCTL, RTSX_PHY_BUSY|RTSX_PHY_WRITE);
808f615cd67Sstsp
809f615cd67Sstsp while (timeout--) {
810f615cd67Sstsp RTSX_READ(sc, RTSX_PHY_RWCTL, &rwctl);
811f615cd67Sstsp if (!(rwctl & RTSX_PHY_BUSY))
812f615cd67Sstsp break;
813f615cd67Sstsp }
814f615cd67Sstsp
815f615cd67Sstsp if (timeout == 0)
816f615cd67Sstsp return ETIMEDOUT;
817f615cd67Sstsp
818f615cd67Sstsp return 0;
819f615cd67Sstsp }
820f615cd67Sstsp
821f615cd67Sstsp int
rtsx_read_cfg(struct rtsx_softc * sc,u_int8_t func,u_int16_t addr,u_int32_t * val)822f615cd67Sstsp rtsx_read_cfg(struct rtsx_softc *sc, u_int8_t func, u_int16_t addr,
823f615cd67Sstsp u_int32_t *val)
824f615cd67Sstsp {
825f615cd67Sstsp int tries = 1024;
826f615cd67Sstsp u_int8_t data0, data1, data2, data3, rwctl;
827f615cd67Sstsp
828f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGADDR0, addr);
829f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGADDR1, addr >> 8);
830f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGRWCTL, RTSX_CFG_BUSY | (func & 0x03 << 4));
831f615cd67Sstsp
832f615cd67Sstsp while (tries--) {
833f615cd67Sstsp RTSX_READ(sc, RTSX_CFGRWCTL, &rwctl);
834f615cd67Sstsp if (!(rwctl & RTSX_CFG_BUSY))
835f615cd67Sstsp break;
836f615cd67Sstsp }
837f615cd67Sstsp
838f615cd67Sstsp if (tries == 0)
839f615cd67Sstsp return EIO;
840f615cd67Sstsp
841f615cd67Sstsp RTSX_READ(sc, RTSX_CFGDATA0, &data0);
842f615cd67Sstsp RTSX_READ(sc, RTSX_CFGDATA1, &data1);
843f615cd67Sstsp RTSX_READ(sc, RTSX_CFGDATA2, &data2);
844f615cd67Sstsp RTSX_READ(sc, RTSX_CFGDATA3, &data3);
845f615cd67Sstsp
846f615cd67Sstsp *val = (data3 << 24) | (data2 << 16) | (data1 << 8) | data0;
847f615cd67Sstsp
848f615cd67Sstsp return 0;
849f615cd67Sstsp }
850f615cd67Sstsp
851f615cd67Sstsp #ifdef notyet
852f615cd67Sstsp int
rtsx_write_cfg(struct rtsx_softc * sc,u_int8_t func,u_int16_t addr,u_int32_t mask,u_int32_t val)853f615cd67Sstsp rtsx_write_cfg(struct rtsx_softc *sc, u_int8_t func, u_int16_t addr,
854f615cd67Sstsp u_int32_t mask, u_int32_t val)
855f615cd67Sstsp {
856f615cd67Sstsp int i, writemask = 0, tries = 1024;
857f615cd67Sstsp u_int8_t rwctl;
858f615cd67Sstsp
859f615cd67Sstsp for (i = 0; i < 4; i++) {
860f615cd67Sstsp if (mask & 0xff) {
861f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGDATA0 + i, val & mask & 0xff);
862f615cd67Sstsp writemask |= (1 << i);
863f615cd67Sstsp }
864f615cd67Sstsp mask >>= 8;
865f615cd67Sstsp val >>= 8;
866f615cd67Sstsp }
867f615cd67Sstsp
868f615cd67Sstsp if (writemask) {
869f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGADDR0, addr);
870f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGADDR1, addr >> 8);
871f615cd67Sstsp RTSX_WRITE(sc, RTSX_CFGRWCTL,
872f615cd67Sstsp RTSX_CFG_BUSY | writemask | (func & 0x03 << 4));
873f615cd67Sstsp }
874f615cd67Sstsp
875f615cd67Sstsp while (tries--) {
876f615cd67Sstsp RTSX_READ(sc, RTSX_CFGRWCTL, &rwctl);
877f615cd67Sstsp if (!(rwctl & RTSX_CFG_BUSY))
878f615cd67Sstsp break;
879f615cd67Sstsp }
880f615cd67Sstsp
881f615cd67Sstsp if (tries == 0)
882f615cd67Sstsp return EIO;
883f615cd67Sstsp
884f615cd67Sstsp return 0;
885f615cd67Sstsp }
886f615cd67Sstsp #endif
887f615cd67Sstsp
888f615cd67Sstsp /* Append a properly encoded host command to the host command buffer. */
889f615cd67Sstsp void
rtsx_hostcmd(u_int32_t * cmdbuf,int * n,u_int8_t cmd,u_int16_t reg,u_int8_t mask,u_int8_t data)890f615cd67Sstsp rtsx_hostcmd(u_int32_t *cmdbuf, int *n, u_int8_t cmd, u_int16_t reg,
891f615cd67Sstsp u_int8_t mask, u_int8_t data)
892f615cd67Sstsp {
893f615cd67Sstsp KASSERT(*n < RTSX_HOSTCMD_MAX);
894f615cd67Sstsp
895f615cd67Sstsp cmdbuf[(*n)++] = htole32((u_int32_t)(cmd & 0x3) << 30) |
896f615cd67Sstsp ((u_int32_t)(reg & 0x3fff) << 16) |
897f615cd67Sstsp ((u_int32_t)(mask) << 8) |
898f615cd67Sstsp ((u_int32_t)data);
899f615cd67Sstsp }
900f615cd67Sstsp
901f615cd67Sstsp void
rtsx_save_regs(struct rtsx_softc * sc)902f615cd67Sstsp rtsx_save_regs(struct rtsx_softc *sc)
903f615cd67Sstsp {
904f615cd67Sstsp int s, i;
905f615cd67Sstsp u_int16_t reg;
906f615cd67Sstsp
907f615cd67Sstsp s = splsdmmc();
908f615cd67Sstsp
909f615cd67Sstsp i = 0;
910f615cd67Sstsp for (reg = 0xFDA0; reg < 0xFDAE; reg++)
911f615cd67Sstsp (void)rtsx_read(sc, reg, &sc->regs[i++]);
912f615cd67Sstsp for (reg = 0xFD52; reg < 0xFD69; reg++)
913f615cd67Sstsp (void)rtsx_read(sc, reg, &sc->regs[i++]);
914f615cd67Sstsp for (reg = 0xFE20; reg < 0xFE34; reg++)
915f615cd67Sstsp (void)rtsx_read(sc, reg, &sc->regs[i++]);
916f615cd67Sstsp
917f615cd67Sstsp sc->regs4[0] = READ4(sc, RTSX_HCBAR);
918f615cd67Sstsp sc->regs4[1] = READ4(sc, RTSX_HCBCTLR);
919f615cd67Sstsp sc->regs4[2] = READ4(sc, RTSX_HDBAR);
920f615cd67Sstsp sc->regs4[3] = READ4(sc, RTSX_HDBCTLR);
921f615cd67Sstsp sc->regs4[4] = READ4(sc, RTSX_HAIMR);
922f615cd67Sstsp sc->regs4[5] = READ4(sc, RTSX_BIER);
923f615cd67Sstsp /* Not saving RTSX_BIPR. */
924f615cd67Sstsp
925f615cd67Sstsp splx(s);
926f615cd67Sstsp }
927f615cd67Sstsp
928f615cd67Sstsp void
rtsx_restore_regs(struct rtsx_softc * sc)929f615cd67Sstsp rtsx_restore_regs(struct rtsx_softc *sc)
930f615cd67Sstsp {
931f615cd67Sstsp int s, i;
932f615cd67Sstsp u_int16_t reg;
933f615cd67Sstsp
934f615cd67Sstsp s = splsdmmc();
935f615cd67Sstsp
936f615cd67Sstsp WRITE4(sc, RTSX_HCBAR, sc->regs4[0]);
937f615cd67Sstsp WRITE4(sc, RTSX_HCBCTLR, sc->regs4[1]);
938f615cd67Sstsp WRITE4(sc, RTSX_HDBAR, sc->regs4[2]);
939f615cd67Sstsp WRITE4(sc, RTSX_HDBCTLR, sc->regs4[3]);
940f615cd67Sstsp WRITE4(sc, RTSX_HAIMR, sc->regs4[4]);
941f615cd67Sstsp WRITE4(sc, RTSX_BIER, sc->regs4[5]);
942f615cd67Sstsp /* Not writing RTSX_BIPR since doing so would clear it. */
943f615cd67Sstsp
944f615cd67Sstsp i = 0;
945f615cd67Sstsp for (reg = 0xFDA0; reg < 0xFDAE; reg++)
946f615cd67Sstsp (void)rtsx_write(sc, reg, 0xff, sc->regs[i++]);
947f615cd67Sstsp for (reg = 0xFD52; reg < 0xFD69; reg++)
948f615cd67Sstsp (void)rtsx_write(sc, reg, 0xff, sc->regs[i++]);
949f615cd67Sstsp for (reg = 0xFE20; reg < 0xFE34; reg++)
950f615cd67Sstsp (void)rtsx_write(sc, reg, 0xff, sc->regs[i++]);
951f615cd67Sstsp
952f615cd67Sstsp splx(s);
953f615cd67Sstsp }
954f615cd67Sstsp
955f615cd67Sstsp u_int8_t
rtsx_response_type(u_int16_t sdmmc_rsp)956f615cd67Sstsp rtsx_response_type(u_int16_t sdmmc_rsp)
957f615cd67Sstsp {
958f615cd67Sstsp int i;
959f615cd67Sstsp struct rsp_type {
960f615cd67Sstsp u_int16_t sdmmc_rsp;
961f615cd67Sstsp u_int8_t rtsx_rsp;
962f615cd67Sstsp } rsp_types[] = {
963f615cd67Sstsp { SCF_RSP_R0, RTSX_SD_RSP_TYPE_R0 },
964f615cd67Sstsp { SCF_RSP_R1, RTSX_SD_RSP_TYPE_R1 },
965f615cd67Sstsp { SCF_RSP_R1B, RTSX_SD_RSP_TYPE_R1B },
966f615cd67Sstsp { SCF_RSP_R2, RTSX_SD_RSP_TYPE_R2 },
967f615cd67Sstsp { SCF_RSP_R3, RTSX_SD_RSP_TYPE_R3 },
968f615cd67Sstsp { SCF_RSP_R4, RTSX_SD_RSP_TYPE_R4 },
969f615cd67Sstsp { SCF_RSP_R5, RTSX_SD_RSP_TYPE_R5 },
970f615cd67Sstsp { SCF_RSP_R6, RTSX_SD_RSP_TYPE_R6 },
971f615cd67Sstsp { SCF_RSP_R7, RTSX_SD_RSP_TYPE_R7 }
972f615cd67Sstsp };
973f615cd67Sstsp
974f615cd67Sstsp for (i = 0; i < nitems(rsp_types); i++) {
975f615cd67Sstsp if (sdmmc_rsp == rsp_types[i].sdmmc_rsp)
976f615cd67Sstsp return rsp_types[i].rtsx_rsp;
977f615cd67Sstsp }
978f615cd67Sstsp
979f615cd67Sstsp return 0;
980f615cd67Sstsp }
981f615cd67Sstsp
982f615cd67Sstsp int
rtsx_hostcmd_send(struct rtsx_softc * sc,int ncmd)983b36d9b34Sstsp rtsx_hostcmd_send(struct rtsx_softc *sc, int ncmd)
984f615cd67Sstsp {
985b36d9b34Sstsp int s;
986f615cd67Sstsp
987f615cd67Sstsp s = splsdmmc();
988f615cd67Sstsp
989f615cd67Sstsp /* Tell the chip where the command buffer is and run the commands. */
990f615cd67Sstsp WRITE4(sc, RTSX_HCBAR, sc->dmap_cmd->dm_segs[0].ds_addr);
991f615cd67Sstsp WRITE4(sc, RTSX_HCBCTLR,
992f615cd67Sstsp ((ncmd * 4) & 0x00ffffff) | RTSX_START_CMD | RTSX_HW_AUTO_RSP);
993f615cd67Sstsp
994f615cd67Sstsp splx(s);
995f615cd67Sstsp
996b36d9b34Sstsp return 0;
997f615cd67Sstsp }
998f615cd67Sstsp
999f615cd67Sstsp int
rtsx_xfer_exec(struct rtsx_softc * sc,bus_dmamap_t dmap,int dmaflags)1000e49248d7Sstsp rtsx_xfer_exec(struct rtsx_softc *sc, bus_dmamap_t dmap, int dmaflags)
1001e49248d7Sstsp {
1002e49248d7Sstsp int s = splsdmmc();
1003e49248d7Sstsp
1004e49248d7Sstsp /* Tell the chip where the data buffer is and run the transfer. */
1005e49248d7Sstsp WRITE4(sc, RTSX_HDBAR, dmap->dm_segs[0].ds_addr);
1006e49248d7Sstsp WRITE4(sc, RTSX_HDBCTLR, dmaflags);
1007e49248d7Sstsp
1008e49248d7Sstsp splx(s);
1009e49248d7Sstsp
1010e49248d7Sstsp /* Wait for completion. */
1011*7f6f7fd3Scheloha return rtsx_wait_intr(sc, RTSX_TRANS_OK_INT, 10);
1012e49248d7Sstsp }
1013e49248d7Sstsp
1014e49248d7Sstsp int
rtsx_xfer(struct rtsx_softc * sc,struct sdmmc_command * cmd,u_int32_t * cmdbuf)1015f615cd67Sstsp rtsx_xfer(struct rtsx_softc *sc, struct sdmmc_command *cmd, u_int32_t *cmdbuf)
1016f615cd67Sstsp {
1017e49248d7Sstsp int ncmd, dma_dir, error, tmode;
1018f615cd67Sstsp int read = ISSET(cmd->c_flags, SCF_CMD_READ);
1019f615cd67Sstsp u_int8_t cfg2;
1020f615cd67Sstsp
1021f615cd67Sstsp DPRINTF(3,("%s: %s xfer: %d bytes with block size %d\n", DEVNAME(sc),
1022f615cd67Sstsp read ? "read" : "write",
1023f615cd67Sstsp cmd->c_datalen, cmd->c_blklen));
1024f615cd67Sstsp
1025f615cd67Sstsp if (cmd->c_datalen > RTSX_DMA_DATA_BUFSIZE) {
1026f615cd67Sstsp DPRINTF(3, ("%s: cmd->c_datalen too large: %d > %d\n",
1027f615cd67Sstsp DEVNAME(sc), cmd->c_datalen, RTSX_DMA_DATA_BUFSIZE));
1028f615cd67Sstsp return ENOMEM;
1029f615cd67Sstsp }
1030f615cd67Sstsp
1031f615cd67Sstsp /* Configure DMA transfer mode parameters. */
1032f615cd67Sstsp cfg2 = RTSX_SD_NO_CHECK_WAIT_CRC_TO | RTSX_SD_CHECK_CRC16 |
1033f615cd67Sstsp RTSX_SD_NO_WAIT_BUSY_END | RTSX_SD_RSP_LEN_0;
1034f615cd67Sstsp if (read) {
1035f615cd67Sstsp dma_dir = RTSX_DMA_DIR_FROM_CARD;
1036f615cd67Sstsp /* Use transfer mode AUTO_READ3, which assumes we've already
1037f615cd67Sstsp * sent the read command and gotten the response, and will
1038f615cd67Sstsp * send CMD 12 manually after reading multiple blocks. */
1039f615cd67Sstsp tmode = RTSX_TM_AUTO_READ3;
1040f615cd67Sstsp cfg2 |= RTSX_SD_CALCULATE_CRC7 | RTSX_SD_CHECK_CRC7;
1041f615cd67Sstsp } else {
1042f615cd67Sstsp dma_dir = RTSX_DMA_DIR_TO_CARD;
1043f615cd67Sstsp /* Use transfer mode AUTO_WRITE3, which assumes we've already
1044f615cd67Sstsp * sent the write command and gotten the response, and will
1045f615cd67Sstsp * send CMD 12 manually after writing multiple blocks. */
1046f615cd67Sstsp tmode = RTSX_TM_AUTO_WRITE3;
1047f615cd67Sstsp cfg2 |= RTSX_SD_NO_CALCULATE_CRC7 | RTSX_SD_NO_CHECK_CRC7;
1048f615cd67Sstsp }
1049f615cd67Sstsp
1050f615cd67Sstsp ncmd = 0;
1051f615cd67Sstsp
1052f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd, RTSX_WRITE_REG_CMD, RTSX_SD_CFG2,
1053f615cd67Sstsp 0xff, cfg2);
1054f615cd67Sstsp
1055f615cd67Sstsp /* Queue commands to configure data transfer size. */
1056f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
105798dad174Skettenis RTSX_WRITE_REG_CMD, RTSX_SD_BYTE_CNT_L, 0xff,
105898dad174Skettenis (cmd->c_blklen & 0xff));
1059f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
106098dad174Skettenis RTSX_WRITE_REG_CMD, RTSX_SD_BYTE_CNT_H, 0xff,
106198dad174Skettenis (cmd->c_blklen >> 8));
1062f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1063f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_BLOCK_CNT_L, 0xff,
1064f615cd67Sstsp ((cmd->c_datalen / cmd->c_blklen) & 0xff));
1065f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1066f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_BLOCK_CNT_H, 0xff,
1067f615cd67Sstsp ((cmd->c_datalen / cmd->c_blklen) >> 8));
1068f615cd67Sstsp
1069f615cd67Sstsp /* Use the DMA ring buffer for commands which transfer data. */
1070f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1071f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_CARD_DATA_SOURCE, 0x01, RTSX_RING_BUFFER);
1072f615cd67Sstsp
1073f615cd67Sstsp /* Configure DMA controller. */
1074f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd, RTSX_WRITE_REG_CMD, RTSX_IRQSTAT0,
1075f615cd67Sstsp RTSX_DMA_DONE_INT, RTSX_DMA_DONE_INT);
1076f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1077f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_DMATC3, 0xff, cmd->c_datalen >> 24);
1078f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1079f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_DMATC2, 0xff, cmd->c_datalen >> 16);
1080f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1081f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_DMATC1, 0xff, cmd->c_datalen >> 8);
1082f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1083f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_DMATC0, 0xff, cmd->c_datalen);
1084f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1085f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_DMACTL,
1086f615cd67Sstsp 0x03 | RTSX_DMA_PACK_SIZE_MASK,
1087f615cd67Sstsp dma_dir | RTSX_DMA_EN | RTSX_DMA_512);
1088f615cd67Sstsp
1089f615cd67Sstsp /* Queue commands to perform SD transfer. */
1090f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1091f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER,
1092f615cd67Sstsp 0xff, tmode | RTSX_SD_TRANSFER_START);
1093f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1094f615cd67Sstsp RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER,
1095f615cd67Sstsp RTSX_SD_TRANSFER_END, RTSX_SD_TRANSFER_END);
1096f615cd67Sstsp
1097b36d9b34Sstsp error = rtsx_hostcmd_send(sc, ncmd);
1098f615cd67Sstsp if (error)
1099f615cd67Sstsp goto ret;
1100f615cd67Sstsp
1101e49248d7Sstsp if (cmd->c_dmamap)
1102e49248d7Sstsp error = rtsx_xfer_adma(sc, cmd);
1103e49248d7Sstsp else
1104e49248d7Sstsp error = rtsx_xfer_bounce(sc, cmd);
1105e49248d7Sstsp ret:
1106e49248d7Sstsp DPRINTF(3,("%s: xfer done, error=%d\n", DEVNAME(sc), error));
1107e49248d7Sstsp return error;
1108e49248d7Sstsp }
1109e49248d7Sstsp
1110e49248d7Sstsp int
rtsx_xfer_bounce(struct rtsx_softc * sc,struct sdmmc_command * cmd)1111e49248d7Sstsp rtsx_xfer_bounce(struct rtsx_softc *sc, struct sdmmc_command *cmd)
1112e49248d7Sstsp {
1113e49248d7Sstsp caddr_t datakvap;
1114e49248d7Sstsp bus_dma_segment_t segs;
1115e49248d7Sstsp int rsegs, error;
1116e49248d7Sstsp int read = ISSET(cmd->c_flags, SCF_CMD_READ);
1117e49248d7Sstsp
1118e49248d7Sstsp /* Allocate and map DMA bounce buffer for data transfer. */
1119f615cd67Sstsp error = bus_dmamem_alloc(sc->dmat, cmd->c_datalen, 0, 0, &segs, 1,
1120f615cd67Sstsp &rsegs, BUS_DMA_WAITOK|BUS_DMA_ZERO);
1121f615cd67Sstsp if (error) {
1122f615cd67Sstsp DPRINTF(3, ("%s: could not allocate %d bytes\n",
1123f615cd67Sstsp DEVNAME(sc), cmd->c_datalen));
1124e49248d7Sstsp return error;
1125f615cd67Sstsp }
1126f615cd67Sstsp error = bus_dmamem_map(sc->dmat, &segs, rsegs, cmd->c_datalen,
1127f615cd67Sstsp &datakvap, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
1128f615cd67Sstsp if (error) {
1129f615cd67Sstsp DPRINTF(3, ("%s: could not map data buffer\n", DEVNAME(sc)));
1130f615cd67Sstsp goto free_databuf;
1131f615cd67Sstsp }
1132f615cd67Sstsp
1133f615cd67Sstsp /* If this is a write, copy data from sdmmc-provided buffer. */
1134f615cd67Sstsp if (!read)
1135f615cd67Sstsp memcpy(datakvap, cmd->c_data, cmd->c_datalen);
1136f615cd67Sstsp
1137f615cd67Sstsp /* Load the data buffer and sync it. */
1138f615cd67Sstsp error = bus_dmamap_load(sc->dmat, sc->dmap_data, datakvap,
1139f615cd67Sstsp cmd->c_datalen, NULL, BUS_DMA_WAITOK);
1140f615cd67Sstsp if (error) {
1141f615cd67Sstsp DPRINTF(3, ("%s: could not load DMA map\n", DEVNAME(sc)));
1142f615cd67Sstsp goto unmap_databuf;
1143f615cd67Sstsp }
1144f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_data, 0, cmd->c_datalen,
1145f615cd67Sstsp BUS_DMASYNC_PREREAD);
1146f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_data, 0, cmd->c_datalen,
1147f615cd67Sstsp BUS_DMASYNC_PREWRITE);
1148f615cd67Sstsp
1149e49248d7Sstsp error = rtsx_xfer_exec(sc, sc->dmap_data,
1150e49248d7Sstsp RTSX_TRIG_DMA | (read ? RTSX_DMA_READ : 0) |
1151e49248d7Sstsp (cmd->c_datalen & 0x00ffffff));
1152f615cd67Sstsp if (error)
1153f615cd67Sstsp goto unload_databuf;
1154f615cd67Sstsp
1155f615cd67Sstsp /* Sync and unload data DMA buffer. */
1156f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_data, 0, cmd->c_datalen,
1157f615cd67Sstsp BUS_DMASYNC_POSTREAD);
1158f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_data, 0, cmd->c_datalen,
1159f615cd67Sstsp BUS_DMASYNC_POSTWRITE);
1160f615cd67Sstsp
1161f615cd67Sstsp unload_databuf:
1162f615cd67Sstsp bus_dmamap_unload(sc->dmat, sc->dmap_data);
1163f615cd67Sstsp
1164f615cd67Sstsp /* If this is a read, copy data into sdmmc-provided buffer. */
1165f615cd67Sstsp if (error == 0 && read)
1166f615cd67Sstsp memcpy(cmd->c_data, datakvap, cmd->c_datalen);
1167f615cd67Sstsp
1168f615cd67Sstsp /* Free DMA data buffer. */
1169f615cd67Sstsp unmap_databuf:
1170f615cd67Sstsp bus_dmamem_unmap(sc->dmat, datakvap, cmd->c_datalen);
1171f615cd67Sstsp free_databuf:
1172f615cd67Sstsp bus_dmamem_free(sc->dmat, &segs, rsegs);
1173e49248d7Sstsp return error;
1174e49248d7Sstsp }
1175e49248d7Sstsp
1176e49248d7Sstsp int
rtsx_xfer_adma(struct rtsx_softc * sc,struct sdmmc_command * cmd)1177e49248d7Sstsp rtsx_xfer_adma(struct rtsx_softc *sc, struct sdmmc_command *cmd)
1178e49248d7Sstsp {
1179e49248d7Sstsp int i, error;
1180e49248d7Sstsp uint64_t *descp;
1181e49248d7Sstsp int read = ISSET(cmd->c_flags, SCF_CMD_READ);
1182e49248d7Sstsp
1183e49248d7Sstsp /* Initialize scatter-gather transfer descriptors. */
1184e49248d7Sstsp descp = (uint64_t *)sc->admabuf;
1185e49248d7Sstsp for (i = 0; i < cmd->c_dmamap->dm_nsegs; i++) {
11868bb9649aSstsp uint64_t paddr = cmd->c_dmamap->dm_segs[i].ds_addr;
1187e49248d7Sstsp uint64_t len = cmd->c_dmamap->dm_segs[i].ds_len;
1188e49248d7Sstsp uint8_t sgflags = RTSX_SG_VALID | RTSX_SG_TRANS_DATA;
1189e49248d7Sstsp uint64_t desc;
1190e49248d7Sstsp
1191e49248d7Sstsp if (i == cmd->c_dmamap->dm_nsegs - 1)
1192e49248d7Sstsp sgflags |= RTSX_SG_END;
1193e49248d7Sstsp len &= 0x00ffffff;
1194e49248d7Sstsp desc = htole64((paddr << 32) | (len << 12) | sgflags);
1195e49248d7Sstsp memcpy(descp, &desc, sizeof(*descp));
1196e49248d7Sstsp descp++;
1197e49248d7Sstsp }
1198e49248d7Sstsp
1199e49248d7Sstsp error = bus_dmamap_load(sc->dmat, sc->dmap_adma, sc->admabuf,
1200e49248d7Sstsp RTSX_ADMA_DESC_SIZE, NULL, BUS_DMA_WAITOK);
1201e49248d7Sstsp if (error) {
1202e49248d7Sstsp DPRINTF(3, ("%s: could not load DMA map\n", DEVNAME(sc)));
1203e49248d7Sstsp return error;
1204e49248d7Sstsp }
1205e49248d7Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_adma, 0, RTSX_ADMA_DESC_SIZE,
1206e49248d7Sstsp BUS_DMASYNC_PREWRITE);
1207e49248d7Sstsp
1208e49248d7Sstsp error = rtsx_xfer_exec(sc, sc->dmap_adma,
1209e49248d7Sstsp RTSX_ADMA_MODE | RTSX_TRIG_DMA | (read ? RTSX_DMA_READ : 0));
1210e49248d7Sstsp
1211e49248d7Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_adma, 0, RTSX_ADMA_DESC_SIZE,
1212e49248d7Sstsp BUS_DMASYNC_POSTWRITE);
1213e49248d7Sstsp
1214e49248d7Sstsp bus_dmamap_unload(sc->dmat, sc->dmap_adma);
1215f615cd67Sstsp return error;
1216f615cd67Sstsp }
1217f615cd67Sstsp
1218f615cd67Sstsp void
rtsx_exec_command(sdmmc_chipset_handle_t sch,struct sdmmc_command * cmd)1219f615cd67Sstsp rtsx_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
1220f615cd67Sstsp {
1221f615cd67Sstsp struct rtsx_softc *sc = sch;
1222f615cd67Sstsp bus_dma_segment_t segs;
1223f615cd67Sstsp int rsegs;
1224f615cd67Sstsp caddr_t cmdkvap;
1225f615cd67Sstsp u_int32_t *cmdbuf;
1226f615cd67Sstsp u_int8_t rsp_type;
1227f615cd67Sstsp u_int16_t r;
1228f615cd67Sstsp int ncmd;
1229f615cd67Sstsp int error = 0;
1230f615cd67Sstsp
1231f615cd67Sstsp DPRINTF(3,("%s: executing cmd %hu\n", DEVNAME(sc), cmd->c_opcode));
1232f615cd67Sstsp
1233f615cd67Sstsp /* Refuse SDIO probe if the chip doesn't support SDIO. */
1234f615cd67Sstsp if (cmd->c_opcode == SD_IO_SEND_OP_COND &&
1235f615cd67Sstsp !ISSET(sc->flags, RTSX_F_SDIO_SUPPORT)) {
1236f615cd67Sstsp error = ENOTSUP;
1237f615cd67Sstsp goto ret;
1238f615cd67Sstsp }
1239f615cd67Sstsp
1240f615cd67Sstsp rsp_type = rtsx_response_type(cmd->c_flags & 0xff00);
1241f615cd67Sstsp if (rsp_type == 0) {
1242f615cd67Sstsp printf("%s: unknown response type 0x%x\n", DEVNAME(sc),
1243f615cd67Sstsp (cmd->c_flags & 0xff00));
1244f615cd67Sstsp error = EINVAL;
1245f615cd67Sstsp goto ret;
1246f615cd67Sstsp }
1247f615cd67Sstsp
1248f615cd67Sstsp /* Allocate and map the host command buffer. */
1249f615cd67Sstsp error = bus_dmamem_alloc(sc->dmat, RTSX_HOSTCMD_BUFSIZE, 0, 0, &segs, 1,
1250f615cd67Sstsp &rsegs, BUS_DMA_WAITOK|BUS_DMA_ZERO);
1251f615cd67Sstsp if (error)
1252f615cd67Sstsp goto ret;
1253f615cd67Sstsp error = bus_dmamem_map(sc->dmat, &segs, rsegs, RTSX_HOSTCMD_BUFSIZE,
1254f615cd67Sstsp &cmdkvap, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
1255f615cd67Sstsp if (error)
1256f615cd67Sstsp goto free_cmdbuf;
1257f615cd67Sstsp
1258f615cd67Sstsp /* The command buffer queues commands the host controller will
1259f615cd67Sstsp * run asynchronously. */
1260f615cd67Sstsp cmdbuf = (u_int32_t *)cmdkvap;
1261f615cd67Sstsp ncmd = 0;
1262f615cd67Sstsp
1263f615cd67Sstsp /* Queue commands to set SD command index and argument. */
1264f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1265f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_CMD0, 0xff, 0x40 | cmd->c_opcode);
1266f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1267f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_CMD1, 0xff, cmd->c_arg >> 24);
1268f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1269f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_CMD2, 0xff, cmd->c_arg >> 16);
1270f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1271f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_CMD3, 0xff, cmd->c_arg >> 8);
1272f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1273f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_CMD4, 0xff, cmd->c_arg);
1274f615cd67Sstsp
1275f615cd67Sstsp /* Queue command to set response type. */
1276f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1277f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_CFG2, 0xff, rsp_type);
1278f615cd67Sstsp
1279f615cd67Sstsp /* Use the ping-pong buffer for commands which do not transfer data. */
1280f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1281f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_CARD_DATA_SOURCE,
1282f615cd67Sstsp 0x01, RTSX_PINGPONG_BUFFER);
1283f615cd67Sstsp
1284f615cd67Sstsp /* Queue commands to perform SD transfer. */
1285f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1286f615cd67Sstsp RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER,
1287f615cd67Sstsp 0xff, RTSX_TM_CMD_RSP | RTSX_SD_TRANSFER_START);
1288f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd,
1289f615cd67Sstsp RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER,
1290f615cd67Sstsp RTSX_SD_TRANSFER_END|RTSX_SD_STAT_IDLE,
1291f615cd67Sstsp RTSX_SD_TRANSFER_END|RTSX_SD_STAT_IDLE);
1292f615cd67Sstsp
1293f615cd67Sstsp /* Queue commands to read back card status response.*/
1294f615cd67Sstsp if (rsp_type == RTSX_SD_RSP_TYPE_R2) {
1295f615cd67Sstsp for (r = RTSX_PPBUF_BASE2 + 15; r > RTSX_PPBUF_BASE2; r--)
1296f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd, RTSX_READ_REG_CMD, r, 0, 0);
1297f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd, RTSX_READ_REG_CMD, RTSX_SD_CMD5,
1298f615cd67Sstsp 0, 0);
1299f615cd67Sstsp } else if (rsp_type != RTSX_SD_RSP_TYPE_R0) {
1300f615cd67Sstsp for (r = RTSX_SD_CMD0; r <= RTSX_SD_CMD4; r++)
1301f615cd67Sstsp rtsx_hostcmd(cmdbuf, &ncmd, RTSX_READ_REG_CMD, r, 0, 0);
1302f615cd67Sstsp }
1303f615cd67Sstsp
1304f615cd67Sstsp /* Load and sync command DMA buffer. */
1305f615cd67Sstsp error = bus_dmamap_load(sc->dmat, sc->dmap_cmd, cmdkvap,
1306f615cd67Sstsp RTSX_HOSTCMD_BUFSIZE, NULL, BUS_DMA_WAITOK);
1307f615cd67Sstsp if (error)
1308f615cd67Sstsp goto unmap_cmdbuf;
1309f615cd67Sstsp
1310f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_cmd, 0, RTSX_HOSTCMD_BUFSIZE,
1311f615cd67Sstsp BUS_DMASYNC_PREREAD);
1312f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_cmd, 0, RTSX_HOSTCMD_BUFSIZE,
1313f615cd67Sstsp BUS_DMASYNC_PREWRITE);
1314f615cd67Sstsp
1315f615cd67Sstsp /* Run the command queue and wait for completion. */
1316b36d9b34Sstsp error = rtsx_hostcmd_send(sc, ncmd);
1317b36d9b34Sstsp if (error == 0)
1318*7f6f7fd3Scheloha error = rtsx_wait_intr(sc, RTSX_TRANS_OK_INT, 1);
1319f615cd67Sstsp if (error)
1320f615cd67Sstsp goto unload_cmdbuf;
1321f615cd67Sstsp
1322f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_cmd, 0, RTSX_HOSTCMD_BUFSIZE,
1323f615cd67Sstsp BUS_DMASYNC_POSTREAD);
1324f615cd67Sstsp bus_dmamap_sync(sc->dmat, sc->dmap_cmd, 0, RTSX_HOSTCMD_BUFSIZE,
1325f615cd67Sstsp BUS_DMASYNC_POSTWRITE);
1326f615cd67Sstsp
1327f615cd67Sstsp /* Copy card response into sdmmc response buffer. */
1328f615cd67Sstsp if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
1329f615cd67Sstsp /* Copy bytes like sdhc(4), which on little-endian uses
1330f615cd67Sstsp * different byte order for short and long responses... */
1331f615cd67Sstsp if (ISSET(cmd->c_flags, SCF_RSP_136)) {
1332f615cd67Sstsp memcpy(cmd->c_resp, cmdkvap + 1, sizeof(cmd->c_resp));
1333f615cd67Sstsp } else {
1334f615cd67Sstsp /* First byte is CHECK_REG_CMD return value, second
1335f615cd67Sstsp * one is the command op code -- we skip those. */
1336f615cd67Sstsp cmd->c_resp[0] =
1337f615cd67Sstsp ((betoh32(cmdbuf[0]) & 0x0000ffff) << 16) |
1338f615cd67Sstsp ((betoh32(cmdbuf[1]) & 0xffff0000) >> 16);
1339f615cd67Sstsp }
1340f615cd67Sstsp }
1341f615cd67Sstsp
1342f615cd67Sstsp if (cmd->c_data) {
1343f615cd67Sstsp error = rtsx_xfer(sc, cmd, cmdbuf);
1344f615cd67Sstsp if (error) {
1345f615cd67Sstsp u_int8_t stat1;
1346f615cd67Sstsp
1347f615cd67Sstsp if (rtsx_read(sc, RTSX_SD_STAT1, &stat1) == 0 &&
1348f615cd67Sstsp (stat1 & RTSX_SD_CRC_ERR))
1349f615cd67Sstsp printf("%s: CRC error\n", DEVNAME(sc));
1350f615cd67Sstsp }
1351f615cd67Sstsp }
1352f615cd67Sstsp
1353f615cd67Sstsp unload_cmdbuf:
1354f615cd67Sstsp bus_dmamap_unload(sc->dmat, sc->dmap_cmd);
1355f615cd67Sstsp unmap_cmdbuf:
1356f615cd67Sstsp bus_dmamem_unmap(sc->dmat, cmdkvap, RTSX_HOSTCMD_BUFSIZE);
1357f615cd67Sstsp free_cmdbuf:
1358f615cd67Sstsp bus_dmamem_free(sc->dmat, &segs, rsegs);
1359f615cd67Sstsp ret:
1360f615cd67Sstsp SET(cmd->c_flags, SCF_ITSDONE);
1361f615cd67Sstsp cmd->c_error = error;
1362f615cd67Sstsp }
1363f615cd67Sstsp
1364f615cd67Sstsp /* Prepare for another command. */
1365f615cd67Sstsp void
rtsx_soft_reset(struct rtsx_softc * sc)1366f615cd67Sstsp rtsx_soft_reset(struct rtsx_softc *sc)
1367f615cd67Sstsp {
1368f615cd67Sstsp DPRINTF(1,("%s: soft reset\n", DEVNAME(sc)));
1369f615cd67Sstsp
1370f615cd67Sstsp /* Stop command transfer. */
1371f615cd67Sstsp WRITE4(sc, RTSX_HCBCTLR, RTSX_STOP_CMD);
1372f615cd67Sstsp
1373f615cd67Sstsp (void)rtsx_write(sc, RTSX_CARD_STOP, RTSX_SD_STOP|RTSX_SD_CLR_ERR,
1374f615cd67Sstsp RTSX_SD_STOP|RTSX_SD_CLR_ERR);
1375f615cd67Sstsp
1376f615cd67Sstsp /* Stop DMA transfer. */
1377f615cd67Sstsp WRITE4(sc, RTSX_HDBCTLR, RTSX_STOP_DMA);
1378f615cd67Sstsp (void)rtsx_write(sc, RTSX_DMACTL, RTSX_DMA_RST, RTSX_DMA_RST);
1379f615cd67Sstsp
1380f615cd67Sstsp (void)rtsx_write(sc, RTSX_RBCTL, RTSX_RB_FLUSH, RTSX_RB_FLUSH);
1381f615cd67Sstsp }
1382f615cd67Sstsp
1383f615cd67Sstsp int
rtsx_wait_intr(struct rtsx_softc * sc,int mask,int secs)1384*7f6f7fd3Scheloha rtsx_wait_intr(struct rtsx_softc *sc, int mask, int secs)
1385f615cd67Sstsp {
1386f615cd67Sstsp int status;
1387f615cd67Sstsp int error = 0;
1388f615cd67Sstsp int s;
1389f615cd67Sstsp
1390f615cd67Sstsp mask |= RTSX_TRANS_FAIL_INT;
1391f615cd67Sstsp
1392f615cd67Sstsp s = splsdmmc();
1393f615cd67Sstsp status = sc->intr_status & mask;
1394f615cd67Sstsp while (status == 0) {
1395*7f6f7fd3Scheloha if (tsleep_nsec(&sc->intr_status, PRIBIO, "rtsxintr",
1396*7f6f7fd3Scheloha SEC_TO_NSEC(secs)) == EWOULDBLOCK) {
1397f615cd67Sstsp rtsx_soft_reset(sc);
1398f615cd67Sstsp error = ETIMEDOUT;
1399f615cd67Sstsp break;
1400f615cd67Sstsp }
1401f615cd67Sstsp status = sc->intr_status & mask;
1402f615cd67Sstsp }
1403f615cd67Sstsp sc->intr_status &= ~status;
1404f615cd67Sstsp
1405f615cd67Sstsp /* Has the card disappeared? */
1406f615cd67Sstsp if (!ISSET(sc->flags, RTSX_F_CARD_PRESENT))
1407f615cd67Sstsp error = ENODEV;
1408f615cd67Sstsp
1409f615cd67Sstsp splx(s);
1410f615cd67Sstsp
1411f615cd67Sstsp if (error == 0 && (status & RTSX_TRANS_FAIL_INT))
1412f615cd67Sstsp error = EIO;
1413f615cd67Sstsp
1414f615cd67Sstsp return error;
1415f615cd67Sstsp }
1416f615cd67Sstsp
1417f615cd67Sstsp void
rtsx_card_insert(struct rtsx_softc * sc)1418f615cd67Sstsp rtsx_card_insert(struct rtsx_softc *sc)
1419f615cd67Sstsp {
1420f615cd67Sstsp DPRINTF(1, ("%s: card inserted\n", DEVNAME(sc)));
1421f615cd67Sstsp
1422f615cd67Sstsp sc->flags |= RTSX_F_CARD_PRESENT;
1423f615cd67Sstsp (void)rtsx_led_enable(sc);
1424f615cd67Sstsp
1425f615cd67Sstsp /* Schedule card discovery task. */
1426f615cd67Sstsp sdmmc_needs_discover(sc->sdmmc);
1427f615cd67Sstsp }
1428f615cd67Sstsp
1429f615cd67Sstsp void
rtsx_card_eject(struct rtsx_softc * sc)1430f615cd67Sstsp rtsx_card_eject(struct rtsx_softc *sc)
1431f615cd67Sstsp {
1432f615cd67Sstsp DPRINTF(1, ("%s: card ejected\n", DEVNAME(sc)));
1433f615cd67Sstsp
1434f615cd67Sstsp sc->flags &= ~RTSX_F_CARD_PRESENT;
1435f615cd67Sstsp (void)rtsx_led_disable(sc);
1436f615cd67Sstsp
1437f615cd67Sstsp /* Schedule card discovery task. */
1438f615cd67Sstsp sdmmc_needs_discover(sc->sdmmc);
1439f615cd67Sstsp }
1440f615cd67Sstsp
1441f615cd67Sstsp /*
1442f615cd67Sstsp * Established by attachment driver at interrupt priority IPL_SDMMC.
1443f615cd67Sstsp */
1444f615cd67Sstsp int
rtsx_intr(void * arg)1445f615cd67Sstsp rtsx_intr(void *arg)
1446f615cd67Sstsp {
1447f615cd67Sstsp struct rtsx_softc *sc = arg;
1448f615cd67Sstsp u_int32_t enabled, status;
1449f615cd67Sstsp
1450f615cd67Sstsp enabled = READ4(sc, RTSX_BIER);
1451f615cd67Sstsp status = READ4(sc, RTSX_BIPR);
1452f615cd67Sstsp
1453f615cd67Sstsp /* Ack interrupts. */
1454f615cd67Sstsp WRITE4(sc, RTSX_BIPR, status);
1455f615cd67Sstsp
1456f615cd67Sstsp if (((enabled & status) == 0) || status == 0xffffffff)
1457f615cd67Sstsp return 0;
1458f615cd67Sstsp
1459f615cd67Sstsp if (status & RTSX_SD_INT) {
1460f615cd67Sstsp if (status & RTSX_SD_EXIST) {
1461f615cd67Sstsp if (!ISSET(sc->flags, RTSX_F_CARD_PRESENT))
1462f615cd67Sstsp rtsx_card_insert(sc);
1463f615cd67Sstsp } else {
1464f615cd67Sstsp rtsx_card_eject(sc);
1465f615cd67Sstsp }
1466f615cd67Sstsp }
1467f615cd67Sstsp
1468f615cd67Sstsp if (status & (RTSX_TRANS_OK_INT | RTSX_TRANS_FAIL_INT)) {
1469f615cd67Sstsp sc->intr_status |= status;
1470f615cd67Sstsp wakeup(&sc->intr_status);
1471f615cd67Sstsp }
1472f615cd67Sstsp
1473f615cd67Sstsp return 1;
1474f615cd67Sstsp }
1475