1926ce35aSJung-uk Kim /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3926ce35aSJung-uk Kim * 4926ce35aSJung-uk Kim * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> 5926ce35aSJung-uk Kim * Copyright (c) 2012 Stefan Sperling <stsp@openbsd.org> 6926ce35aSJung-uk Kim * Copyright (c) 2020 Henri Hennebert <hlh@restart.be> 7926ce35aSJung-uk Kim * Copyright (c) 2020 Gary Jennejohn <gj@freebsd.org> 8926ce35aSJung-uk Kim * Copyright (c) 2020 Jesper Schmitz Mouridsen <jsm@FreeBSD.org> 9926ce35aSJung-uk Kim * All rights reserved. 10926ce35aSJung-uk Kim * 11926ce35aSJung-uk Kim * Patch from: 12926ce35aSJung-uk Kim * - Lutz Bichler <Lutz.Bichler@gmail.com> 13926ce35aSJung-uk Kim * 14926ce35aSJung-uk Kim * Base on OpenBSD /sys/dev/pci/rtsx_pci.c & /dev/ic/rtsx.c 15926ce35aSJung-uk Kim * on Linux /drivers/mmc/host/rtsx_pci_sdmmc.c, 16926ce35aSJung-uk Kim * /include/linux/rtsx_pci.h & 17926ce35aSJung-uk Kim * /drivers/misc/cardreader/rtsx_pcr.c 18926ce35aSJung-uk Kim * on NetBSD /sys/dev/ic/rtsx.c 19926ce35aSJung-uk Kim * 20926ce35aSJung-uk Kim * Permission to use, copy, modify, and distribute this software for any 21926ce35aSJung-uk Kim * purpose with or without fee is hereby granted, provided that the above 22926ce35aSJung-uk Kim * copyright notice and this permission notice appear in all copies. 23926ce35aSJung-uk Kim * 24926ce35aSJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25926ce35aSJung-uk Kim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26926ce35aSJung-uk Kim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27926ce35aSJung-uk Kim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28926ce35aSJung-uk Kim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29926ce35aSJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30926ce35aSJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31926ce35aSJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32926ce35aSJung-uk Kim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33926ce35aSJung-uk Kim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34926ce35aSJung-uk Kim * SUCH DAMAGE. 35926ce35aSJung-uk Kim */ 36926ce35aSJung-uk Kim 37926ce35aSJung-uk Kim #include <sys/param.h> 38926ce35aSJung-uk Kim #include <sys/module.h> 39926ce35aSJung-uk Kim #include <sys/systm.h> /* For FreeBSD 11 */ 40926ce35aSJung-uk Kim #include <sys/types.h> /* For FreeBSD 11 */ 41926ce35aSJung-uk Kim #include <sys/errno.h> 42926ce35aSJung-uk Kim #include <sys/kernel.h> 43926ce35aSJung-uk Kim #include <sys/bus.h> 44926ce35aSJung-uk Kim #include <sys/endian.h> 45926ce35aSJung-uk Kim #include <machine/bus.h> 46926ce35aSJung-uk Kim #include <sys/mutex.h> 479d3bc163SHenri Hennebert #include <sys/malloc.h> 48926ce35aSJung-uk Kim #include <sys/rman.h> 49926ce35aSJung-uk Kim #include <sys/queue.h> 50926ce35aSJung-uk Kim #include <sys/taskqueue.h> 51926ce35aSJung-uk Kim #include <sys/sysctl.h> 52926ce35aSJung-uk Kim #include <dev/pci/pcivar.h> 53926ce35aSJung-uk Kim #include <dev/pci/pcireg.h> 54926ce35aSJung-uk Kim #include <dev/mmc/bridge.h> 55926ce35aSJung-uk Kim #include <dev/mmc/mmcreg.h> 56926ce35aSJung-uk Kim #include <dev/mmc/mmcbrvar.h> 57926ce35aSJung-uk Kim #include <machine/_inttypes.h> 58926ce35aSJung-uk Kim 59926ce35aSJung-uk Kim #include "opt_mmccam.h" 60926ce35aSJung-uk Kim 61926ce35aSJung-uk Kim #ifdef MMCCAM 62926ce35aSJung-uk Kim #include <cam/cam.h> 63926ce35aSJung-uk Kim #include <cam/cam_ccb.h> 64926ce35aSJung-uk Kim #include <cam/cam_debug.h> 65926ce35aSJung-uk Kim #include <cam/cam_sim.h> 66926ce35aSJung-uk Kim #include <cam/cam_xpt_sim.h> 678e9740b6SHenri Hennebert #include <cam/mmc/mmc_sim.h> 688e9740b6SHenri Hennebert #include "mmc_sim_if.h" 69926ce35aSJung-uk Kim #endif /* MMCCAM */ 70926ce35aSJung-uk Kim 71926ce35aSJung-uk Kim #include "rtsxreg.h" 72926ce35aSJung-uk Kim 73926ce35aSJung-uk Kim /* The softc holds our per-instance data. */ 74926ce35aSJung-uk Kim struct rtsx_softc { 75926ce35aSJung-uk Kim struct mtx rtsx_mtx; /* device mutex */ 76926ce35aSJung-uk Kim device_t rtsx_dev; /* device */ 77926ce35aSJung-uk Kim uint16_t rtsx_flags; /* device flags */ 78926ce35aSJung-uk Kim uint16_t rtsx_device_id; /* device ID */ 79926ce35aSJung-uk Kim device_t rtsx_mmc_dev; /* device of mmc bus */ 80926ce35aSJung-uk Kim uint32_t rtsx_intr_enabled; /* enabled interrupts */ 81926ce35aSJung-uk Kim uint32_t rtsx_intr_status; /* soft interrupt status */ 82926ce35aSJung-uk Kim int rtsx_irq_res_id; /* bus IRQ resource id */ 83926ce35aSJung-uk Kim struct resource *rtsx_irq_res; /* bus IRQ resource */ 84926ce35aSJung-uk Kim void *rtsx_irq_cookie; /* bus IRQ resource cookie */ 85926ce35aSJung-uk Kim struct callout rtsx_timeout_callout; /* callout for timeout */ 869d3bc163SHenri Hennebert int rtsx_timeout_cmd; /* interrupt timeout for setup commands */ 879d3bc163SHenri Hennebert int rtsx_timeout_io; /* interrupt timeout for I/O commands */ 88926ce35aSJung-uk Kim void (*rtsx_intr_trans_ok)(struct rtsx_softc *sc); 89926ce35aSJung-uk Kim /* function to call if transfer succeed */ 90926ce35aSJung-uk Kim void (*rtsx_intr_trans_ko)(struct rtsx_softc *sc); 91926ce35aSJung-uk Kim /* function to call if transfer fail */ 929d3bc163SHenri Hennebert 93926ce35aSJung-uk Kim struct timeout_task 94926ce35aSJung-uk Kim rtsx_card_insert_task; /* card insert delayed task */ 95926ce35aSJung-uk Kim struct task rtsx_card_remove_task; /* card remove task */ 96926ce35aSJung-uk Kim 972e883067SHenri Hennebert int rtsx_mem_res_id; /* bus memory resource id */ 982e883067SHenri Hennebert struct resource *rtsx_mem_res; /* bus memory resource */ 992e883067SHenri Hennebert bus_space_tag_t rtsx_mem_btag; /* host register set tag */ 1002e883067SHenri Hennebert bus_space_handle_t rtsx_mem_bhandle; /* host register set handle */ 101926ce35aSJung-uk Kim 102926ce35aSJung-uk Kim bus_dma_tag_t rtsx_cmd_dma_tag; /* DMA tag for command transfer */ 103926ce35aSJung-uk Kim bus_dmamap_t rtsx_cmd_dmamap; /* DMA map for command transfer */ 104926ce35aSJung-uk Kim void *rtsx_cmd_dmamem; /* DMA mem for command transfer */ 105926ce35aSJung-uk Kim bus_addr_t rtsx_cmd_buffer; /* device visible address of the DMA segment */ 106926ce35aSJung-uk Kim int rtsx_cmd_index; /* index in rtsx_cmd_buffer */ 107926ce35aSJung-uk Kim 108926ce35aSJung-uk Kim bus_dma_tag_t rtsx_data_dma_tag; /* DMA tag for data transfer */ 109926ce35aSJung-uk Kim bus_dmamap_t rtsx_data_dmamap; /* DMA map for data transfer */ 110926ce35aSJung-uk Kim void *rtsx_data_dmamem; /* DMA mem for data transfer */ 111926ce35aSJung-uk Kim bus_addr_t rtsx_data_buffer; /* device visible address of the DMA segment */ 112926ce35aSJung-uk Kim 113926ce35aSJung-uk Kim #ifdef MMCCAM 114926ce35aSJung-uk Kim union ccb *rtsx_ccb; /* CAM control block */ 1158e9740b6SHenri Hennebert struct mmc_sim rtsx_mmc_sim; /* CAM generic sim */ 116926ce35aSJung-uk Kim struct mmc_request rtsx_cam_req; /* CAM MMC request */ 117926ce35aSJung-uk Kim #endif /* MMCCAM */ 118926ce35aSJung-uk Kim 119926ce35aSJung-uk Kim struct mmc_request *rtsx_req; /* MMC request */ 120926ce35aSJung-uk Kim struct mmc_host rtsx_host; /* host parameters */ 121926ce35aSJung-uk Kim int rtsx_pcie_cap; /* PCIe capability offset */ 122926ce35aSJung-uk Kim int8_t rtsx_bus_busy; /* bus busy status */ 123926ce35aSJung-uk Kim int8_t rtsx_ios_bus_width; /* current host.ios.bus_width */ 124926ce35aSJung-uk Kim int32_t rtsx_ios_clock; /* current host.ios.clock */ 125926ce35aSJung-uk Kim int8_t rtsx_ios_power_mode; /* current host.ios.power mode */ 126926ce35aSJung-uk Kim int8_t rtsx_ios_timing; /* current host.ios.timing */ 127926ce35aSJung-uk Kim int8_t rtsx_ios_vccq; /* current host.ios.vccq */ 128926ce35aSJung-uk Kim uint8_t rtsx_read_only; /* card read only status */ 129926ce35aSJung-uk Kim uint8_t rtsx_inversion; /* inversion of card detection and read only status */ 130926ce35aSJung-uk Kim uint8_t rtsx_force_timing; /* force bus_timing_uhs_sdr50 */ 131577130e5SHenri Hennebert uint8_t rtsx_debug_mask; /* debugging mask */ 132577130e5SHenri Hennebert #define RTSX_DEBUG_BASIC 0x01 /* debug basic flow */ 133577130e5SHenri Hennebert #define RTSX_TRACE_SD_CMD 0x02 /* trace SD commands */ 134577130e5SHenri Hennebert #define RTSX_DEBUG_TUNING 0x04 /* debug tuning */ 135926ce35aSJung-uk Kim #ifdef MMCCAM 136926ce35aSJung-uk Kim uint8_t rtsx_cam_status; /* CAM status - 1 if card in use */ 137926ce35aSJung-uk Kim #endif /* MMCCAM */ 138926ce35aSJung-uk Kim uint64_t rtsx_read_count; /* count of read operations */ 139926ce35aSJung-uk Kim uint64_t rtsx_write_count; /* count of write operations */ 140926ce35aSJung-uk Kim bool rtsx_discovery_mode; /* are we in discovery mode? */ 141926ce35aSJung-uk Kim bool rtsx_tuning_mode; /* are we tuning */ 142926ce35aSJung-uk Kim bool rtsx_double_clk; /* double clock freqency */ 143926ce35aSJung-uk Kim bool rtsx_vpclk; /* voltage at Pulse-width Modulation(PWM) clock? */ 144926ce35aSJung-uk Kim uint8_t rtsx_ssc_depth; /* Spread spectrum clocking depth */ 145926ce35aSJung-uk Kim uint8_t rtsx_card_drive_sel; /* value for RTSX_CARD_DRIVE_SEL */ 146926ce35aSJung-uk Kim uint8_t rtsx_sd30_drive_sel_3v3;/* value for RTSX_SD30_DRIVE_SEL */ 147926ce35aSJung-uk Kim }; 148926ce35aSJung-uk Kim 149926ce35aSJung-uk Kim /* rtsx_flags values */ 150926ce35aSJung-uk Kim #define RTSX_F_DEFAULT 0x0000 151926ce35aSJung-uk Kim #define RTSX_F_CARD_PRESENT 0x0001 152926ce35aSJung-uk Kim #define RTSX_F_SDIO_SUPPORT 0x0002 153926ce35aSJung-uk Kim #define RTSX_F_VERSION_A 0x0004 154926ce35aSJung-uk Kim #define RTSX_F_VERSION_B 0x0008 155926ce35aSJung-uk Kim #define RTSX_F_VERSION_C 0x0010 156926ce35aSJung-uk Kim #define RTSX_F_VERSION_D 0x0020 157926ce35aSJung-uk Kim #define RTSX_F_8411B_QFN48 0x0040 158926ce35aSJung-uk Kim #define RTSX_F_REVERSE_SOCKET 0x0080 159926ce35aSJung-uk Kim 160926ce35aSJung-uk Kim #define RTSX_REALTEK 0x10ec 161926ce35aSJung-uk Kim #define RTSX_RTS5209 0x5209 162926ce35aSJung-uk Kim #define RTSX_RTS5227 0x5227 163926ce35aSJung-uk Kim #define RTSX_RTS5229 0x5229 164926ce35aSJung-uk Kim #define RTSX_RTS522A 0x522a 165926ce35aSJung-uk Kim #define RTSX_RTS525A 0x525a 166926ce35aSJung-uk Kim #define RTSX_RTS5249 0x5249 167577130e5SHenri Hennebert #define RTSX_RTS5260 0x5260 168926ce35aSJung-uk Kim #define RTSX_RTL8402 0x5286 169926ce35aSJung-uk Kim #define RTSX_RTL8411 0x5289 170926ce35aSJung-uk Kim #define RTSX_RTL8411B 0x5287 171926ce35aSJung-uk Kim 1728290c144SHenri Hennebert #define RTSX_VERSION "2.1g" 173926ce35aSJung-uk Kim 17471883128SHenri Hennebert static const struct rtsx_pciids { 175926ce35aSJung-uk Kim uint16_t device_id; 176926ce35aSJung-uk Kim const char *desc; 17771883128SHenri Hennebert } rtsx_ids[] = { 17871883128SHenri Hennebert { RTSX_RTS5209, RTSX_VERSION " Realtek RTS5209 PCIe SD Card Reader" }, 17971883128SHenri Hennebert { RTSX_RTS5227, RTSX_VERSION " Realtek RTS5227 PCIe SD Card Reader" }, 18071883128SHenri Hennebert { RTSX_RTS5229, RTSX_VERSION " Realtek RTS5229 PCIe SD Card Reader" }, 18171883128SHenri Hennebert { RTSX_RTS522A, RTSX_VERSION " Realtek RTS522A PCIe SD Card Reader" }, 18271883128SHenri Hennebert { RTSX_RTS525A, RTSX_VERSION " Realtek RTS525A PCIe SD Card Reader" }, 18371883128SHenri Hennebert { RTSX_RTS5249, RTSX_VERSION " Realtek RTS5249 PCIe SD Card Reader" }, 18471883128SHenri Hennebert { RTSX_RTS5260, RTSX_VERSION " Realtek RTS5260 PCIe SD Card Reader" }, 18571883128SHenri Hennebert { RTSX_RTL8402, RTSX_VERSION " Realtek RTL8402 PCIe SD Card Reader" }, 18671883128SHenri Hennebert { RTSX_RTL8411, RTSX_VERSION " Realtek RTL8411 PCIe SD Card Reader" }, 18771883128SHenri Hennebert { RTSX_RTL8411B, RTSX_VERSION " Realtek RTL8411B PCIe SD Card Reader" }, 188926ce35aSJung-uk Kim }; 189926ce35aSJung-uk Kim 1909d3bc163SHenri Hennebert /* See `kenv | grep smbios.system` */ 1919d3bc163SHenri Hennebert static const struct rtsx_inversion_model { 1929d3bc163SHenri Hennebert char *maker; 1939d3bc163SHenri Hennebert char *family; 1949d3bc163SHenri Hennebert char *product; 1959d3bc163SHenri Hennebert } rtsx_inversion_models[] = { 1969d3bc163SHenri Hennebert { "LENOVO", "ThinkPad T470p", "20J7S0PM00"}, 19771883128SHenri Hennebert { "LENOVO", "ThinkPad X13 Gen 1", "20UF000QRT"}, 1989d3bc163SHenri Hennebert { NULL, NULL, NULL} 1999d3bc163SHenri Hennebert }; 2009d3bc163SHenri Hennebert 201926ce35aSJung-uk Kim static int rtsx_dma_alloc(struct rtsx_softc *sc); 202926ce35aSJung-uk Kim static void rtsx_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error); 203926ce35aSJung-uk Kim static void rtsx_dma_free(struct rtsx_softc *sc); 204926ce35aSJung-uk Kim static void rtsx_intr(void *arg); 205926ce35aSJung-uk Kim static void rtsx_handle_card_present(struct rtsx_softc *sc); 206926ce35aSJung-uk Kim static void rtsx_card_task(void *arg, int pending __unused); 207926ce35aSJung-uk Kim static bool rtsx_is_card_present(struct rtsx_softc *sc); 208926ce35aSJung-uk Kim static int rtsx_init(struct rtsx_softc *sc); 209926ce35aSJung-uk Kim static int rtsx_map_sd_drive(int index); 210926ce35aSJung-uk Kim static int rtsx_rts5227_fill_driving(struct rtsx_softc *sc); 211926ce35aSJung-uk Kim static int rtsx_rts5249_fill_driving(struct rtsx_softc *sc); 212577130e5SHenri Hennebert static int rtsx_rts5260_fill_driving(struct rtsx_softc *sc); 213926ce35aSJung-uk Kim static int rtsx_read(struct rtsx_softc *, uint16_t, uint8_t *); 214926ce35aSJung-uk Kim static int rtsx_read_cfg(struct rtsx_softc *sc, uint8_t func, uint16_t addr, uint32_t *val); 215926ce35aSJung-uk Kim static int rtsx_write(struct rtsx_softc *sc, uint16_t addr, uint8_t mask, uint8_t val); 216926ce35aSJung-uk Kim static int rtsx_read_phy(struct rtsx_softc *sc, uint8_t addr, uint16_t *val); 217926ce35aSJung-uk Kim static int rtsx_write_phy(struct rtsx_softc *sc, uint8_t addr, uint16_t val); 218926ce35aSJung-uk Kim static int rtsx_bus_power_off(struct rtsx_softc *sc); 219926ce35aSJung-uk Kim static int rtsx_bus_power_on(struct rtsx_softc *sc); 220926ce35aSJung-uk Kim static int rtsx_set_bus_width(struct rtsx_softc *sc, enum mmc_bus_width width); 221926ce35aSJung-uk Kim static int rtsx_set_sd_timing(struct rtsx_softc *sc, enum mmc_bus_timing timing); 222926ce35aSJung-uk Kim static int rtsx_set_sd_clock(struct rtsx_softc *sc, uint32_t freq); 223926ce35aSJung-uk Kim static int rtsx_stop_sd_clock(struct rtsx_softc *sc); 224926ce35aSJung-uk Kim static int rtsx_switch_sd_clock(struct rtsx_softc *sc, uint8_t clk, uint8_t n, uint8_t div, uint8_t mcu); 2258e9740b6SHenri Hennebert #ifndef MMCCAM 226926ce35aSJung-uk Kim static void rtsx_sd_change_tx_phase(struct rtsx_softc *sc, uint8_t sample_point); 227926ce35aSJung-uk Kim static void rtsx_sd_change_rx_phase(struct rtsx_softc *sc, uint8_t sample_point); 228926ce35aSJung-uk Kim static void rtsx_sd_tuning_rx_phase(struct rtsx_softc *sc, uint32_t *phase_map); 229926ce35aSJung-uk Kim static int rtsx_sd_tuning_rx_cmd(struct rtsx_softc *sc, uint8_t sample_point); 230926ce35aSJung-uk Kim static int rtsx_sd_tuning_rx_cmd_wait(struct rtsx_softc *sc, struct mmc_command *cmd); 231926ce35aSJung-uk Kim static void rtsx_sd_tuning_rx_cmd_wakeup(struct rtsx_softc *sc); 232926ce35aSJung-uk Kim static void rtsx_sd_wait_data_idle(struct rtsx_softc *sc); 233926ce35aSJung-uk Kim static uint8_t rtsx_sd_search_final_rx_phase(struct rtsx_softc *sc, uint32_t phase_map); 234926ce35aSJung-uk Kim static int rtsx_sd_get_rx_phase_len(uint32_t phase_map, int start_bit); 2358e9740b6SHenri Hennebert #endif /* !MMCCAM */ 236926ce35aSJung-uk Kim #if 0 /* For led */ 237926ce35aSJung-uk Kim static int rtsx_led_enable(struct rtsx_softc *sc); 238926ce35aSJung-uk Kim static int rtsx_led_disable(struct rtsx_softc *sc); 239926ce35aSJung-uk Kim #endif /* For led */ 240926ce35aSJung-uk Kim static uint8_t rtsx_response_type(uint16_t mmc_rsp); 241926ce35aSJung-uk Kim static void rtsx_init_cmd(struct rtsx_softc *sc, struct mmc_command *cmd); 242926ce35aSJung-uk Kim static void rtsx_push_cmd(struct rtsx_softc *sc, uint8_t cmd, uint16_t reg, 243926ce35aSJung-uk Kim uint8_t mask, uint8_t data); 244926ce35aSJung-uk Kim static void rtsx_set_cmd_data_len(struct rtsx_softc *sc, uint16_t block_cnt, uint16_t byte_cnt); 245926ce35aSJung-uk Kim static void rtsx_send_cmd(struct rtsx_softc *sc); 246926ce35aSJung-uk Kim static void rtsx_ret_resp(struct rtsx_softc *sc); 247926ce35aSJung-uk Kim static void rtsx_set_resp(struct rtsx_softc *sc, struct mmc_command *cmd); 248926ce35aSJung-uk Kim static void rtsx_stop_cmd(struct rtsx_softc *sc); 249926ce35aSJung-uk Kim static void rtsx_clear_error(struct rtsx_softc *sc); 250926ce35aSJung-uk Kim static void rtsx_req_done(struct rtsx_softc *sc); 251926ce35aSJung-uk Kim static int rtsx_send_req(struct rtsx_softc *sc, struct mmc_command *cmd); 252926ce35aSJung-uk Kim static int rtsx_xfer_short(struct rtsx_softc *sc, struct mmc_command *cmd); 253926ce35aSJung-uk Kim static void rtsx_ask_ppbuf_part1(struct rtsx_softc *sc); 254926ce35aSJung-uk Kim static void rtsx_get_ppbuf_part1(struct rtsx_softc *sc); 255926ce35aSJung-uk Kim static void rtsx_get_ppbuf_part2(struct rtsx_softc *sc); 256926ce35aSJung-uk Kim static void rtsx_put_ppbuf_part1(struct rtsx_softc *sc); 257926ce35aSJung-uk Kim static void rtsx_put_ppbuf_part2(struct rtsx_softc *sc); 258926ce35aSJung-uk Kim static void rtsx_write_ppbuf(struct rtsx_softc *sc); 259926ce35aSJung-uk Kim static int rtsx_xfer(struct rtsx_softc *sc, struct mmc_command *cmd); 260926ce35aSJung-uk Kim static void rtsx_xfer_begin(struct rtsx_softc *sc); 261926ce35aSJung-uk Kim static void rtsx_xfer_start(struct rtsx_softc *sc); 262926ce35aSJung-uk Kim static void rtsx_xfer_finish(struct rtsx_softc *sc); 263926ce35aSJung-uk Kim static void rtsx_timeout(void *arg); 264926ce35aSJung-uk Kim 265926ce35aSJung-uk Kim #ifdef MMCCAM 2668e9740b6SHenri Hennebert static int rtsx_get_tran_settings(device_t dev, struct ccb_trans_settings_mmc *cts); 2678e9740b6SHenri Hennebert static int rtsx_set_tran_settings(device_t dev, struct ccb_trans_settings_mmc *cts); 2688e9740b6SHenri Hennebert static int rtsx_cam_request(device_t dev, union ccb *ccb); 269926ce35aSJung-uk Kim #endif /* MMCCAM */ 270926ce35aSJung-uk Kim 271926ce35aSJung-uk Kim static int rtsx_read_ivar(device_t bus, device_t child, int which, uintptr_t *result); 272926ce35aSJung-uk Kim static int rtsx_write_ivar(device_t bus, device_t child, int which, uintptr_t value); 273926ce35aSJung-uk Kim 274926ce35aSJung-uk Kim static int rtsx_mmcbr_update_ios(device_t bus, device_t child __unused); 275926ce35aSJung-uk Kim static int rtsx_mmcbr_switch_vccq(device_t bus, device_t child __unused); 2768e9740b6SHenri Hennebert static int rtsx_mmcbr_request(device_t bus, device_t child __unused, struct mmc_request *req); 2778e9740b6SHenri Hennebert #ifndef MMCCAM 278926ce35aSJung-uk Kim static int rtsx_mmcbr_tune(device_t bus, device_t child __unused, bool hs400 __unused); 279926ce35aSJung-uk Kim static int rtsx_mmcbr_retune(device_t bus, device_t child __unused, bool reset __unused); 280926ce35aSJung-uk Kim static int rtsx_mmcbr_get_ro(device_t bus, device_t child __unused); 281926ce35aSJung-uk Kim static int rtsx_mmcbr_acquire_host(device_t bus, device_t child __unused); 282926ce35aSJung-uk Kim static int rtsx_mmcbr_release_host(device_t bus, device_t child __unused); 2838e9740b6SHenri Hennebert #endif /* !MMCCAM */ 284926ce35aSJung-uk Kim 285926ce35aSJung-uk Kim static int rtsx_probe(device_t dev); 286926ce35aSJung-uk Kim static int rtsx_attach(device_t dev); 287926ce35aSJung-uk Kim static int rtsx_detach(device_t dev); 288926ce35aSJung-uk Kim static int rtsx_shutdown(device_t dev); 289926ce35aSJung-uk Kim static int rtsx_suspend(device_t dev); 290926ce35aSJung-uk Kim static int rtsx_resume(device_t dev); 291926ce35aSJung-uk Kim 292926ce35aSJung-uk Kim #define RTSX_LOCK_INIT(_sc) mtx_init(&(_sc)->rtsx_mtx, \ 293926ce35aSJung-uk Kim device_get_nameunit(sc->rtsx_dev), "rtsx", MTX_DEF) 294926ce35aSJung-uk Kim #define RTSX_LOCK(_sc) mtx_lock(&(_sc)->rtsx_mtx) 295926ce35aSJung-uk Kim #define RTSX_UNLOCK(_sc) mtx_unlock(&(_sc)->rtsx_mtx) 296926ce35aSJung-uk Kim #define RTSX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rtsx_mtx) 297926ce35aSJung-uk Kim 298926ce35aSJung-uk Kim #define RTSX_SDCLK_OFF 0 299926ce35aSJung-uk Kim #define RTSX_SDCLK_250KHZ 250000 300926ce35aSJung-uk Kim #define RTSX_SDCLK_400KHZ 400000 301926ce35aSJung-uk Kim #define RTSX_SDCLK_25MHZ 25000000 302926ce35aSJung-uk Kim #define RTSX_SDCLK_50MHZ 50000000 303926ce35aSJung-uk Kim #define RTSX_SDCLK_100MHZ 100000000 304926ce35aSJung-uk Kim #define RTSX_SDCLK_208MHZ 208000000 305926ce35aSJung-uk Kim 306926ce35aSJung-uk Kim #define RTSX_MIN_DIV_N 80 307926ce35aSJung-uk Kim #define RTSX_MAX_DIV_N 208 308926ce35aSJung-uk Kim 309926ce35aSJung-uk Kim #define RTSX_MAX_DATA_BLKLEN 512 310926ce35aSJung-uk Kim 311926ce35aSJung-uk Kim #define RTSX_DMA_ALIGN 4 312926ce35aSJung-uk Kim #define RTSX_HOSTCMD_MAX 256 313926ce35aSJung-uk Kim #define RTSX_DMA_CMD_BIFSIZE (sizeof(uint32_t) * RTSX_HOSTCMD_MAX) 31413a5a46cSAndrew Gallatin #define RTSX_DMA_DATA_BUFSIZE maxphys 315926ce35aSJung-uk Kim 316926ce35aSJung-uk Kim #define ISSET(t, f) ((t) & (f)) 317926ce35aSJung-uk Kim 318926ce35aSJung-uk Kim #define READ4(sc, reg) \ 3192e883067SHenri Hennebert (bus_space_read_4((sc)->rtsx_mem_btag, (sc)->rtsx_mem_bhandle, (reg))) 320926ce35aSJung-uk Kim #define WRITE4(sc, reg, val) \ 3212e883067SHenri Hennebert (bus_space_write_4((sc)->rtsx_mem_btag, (sc)->rtsx_mem_bhandle, (reg), (val))) 322926ce35aSJung-uk Kim 323926ce35aSJung-uk Kim #define RTSX_READ(sc, reg, val) \ 324926ce35aSJung-uk Kim do { \ 325926ce35aSJung-uk Kim int err = rtsx_read((sc), (reg), (val)); \ 326926ce35aSJung-uk Kim if (err) \ 327926ce35aSJung-uk Kim return (err); \ 328926ce35aSJung-uk Kim } while (0) 329926ce35aSJung-uk Kim 330926ce35aSJung-uk Kim #define RTSX_WRITE(sc, reg, val) \ 331926ce35aSJung-uk Kim do { \ 332926ce35aSJung-uk Kim int err = rtsx_write((sc), (reg), 0xff, (val)); \ 333926ce35aSJung-uk Kim if (err) \ 334926ce35aSJung-uk Kim return (err); \ 335926ce35aSJung-uk Kim } while (0) 336926ce35aSJung-uk Kim #define RTSX_CLR(sc, reg, bits) \ 337926ce35aSJung-uk Kim do { \ 338926ce35aSJung-uk Kim int err = rtsx_write((sc), (reg), (bits), 0); \ 339926ce35aSJung-uk Kim if (err) \ 340926ce35aSJung-uk Kim return (err); \ 341926ce35aSJung-uk Kim } while (0) 342926ce35aSJung-uk Kim 343926ce35aSJung-uk Kim #define RTSX_SET(sc, reg, bits) \ 344926ce35aSJung-uk Kim do { \ 345926ce35aSJung-uk Kim int err = rtsx_write((sc), (reg), (bits), 0xff);\ 346926ce35aSJung-uk Kim if (err) \ 347926ce35aSJung-uk Kim return (err); \ 348926ce35aSJung-uk Kim } while (0) 349926ce35aSJung-uk Kim 350926ce35aSJung-uk Kim #define RTSX_BITOP(sc, reg, mask, bits) \ 351926ce35aSJung-uk Kim do { \ 352926ce35aSJung-uk Kim int err = rtsx_write((sc), (reg), (mask), (bits)); \ 353926ce35aSJung-uk Kim if (err) \ 354926ce35aSJung-uk Kim return (err); \ 355926ce35aSJung-uk Kim } while (0) 356926ce35aSJung-uk Kim 357926ce35aSJung-uk Kim /* 358926ce35aSJung-uk Kim * We use two DMA buffers: a command buffer and a data buffer. 359926ce35aSJung-uk Kim * 360926ce35aSJung-uk Kim * The command buffer contains a command queue for the host controller, 361926ce35aSJung-uk Kim * which describes SD/MMC commands to run, and other parameters. The chip 362926ce35aSJung-uk Kim * runs the command queue when a special bit in the RTSX_HCBAR register is 363926ce35aSJung-uk Kim * set and signals completion with the RTSX_TRANS_OK_INT interrupt. 364926ce35aSJung-uk Kim * Each command is encoded as a 4 byte sequence containing command number 365926ce35aSJung-uk Kim * (read, write, or check a host controller register), a register address, 366926ce35aSJung-uk Kim * and a data bit-mask and value. 367926ce35aSJung-uk Kim * SD/MMC commands which do not transfer any data from/to the card only use 368926ce35aSJung-uk Kim * the command buffer. 369926ce35aSJung-uk Kim * 370926ce35aSJung-uk Kim * The data buffer is used for transfer longer than 512. Data transfer is 371926ce35aSJung-uk Kim * controlled via the RTSX_HDBAR register and completion is signalled by 372926ce35aSJung-uk Kim * the RTSX_TRANS_OK_INT interrupt. 373926ce35aSJung-uk Kim * 374926ce35aSJung-uk Kim * The chip is unable to perform DMA above 4GB. 375926ce35aSJung-uk Kim */ 376926ce35aSJung-uk Kim 377926ce35aSJung-uk Kim /* 378926ce35aSJung-uk Kim * Main commands in the usual seqence used: 379926ce35aSJung-uk Kim * 380926ce35aSJung-uk Kim * CMD0 Go idle state 381926ce35aSJung-uk Kim * CMD8 Send interface condition 382926ce35aSJung-uk Kim * CMD55 Application Command for next ACMD 383926ce35aSJung-uk Kim * ACMD41 Send Operation Conditions Register (OCR: voltage profile of the card) 384926ce35aSJung-uk Kim * CMD2 Send Card Identification (CID) Register 385926ce35aSJung-uk Kim * CMD3 Send relative address 386926ce35aSJung-uk Kim * CMD9 Send Card Specific Data (CSD) 387926ce35aSJung-uk Kim * CMD13 Send status (32 bits - bit 25: card password protected) 388926ce35aSJung-uk Kim * CMD7 Select card (before Get card SCR) 389926ce35aSJung-uk Kim * ACMD51 Send SCR (SD CARD Configuration Register - [51:48]: Bus widths supported) 390926ce35aSJung-uk Kim * CMD6 SD switch function 391926ce35aSJung-uk Kim * ACMD13 Send SD status (512 bits) 392926ce35aSJung-uk Kim * ACMD42 Set/Clear card detect 393926ce35aSJung-uk Kim * ACMD6 Set bus width 394926ce35aSJung-uk Kim * CMD19 Send tuning block 395926ce35aSJung-uk Kim * CMD12 Stop transmission 396926ce35aSJung-uk Kim * 397926ce35aSJung-uk Kim * CMD17 Read single block (<=512) 398926ce35aSJung-uk Kim * CMD18 Read multiple blocks (>512) 399926ce35aSJung-uk Kim * CMD24 Write single block (<=512) 400926ce35aSJung-uk Kim * CMD25 Write multiple blocks (>512) 401926ce35aSJung-uk Kim * 402926ce35aSJung-uk Kim * CMD52 IO R/W direct 403926ce35aSJung-uk Kim * CMD5 Send Operation Conditions 404926ce35aSJung-uk Kim */ 405926ce35aSJung-uk Kim 406926ce35aSJung-uk Kim static int 407926ce35aSJung-uk Kim rtsx_dma_alloc(struct rtsx_softc *sc) 408926ce35aSJung-uk Kim { 409926ce35aSJung-uk Kim int error = 0; 410926ce35aSJung-uk Kim 411926ce35aSJung-uk Kim error = bus_dma_tag_create(bus_get_dma_tag(sc->rtsx_dev), /* inherit from parent */ 412926ce35aSJung-uk Kim RTSX_DMA_ALIGN, 0, /* alignment, boundary */ 413926ce35aSJung-uk Kim BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 414926ce35aSJung-uk Kim BUS_SPACE_MAXADDR, /* highaddr */ 415926ce35aSJung-uk Kim NULL, NULL, /* filter, filterarg */ 416926ce35aSJung-uk Kim RTSX_DMA_CMD_BIFSIZE, 1, /* maxsize, nsegments */ 417926ce35aSJung-uk Kim RTSX_DMA_CMD_BIFSIZE, /* maxsegsize */ 418926ce35aSJung-uk Kim 0, /* flags */ 419926ce35aSJung-uk Kim NULL, NULL, /* lockfunc, lockarg */ 420926ce35aSJung-uk Kim &sc->rtsx_cmd_dma_tag); 421926ce35aSJung-uk Kim if (error) { 422926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 423926ce35aSJung-uk Kim "Can't create cmd parent DMA tag\n"); 424926ce35aSJung-uk Kim return (error); 425926ce35aSJung-uk Kim } 426926ce35aSJung-uk Kim error = bus_dmamem_alloc(sc->rtsx_cmd_dma_tag, /* DMA tag */ 427926ce35aSJung-uk Kim &sc->rtsx_cmd_dmamem, /* will hold the KVA pointer */ 428926ce35aSJung-uk Kim BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, /* flags */ 429926ce35aSJung-uk Kim &sc->rtsx_cmd_dmamap); /* DMA map */ 430926ce35aSJung-uk Kim if (error) { 431926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 432926ce35aSJung-uk Kim "Can't create DMA map for command transfer\n"); 433926ce35aSJung-uk Kim goto destroy_cmd_dma_tag; 434926ce35aSJung-uk Kim 435926ce35aSJung-uk Kim } 436926ce35aSJung-uk Kim error = bus_dmamap_load(sc->rtsx_cmd_dma_tag, /* DMA tag */ 437926ce35aSJung-uk Kim sc->rtsx_cmd_dmamap, /* DMA map */ 438926ce35aSJung-uk Kim sc->rtsx_cmd_dmamem, /* KVA pointer to be mapped */ 439926ce35aSJung-uk Kim RTSX_DMA_CMD_BIFSIZE, /* size of buffer */ 440926ce35aSJung-uk Kim rtsx_dmamap_cb, /* callback */ 441926ce35aSJung-uk Kim &sc->rtsx_cmd_buffer, /* first arg of callback */ 442926ce35aSJung-uk Kim 0); /* flags */ 443926ce35aSJung-uk Kim if (error || sc->rtsx_cmd_buffer == 0) { 444926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 445926ce35aSJung-uk Kim "Can't load DMA memory for command transfer\n"); 446926ce35aSJung-uk Kim error = (error) ? error : EFAULT; 447926ce35aSJung-uk Kim goto destroy_cmd_dmamem_alloc; 448926ce35aSJung-uk Kim } 449926ce35aSJung-uk Kim 450926ce35aSJung-uk Kim error = bus_dma_tag_create(bus_get_dma_tag(sc->rtsx_dev), /* inherit from parent */ 451926ce35aSJung-uk Kim RTSX_DMA_DATA_BUFSIZE, 0, /* alignment, boundary */ 452926ce35aSJung-uk Kim BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 453926ce35aSJung-uk Kim BUS_SPACE_MAXADDR, /* highaddr */ 454926ce35aSJung-uk Kim NULL, NULL, /* filter, filterarg */ 455926ce35aSJung-uk Kim RTSX_DMA_DATA_BUFSIZE, 1, /* maxsize, nsegments */ 456926ce35aSJung-uk Kim RTSX_DMA_DATA_BUFSIZE, /* maxsegsize */ 457926ce35aSJung-uk Kim 0, /* flags */ 458926ce35aSJung-uk Kim NULL, NULL, /* lockfunc, lockarg */ 459926ce35aSJung-uk Kim &sc->rtsx_data_dma_tag); 460926ce35aSJung-uk Kim if (error) { 461926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 462926ce35aSJung-uk Kim "Can't create data parent DMA tag\n"); 463926ce35aSJung-uk Kim goto destroy_cmd_dmamap_load; 464926ce35aSJung-uk Kim } 465926ce35aSJung-uk Kim error = bus_dmamem_alloc(sc->rtsx_data_dma_tag, /* DMA tag */ 466926ce35aSJung-uk Kim &sc->rtsx_data_dmamem, /* will hold the KVA pointer */ 467926ce35aSJung-uk Kim BUS_DMA_WAITOK | BUS_DMA_ZERO, /* flags */ 468926ce35aSJung-uk Kim &sc->rtsx_data_dmamap); /* DMA map */ 469926ce35aSJung-uk Kim if (error) { 470926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 471926ce35aSJung-uk Kim "Can't create DMA map for data transfer\n"); 472926ce35aSJung-uk Kim goto destroy_data_dma_tag; 473926ce35aSJung-uk Kim } 474926ce35aSJung-uk Kim error = bus_dmamap_load(sc->rtsx_data_dma_tag, /* DMA tag */ 475926ce35aSJung-uk Kim sc->rtsx_data_dmamap, /* DMA map */ 476926ce35aSJung-uk Kim sc->rtsx_data_dmamem, /* KVA pointer to be mapped */ 477926ce35aSJung-uk Kim RTSX_DMA_DATA_BUFSIZE, /* size of buffer */ 478926ce35aSJung-uk Kim rtsx_dmamap_cb, /* callback */ 479926ce35aSJung-uk Kim &sc->rtsx_data_buffer, /* first arg of callback */ 480926ce35aSJung-uk Kim 0); /* flags */ 481926ce35aSJung-uk Kim if (error || sc->rtsx_data_buffer == 0) { 482926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 483926ce35aSJung-uk Kim "Can't load DMA memory for data transfer\n"); 484926ce35aSJung-uk Kim error = (error) ? error : EFAULT; 485926ce35aSJung-uk Kim goto destroy_data_dmamem_alloc; 486926ce35aSJung-uk Kim } 487926ce35aSJung-uk Kim return (error); 488926ce35aSJung-uk Kim 489926ce35aSJung-uk Kim destroy_data_dmamem_alloc: 490926ce35aSJung-uk Kim bus_dmamem_free(sc->rtsx_data_dma_tag, sc->rtsx_data_dmamem, sc->rtsx_data_dmamap); 491926ce35aSJung-uk Kim destroy_data_dma_tag: 492926ce35aSJung-uk Kim bus_dma_tag_destroy(sc->rtsx_data_dma_tag); 493926ce35aSJung-uk Kim destroy_cmd_dmamap_load: 494926ce35aSJung-uk Kim bus_dmamap_unload(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap); 495926ce35aSJung-uk Kim destroy_cmd_dmamem_alloc: 496926ce35aSJung-uk Kim bus_dmamem_free(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamem, sc->rtsx_cmd_dmamap); 497926ce35aSJung-uk Kim destroy_cmd_dma_tag: 498926ce35aSJung-uk Kim bus_dma_tag_destroy(sc->rtsx_cmd_dma_tag); 499926ce35aSJung-uk Kim 500926ce35aSJung-uk Kim return (error); 501926ce35aSJung-uk Kim } 502926ce35aSJung-uk Kim 503926ce35aSJung-uk Kim static void 504926ce35aSJung-uk Kim rtsx_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 505926ce35aSJung-uk Kim { 506926ce35aSJung-uk Kim if (error) { 507926ce35aSJung-uk Kim printf("rtsx_dmamap_cb: error %d\n", error); 508926ce35aSJung-uk Kim return; 509926ce35aSJung-uk Kim } 510926ce35aSJung-uk Kim *(bus_addr_t *)arg = segs[0].ds_addr; 511926ce35aSJung-uk Kim } 512926ce35aSJung-uk Kim 513926ce35aSJung-uk Kim static void 514926ce35aSJung-uk Kim rtsx_dma_free(struct rtsx_softc *sc) 515926ce35aSJung-uk Kim { 516926ce35aSJung-uk Kim if (sc->rtsx_cmd_dma_tag != NULL) { 517926ce35aSJung-uk Kim if (sc->rtsx_cmd_dmamap != NULL) 518926ce35aSJung-uk Kim bus_dmamap_unload(sc->rtsx_cmd_dma_tag, 519926ce35aSJung-uk Kim sc->rtsx_cmd_dmamap); 520926ce35aSJung-uk Kim if (sc->rtsx_cmd_dmamem != NULL) 521926ce35aSJung-uk Kim bus_dmamem_free(sc->rtsx_cmd_dma_tag, 522926ce35aSJung-uk Kim sc->rtsx_cmd_dmamem, 523926ce35aSJung-uk Kim sc->rtsx_cmd_dmamap); 524926ce35aSJung-uk Kim sc->rtsx_cmd_dmamap = NULL; 525926ce35aSJung-uk Kim sc->rtsx_cmd_dmamem = NULL; 526926ce35aSJung-uk Kim sc->rtsx_cmd_buffer = 0; 527926ce35aSJung-uk Kim bus_dma_tag_destroy(sc->rtsx_cmd_dma_tag); 528926ce35aSJung-uk Kim sc->rtsx_cmd_dma_tag = NULL; 529926ce35aSJung-uk Kim } 530926ce35aSJung-uk Kim if (sc->rtsx_data_dma_tag != NULL) { 531926ce35aSJung-uk Kim if (sc->rtsx_data_dmamap != NULL) 532926ce35aSJung-uk Kim bus_dmamap_unload(sc->rtsx_data_dma_tag, 533926ce35aSJung-uk Kim sc->rtsx_data_dmamap); 534926ce35aSJung-uk Kim if (sc->rtsx_data_dmamem != NULL) 535926ce35aSJung-uk Kim bus_dmamem_free(sc->rtsx_data_dma_tag, 536926ce35aSJung-uk Kim sc->rtsx_data_dmamem, 537926ce35aSJung-uk Kim sc->rtsx_data_dmamap); 538926ce35aSJung-uk Kim sc->rtsx_data_dmamap = NULL; 539926ce35aSJung-uk Kim sc->rtsx_data_dmamem = NULL; 540926ce35aSJung-uk Kim sc->rtsx_data_buffer = 0; 541926ce35aSJung-uk Kim bus_dma_tag_destroy(sc->rtsx_data_dma_tag); 542926ce35aSJung-uk Kim sc->rtsx_data_dma_tag = NULL; 543926ce35aSJung-uk Kim } 544926ce35aSJung-uk Kim } 545926ce35aSJung-uk Kim 546926ce35aSJung-uk Kim static void 547926ce35aSJung-uk Kim rtsx_intr(void *arg) 548926ce35aSJung-uk Kim { 549926ce35aSJung-uk Kim struct rtsx_softc *sc = arg; 550926ce35aSJung-uk Kim uint32_t enabled; 551926ce35aSJung-uk Kim uint32_t status; 552926ce35aSJung-uk Kim 553926ce35aSJung-uk Kim RTSX_LOCK(sc); 554926ce35aSJung-uk Kim 555926ce35aSJung-uk Kim enabled = sc->rtsx_intr_enabled; 556926ce35aSJung-uk Kim status = READ4(sc, RTSX_BIPR); /* read Bus Interrupt Pending Register */ 557926ce35aSJung-uk Kim sc->rtsx_intr_status = status; 558926ce35aSJung-uk Kim 559577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 560926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Interrupt handler - enabled: 0x%08x, status: 0x%08x\n", enabled, status); 561926ce35aSJung-uk Kim 562926ce35aSJung-uk Kim /* Ack interrupts. */ 563926ce35aSJung-uk Kim WRITE4(sc, RTSX_BIPR, status); 564926ce35aSJung-uk Kim 565926ce35aSJung-uk Kim if (((enabled & status) == 0) || status == 0xffffffff) { 566926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Spurious interrupt - enabled: 0x%08x, status: 0x%08x\n", enabled, status); 567926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 568926ce35aSJung-uk Kim return; 569926ce35aSJung-uk Kim } 570926ce35aSJung-uk Kim 571926ce35aSJung-uk Kim /* Detect write protect. */ 572926ce35aSJung-uk Kim if (status & RTSX_SD_WRITE_PROTECT) 573926ce35aSJung-uk Kim sc->rtsx_read_only = 1; 574926ce35aSJung-uk Kim else 575926ce35aSJung-uk Kim sc->rtsx_read_only = 0; 576926ce35aSJung-uk Kim 577926ce35aSJung-uk Kim /* Start task to handle SD card status change (from dwmmc.c). */ 578926ce35aSJung-uk Kim if (status & RTSX_SD_INT) { 579926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Interrupt card inserted/removed\n"); 580926ce35aSJung-uk Kim rtsx_handle_card_present(sc); 581926ce35aSJung-uk Kim } 582926ce35aSJung-uk Kim 583926ce35aSJung-uk Kim if (sc->rtsx_req == NULL) { 584926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 585926ce35aSJung-uk Kim return; 586926ce35aSJung-uk Kim } 587926ce35aSJung-uk Kim 588926ce35aSJung-uk Kim if (status & RTSX_TRANS_OK_INT) { 589926ce35aSJung-uk Kim sc->rtsx_req->cmd->error = MMC_ERR_NONE; 590926ce35aSJung-uk Kim if (sc->rtsx_intr_trans_ok != NULL) 591926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok(sc); 592926ce35aSJung-uk Kim } else if (status & RTSX_TRANS_FAIL_INT) { 593926ce35aSJung-uk Kim uint8_t stat1; 594926ce35aSJung-uk Kim sc->rtsx_req->cmd->error = MMC_ERR_FAILED; 595926ce35aSJung-uk Kim if (rtsx_read(sc, RTSX_SD_STAT1, &stat1) == 0 && 596926ce35aSJung-uk Kim (stat1 & RTSX_SD_CRC_ERR)) { 597926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "CRC error\n"); 598926ce35aSJung-uk Kim sc->rtsx_req->cmd->error = MMC_ERR_BADCRC; 599926ce35aSJung-uk Kim } 600926ce35aSJung-uk Kim if (!sc->rtsx_tuning_mode) 601926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Transfer fail - status: 0x%08x\n", status); 602926ce35aSJung-uk Kim rtsx_stop_cmd(sc); 603926ce35aSJung-uk Kim if (sc->rtsx_intr_trans_ko != NULL) 604926ce35aSJung-uk Kim sc->rtsx_intr_trans_ko(sc); 605926ce35aSJung-uk Kim } 606926ce35aSJung-uk Kim 607926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 608926ce35aSJung-uk Kim } 609926ce35aSJung-uk Kim 610926ce35aSJung-uk Kim /* 611926ce35aSJung-uk Kim * Function called from the IRQ handler (from dwmmc.c). 612926ce35aSJung-uk Kim */ 613926ce35aSJung-uk Kim static void 614926ce35aSJung-uk Kim rtsx_handle_card_present(struct rtsx_softc *sc) 615926ce35aSJung-uk Kim { 616926ce35aSJung-uk Kim bool was_present; 617926ce35aSJung-uk Kim bool is_present; 618926ce35aSJung-uk Kim 619926ce35aSJung-uk Kim #ifdef MMCCAM 620926ce35aSJung-uk Kim was_present = sc->rtsx_cam_status; 6219d3bc163SHenri Hennebert #else /* !MMCCAM */ 622926ce35aSJung-uk Kim was_present = sc->rtsx_mmc_dev != NULL; 623926ce35aSJung-uk Kim #endif /* MMCCAM */ 624926ce35aSJung-uk Kim is_present = rtsx_is_card_present(sc); 625926ce35aSJung-uk Kim if (is_present) 626926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Card present\n"); 627926ce35aSJung-uk Kim else 628926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Card absent\n"); 629926ce35aSJung-uk Kim 630926ce35aSJung-uk Kim if (!was_present && is_present) { 631926ce35aSJung-uk Kim /* 632926ce35aSJung-uk Kim * The delay is to debounce the card insert 633926ce35aSJung-uk Kim * (sometimes the card detect pin stabilizes 634926ce35aSJung-uk Kim * before the other pins have made good contact). 635926ce35aSJung-uk Kim */ 636926ce35aSJung-uk Kim taskqueue_enqueue_timeout(taskqueue_swi_giant, 637926ce35aSJung-uk Kim &sc->rtsx_card_insert_task, -hz); 638926ce35aSJung-uk Kim } else if (was_present && !is_present) { 639926ce35aSJung-uk Kim taskqueue_enqueue(taskqueue_swi_giant, &sc->rtsx_card_remove_task); 640926ce35aSJung-uk Kim } 641926ce35aSJung-uk Kim } 642926ce35aSJung-uk Kim 643926ce35aSJung-uk Kim /* 6445bdf58e1SGordon Bergling * This function is called at startup. 645926ce35aSJung-uk Kim */ 646926ce35aSJung-uk Kim static void 647926ce35aSJung-uk Kim rtsx_card_task(void *arg, int pending __unused) 648926ce35aSJung-uk Kim { 649926ce35aSJung-uk Kim struct rtsx_softc *sc = arg; 650926ce35aSJung-uk Kim 651926ce35aSJung-uk Kim if (rtsx_is_card_present(sc)) { 652926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_CARD_PRESENT; 653926ce35aSJung-uk Kim /* Card is present, attach if necessary. */ 654926ce35aSJung-uk Kim #ifdef MMCCAM 655926ce35aSJung-uk Kim if (sc->rtsx_cam_status == 0) { 6569d3bc163SHenri Hennebert #else /* !MMCCAM */ 657926ce35aSJung-uk Kim if (sc->rtsx_mmc_dev == NULL) { 658926ce35aSJung-uk Kim #endif /* MMCCAM */ 659577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 660926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Card inserted\n"); 661926ce35aSJung-uk Kim 662926ce35aSJung-uk Kim sc->rtsx_read_count = sc->rtsx_write_count = 0; 663926ce35aSJung-uk Kim #ifdef MMCCAM 664926ce35aSJung-uk Kim sc->rtsx_cam_status = 1; 6658e9740b6SHenri Hennebert mmc_cam_sim_discover(&sc->rtsx_mmc_sim); 6669d3bc163SHenri Hennebert #else /* !MMCCAM */ 6678e9740b6SHenri Hennebert RTSX_LOCK(sc); 6685b56413dSWarner Losh sc->rtsx_mmc_dev = device_add_child(sc->rtsx_dev, "mmc", DEVICE_UNIT_ANY); 669926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 670926ce35aSJung-uk Kim if (sc->rtsx_mmc_dev == NULL) { 671926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Adding MMC bus failed\n"); 672926ce35aSJung-uk Kim } else { 673926ce35aSJung-uk Kim device_set_ivars(sc->rtsx_mmc_dev, sc); 674926ce35aSJung-uk Kim device_probe_and_attach(sc->rtsx_mmc_dev); 675926ce35aSJung-uk Kim } 676926ce35aSJung-uk Kim #endif /* MMCCAM */ 6778e9740b6SHenri Hennebert } 678926ce35aSJung-uk Kim } else { 679926ce35aSJung-uk Kim sc->rtsx_flags &= ~RTSX_F_CARD_PRESENT; 680926ce35aSJung-uk Kim /* Card isn't present, detach if necessary. */ 681926ce35aSJung-uk Kim #ifdef MMCCAM 682926ce35aSJung-uk Kim if (sc->rtsx_cam_status != 0) { 6839d3bc163SHenri Hennebert #else /* !MMCCAM */ 684926ce35aSJung-uk Kim if (sc->rtsx_mmc_dev != NULL) { 685926ce35aSJung-uk Kim #endif /* MMCCAM */ 686577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 687926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Card removed\n"); 688926ce35aSJung-uk Kim 689577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 690926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Read count: %" PRIu64 ", write count: %" PRIu64 "\n", 691926ce35aSJung-uk Kim sc->rtsx_read_count, sc->rtsx_write_count); 692926ce35aSJung-uk Kim #ifdef MMCCAM 693926ce35aSJung-uk Kim sc->rtsx_cam_status = 0; 6948e9740b6SHenri Hennebert mmc_cam_sim_discover(&sc->rtsx_mmc_sim); 6959d3bc163SHenri Hennebert #else /* !MMCCAM */ 696926ce35aSJung-uk Kim if (device_delete_child(sc->rtsx_dev, sc->rtsx_mmc_dev)) 697926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Detaching MMC bus failed\n"); 698926ce35aSJung-uk Kim sc->rtsx_mmc_dev = NULL; 699926ce35aSJung-uk Kim #endif /* MMCCAM */ 7008e9740b6SHenri Hennebert } 701926ce35aSJung-uk Kim } 702926ce35aSJung-uk Kim } 703926ce35aSJung-uk Kim 704926ce35aSJung-uk Kim static bool 705926ce35aSJung-uk Kim rtsx_is_card_present(struct rtsx_softc *sc) 706926ce35aSJung-uk Kim { 707926ce35aSJung-uk Kim uint32_t status; 708926ce35aSJung-uk Kim 709926ce35aSJung-uk Kim status = READ4(sc, RTSX_BIPR); 710926ce35aSJung-uk Kim if (sc->rtsx_inversion == 0) 711926ce35aSJung-uk Kim return (status & RTSX_SD_EXIST); 712926ce35aSJung-uk Kim else 713926ce35aSJung-uk Kim return !(status & RTSX_SD_EXIST); 714926ce35aSJung-uk Kim } 715926ce35aSJung-uk Kim 716926ce35aSJung-uk Kim static int 717926ce35aSJung-uk Kim rtsx_init(struct rtsx_softc *sc) 718926ce35aSJung-uk Kim { 719926ce35aSJung-uk Kim uint8_t version; 720926ce35aSJung-uk Kim uint8_t val; 721926ce35aSJung-uk Kim int error; 722926ce35aSJung-uk Kim 723926ce35aSJung-uk Kim sc->rtsx_host.host_ocr = RTSX_SUPPORTED_VOLTAGE; 724926ce35aSJung-uk Kim sc->rtsx_host.f_min = RTSX_SDCLK_250KHZ; 725926ce35aSJung-uk Kim sc->rtsx_host.f_max = RTSX_SDCLK_208MHZ; 726926ce35aSJung-uk Kim sc->rtsx_host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED | 727926ce35aSJung-uk Kim MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; 728926ce35aSJung-uk Kim 729926ce35aSJung-uk Kim sc->rtsx_host.caps |= MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104; 730926ce35aSJung-uk Kim if (sc->rtsx_device_id == RTSX_RTS5209) 731926ce35aSJung-uk Kim sc->rtsx_host.caps |= MMC_CAP_8_BIT_DATA; 732926ce35aSJung-uk Kim pci_find_cap(sc->rtsx_dev, PCIY_EXPRESS, &(sc->rtsx_pcie_cap)); 733926ce35aSJung-uk Kim 734926ce35aSJung-uk Kim /* 735926ce35aSJung-uk Kim * Check IC version. 736926ce35aSJung-uk Kim */ 737926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 738926ce35aSJung-uk Kim case RTSX_RTS5229: 739926ce35aSJung-uk Kim /* Read IC version from dummy register. */ 740926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_DUMMY_REG, &version); 741926ce35aSJung-uk Kim if ((version & 0x0F) == RTSX_IC_VERSION_C) 742926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_VERSION_C; 743926ce35aSJung-uk Kim break; 744926ce35aSJung-uk Kim case RTSX_RTS522A: 745926ce35aSJung-uk Kim /* Read IC version from dummy register. */ 746926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_DUMMY_REG, &version); 747926ce35aSJung-uk Kim if ((version & 0x0F) == RTSX_IC_VERSION_A) 748926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_VERSION_A; 749926ce35aSJung-uk Kim break; 750926ce35aSJung-uk Kim case RTSX_RTS525A: 751926ce35aSJung-uk Kim /* Read IC version from dummy register. */ 752926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_DUMMY_REG, &version); 753926ce35aSJung-uk Kim if ((version & 0x0F) == RTSX_IC_VERSION_A) 754926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_VERSION_A; 755926ce35aSJung-uk Kim break; 756926ce35aSJung-uk Kim case RTSX_RTL8411B: 757926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_RTL8411B_PACKAGE, &version); 758926ce35aSJung-uk Kim if (version & RTSX_RTL8411B_QFN48) 759926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_8411B_QFN48; 760926ce35aSJung-uk Kim break; 761926ce35aSJung-uk Kim } 762926ce35aSJung-uk Kim 763926ce35aSJung-uk Kim /* 764926ce35aSJung-uk Kim * Fetch vendor settings. 765926ce35aSJung-uk Kim */ 766926ce35aSJung-uk Kim /* 767926ce35aSJung-uk Kim * Normally OEMs will set vendor setting to the config space 768926ce35aSJung-uk Kim * of Realtek card reader in BIOS stage. This statement reads 769926ce35aSJung-uk Kim * the setting and configure the internal registers according 770926ce35aSJung-uk Kim * to it, to improve card reader's compatibility condition. 771926ce35aSJung-uk Kim */ 772926ce35aSJung-uk Kim sc->rtsx_card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; 773926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 774926ce35aSJung-uk Kim uint32_t reg; 775926ce35aSJung-uk Kim uint32_t reg1; 776926ce35aSJung-uk Kim uint8_t reg3; 777926ce35aSJung-uk Kim case RTSX_RTS5209: 778926ce35aSJung-uk Kim sc->rtsx_card_drive_sel = RTSX_RTS5209_CARD_DRIVE_DEFAULT; 779926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = RTSX_DRIVER_TYPE_D; 780926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG2, 4); 781926ce35aSJung-uk Kim if (!(reg & 0x80)) { 782926ce35aSJung-uk Kim sc->rtsx_card_drive_sel = (reg >> 8) & 0x3F; 783926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = reg & 0x07; 784577130e5SHenri Hennebert } else if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 785926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "pci_read_config() error - reg: 0x%08x\n", reg); 786926ce35aSJung-uk Kim } 787577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 788926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "card_drive_sel: 0x%02x, sd30_drive_sel_3v3: 0x%02x\n", 789926ce35aSJung-uk Kim sc->rtsx_card_drive_sel, sc->rtsx_sd30_drive_sel_3v3); 790926ce35aSJung-uk Kim break; 791926ce35aSJung-uk Kim case RTSX_RTS5227: 792926ce35aSJung-uk Kim case RTSX_RTS522A: 793926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = RTSX_CFG_DRIVER_TYPE_B; 794926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG1, 4); 795926ce35aSJung-uk Kim if (!(reg & 0x1000000)) { 796926ce35aSJung-uk Kim sc->rtsx_card_drive_sel &= 0x3F; 797926ce35aSJung-uk Kim sc->rtsx_card_drive_sel |= ((reg >> 25) & 0x01) << 6; 798926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG2, 4); 799926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = (reg >> 5) & 0x03; 800926ce35aSJung-uk Kim if (reg & 0x4000) 801926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_REVERSE_SOCKET; 802577130e5SHenri Hennebert } else if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 803926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "pci_read_config() error - reg: 0x%08x\n", reg); 804926ce35aSJung-uk Kim } 805577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 806926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 807926ce35aSJung-uk Kim "card_drive_sel: 0x%02x, sd30_drive_sel_3v3: 0x%02x, reverse_socket is %s\n", 808926ce35aSJung-uk Kim sc->rtsx_card_drive_sel, sc->rtsx_sd30_drive_sel_3v3, 809926ce35aSJung-uk Kim (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) ? "true" : "false"); 810926ce35aSJung-uk Kim break; 811926ce35aSJung-uk Kim case RTSX_RTS5229: 812926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = RTSX_DRIVER_TYPE_D; 813926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG1, 4); 814926ce35aSJung-uk Kim if (!(reg & 0x1000000)) { 815926ce35aSJung-uk Kim sc->rtsx_card_drive_sel &= 0x3F; 816926ce35aSJung-uk Kim sc->rtsx_card_drive_sel |= ((reg >> 25) & 0x01) << 6; 817926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG2, 4); 818926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = rtsx_map_sd_drive((reg >> 5) & 0x03); 819577130e5SHenri Hennebert } else if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 820926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "pci_read_config() error - reg: 0x%08x\n", reg); 821926ce35aSJung-uk Kim } 822577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 823926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "card_drive_sel: 0x%02x, sd30_drive_sel_3v3: 0x%02x\n", 824926ce35aSJung-uk Kim sc->rtsx_card_drive_sel, sc->rtsx_sd30_drive_sel_3v3); 825926ce35aSJung-uk Kim break; 826926ce35aSJung-uk Kim case RTSX_RTS525A: 827926ce35aSJung-uk Kim case RTSX_RTS5249: 828577130e5SHenri Hennebert case RTSX_RTS5260: 829926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = RTSX_CFG_DRIVER_TYPE_B; 830926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG1, 4); 831926ce35aSJung-uk Kim if ((reg & 0x1000000)) { 832926ce35aSJung-uk Kim sc->rtsx_card_drive_sel &= 0x3F; 833926ce35aSJung-uk Kim sc->rtsx_card_drive_sel |= ((reg >> 25) & 0x01) << 6; 834926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG2, 4); 835926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = (reg >> 5) & 0x03; 836926ce35aSJung-uk Kim if (reg & 0x4000) 837926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_REVERSE_SOCKET; 838577130e5SHenri Hennebert } else if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 839926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "pci_read_config() error - reg: 0x%08x\n", reg); 840926ce35aSJung-uk Kim } 841577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 842926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 843926ce35aSJung-uk Kim "card_drive_sel = 0x%02x, sd30_drive_sel_3v3: 0x%02x, reverse_socket is %s\n", 844926ce35aSJung-uk Kim sc->rtsx_card_drive_sel, sc->rtsx_sd30_drive_sel_3v3, 845926ce35aSJung-uk Kim (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) ? "true" : "false"); 846926ce35aSJung-uk Kim break; 847926ce35aSJung-uk Kim case RTSX_RTL8402: 848926ce35aSJung-uk Kim case RTSX_RTL8411: 849926ce35aSJung-uk Kim sc->rtsx_card_drive_sel = RTSX_RTL8411_CARD_DRIVE_DEFAULT; 850926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = RTSX_DRIVER_TYPE_D; 851926ce35aSJung-uk Kim reg1 = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG1, 4); 852926ce35aSJung-uk Kim if (reg1 & 0x1000000) { 853926ce35aSJung-uk Kim sc->rtsx_card_drive_sel &= 0x3F; 854926ce35aSJung-uk Kim sc->rtsx_card_drive_sel |= ((reg1 >> 25) & 0x01) << 6; 855926ce35aSJung-uk Kim reg3 = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG3, 1); 856926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = (reg3 >> 5) & 0x07; 857577130e5SHenri Hennebert } else if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 858926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "pci_read_config() error - reg1: 0x%08x\n", reg1); 859926ce35aSJung-uk Kim } 860577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 861926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 862926ce35aSJung-uk Kim "card_drive_sel: 0x%02x, sd30_drive_sel_3v3: 0x%02x\n", 863926ce35aSJung-uk Kim sc->rtsx_card_drive_sel, sc->rtsx_sd30_drive_sel_3v3); 864926ce35aSJung-uk Kim break; 865926ce35aSJung-uk Kim case RTSX_RTL8411B: 866926ce35aSJung-uk Kim sc->rtsx_card_drive_sel = RTSX_RTL8411_CARD_DRIVE_DEFAULT; 867926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = RTSX_DRIVER_TYPE_D; 868926ce35aSJung-uk Kim reg = pci_read_config(sc->rtsx_dev, RTSX_PCR_SETTING_REG1, 4); 869926ce35aSJung-uk Kim if (!(reg & 0x1000000)) { 870926ce35aSJung-uk Kim sc->rtsx_sd30_drive_sel_3v3 = rtsx_map_sd_drive(reg & 0x03); 871577130e5SHenri Hennebert } else if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 872926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "pci_read_config() error - reg: 0x%08x\n", reg); 873926ce35aSJung-uk Kim } 874577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 875926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 876926ce35aSJung-uk Kim "card_drive_sel: 0x%02x, sd30_drive_sel_3v3: 0x%02x\n", 877926ce35aSJung-uk Kim sc->rtsx_card_drive_sel, sc->rtsx_sd30_drive_sel_3v3); 878926ce35aSJung-uk Kim break; 879926ce35aSJung-uk Kim } 880926ce35aSJung-uk Kim 881577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 882926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_init() rtsx_flags: 0x%04x\n", sc->rtsx_flags); 883926ce35aSJung-uk Kim 884926ce35aSJung-uk Kim /* Enable interrupts. */ 8858290c144SHenri Hennebert sc->rtsx_intr_enabled = RTSX_TRANS_OK_INT_EN | RTSX_TRANS_FAIL_INT_EN | RTSX_SD_INT_EN; 886926ce35aSJung-uk Kim WRITE4(sc, RTSX_BIER, sc->rtsx_intr_enabled); 887926ce35aSJung-uk Kim 888926ce35aSJung-uk Kim /* Power on SSC clock. */ 889926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_FPDCTL, RTSX_SSC_POWER_DOWN); 890926ce35aSJung-uk Kim /* Wait SSC power stable. */ 891926ce35aSJung-uk Kim DELAY(200); 892926ce35aSJung-uk Kim 893926ce35aSJung-uk Kim /* Disable ASPM */ 894926ce35aSJung-uk Kim val = pci_read_config(sc->rtsx_dev, sc->rtsx_pcie_cap + PCIER_LINK_CTL, 1); 895926ce35aSJung-uk Kim pci_write_config(sc->rtsx_dev, sc->rtsx_pcie_cap + PCIER_LINK_CTL, val & 0xfc, 1); 896926ce35aSJung-uk Kim 897926ce35aSJung-uk Kim /* 898926ce35aSJung-uk Kim * Optimize phy. 899926ce35aSJung-uk Kim */ 900926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 901926ce35aSJung-uk Kim case RTSX_RTS5209: 902926ce35aSJung-uk Kim /* Some magic numbers from Linux driver. */ 903926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, 0x00, 0xB966))) 904926ce35aSJung-uk Kim return (error); 905926ce35aSJung-uk Kim break; 906926ce35aSJung-uk Kim case RTSX_RTS5227: 907926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_PM_CTRL3, RTSX_D3_DELINK_MODE_EN); 908926ce35aSJung-uk Kim 909926ce35aSJung-uk Kim /* Optimize RX sensitivity. */ 910926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, 0x00, 0xBA42))) 911926ce35aSJung-uk Kim return (error); 912926ce35aSJung-uk Kim break; 913926ce35aSJung-uk Kim case RTSX_RTS5229: 914926ce35aSJung-uk Kim /* Optimize RX sensitivity. */ 915926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, 0x00, 0xBA42))) 916926ce35aSJung-uk Kim return (error); 917926ce35aSJung-uk Kim break; 918926ce35aSJung-uk Kim case RTSX_RTS522A: 919926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_RTS522A_PM_CTRL3, RTSX_D3_DELINK_MODE_EN); 920926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_VERSION_A) { 921926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_RCR2, RTSX_PHY_RCR2_INIT_27S))) 922926ce35aSJung-uk Kim return (error); 923926ce35aSJung-uk Kim } 924926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_RCR1, RTSX_PHY_RCR1_INIT_27S))) 925926ce35aSJung-uk Kim return (error); 926926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_FLD0, RTSX_PHY_FLD0_INIT_27S))) 927926ce35aSJung-uk Kim return (error); 928926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_FLD3, RTSX_PHY_FLD3_INIT_27S))) 929926ce35aSJung-uk Kim return (error); 930926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_FLD4, RTSX_PHY_FLD4_INIT_27S))) 931926ce35aSJung-uk Kim return (error); 932926ce35aSJung-uk Kim break; 933926ce35aSJung-uk Kim case RTSX_RTS525A: 934926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX__PHY_FLD0, 935926ce35aSJung-uk Kim RTSX__PHY_FLD0_CLK_REQ_20C | RTSX__PHY_FLD0_RX_IDLE_EN | 936926ce35aSJung-uk Kim RTSX__PHY_FLD0_BIT_ERR_RSTN | RTSX__PHY_FLD0_BER_COUNT | 937926ce35aSJung-uk Kim RTSX__PHY_FLD0_BER_TIMER | RTSX__PHY_FLD0_CHECK_EN))) 938926ce35aSJung-uk Kim return (error); 939926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX__PHY_ANA03, 940926ce35aSJung-uk Kim RTSX__PHY_ANA03_TIMER_MAX | RTSX__PHY_ANA03_OOBS_DEB_EN | 941926ce35aSJung-uk Kim RTSX__PHY_CMU_DEBUG_EN))) 942926ce35aSJung-uk Kim return (error); 943926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_VERSION_A) 944926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX__PHY_REV0, 945926ce35aSJung-uk Kim RTSX__PHY_REV0_FILTER_OUT | RTSX__PHY_REV0_CDR_BYPASS_PFD | 946926ce35aSJung-uk Kim RTSX__PHY_REV0_CDR_RX_IDLE_BYPASS))) 947926ce35aSJung-uk Kim return (error); 948926ce35aSJung-uk Kim break; 949926ce35aSJung-uk Kim case RTSX_RTS5249: 950926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_PM_CTRL3, RTSX_D3_DELINK_MODE_EN); 951926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_REV, 952926ce35aSJung-uk Kim RTSX_PHY_REV_RESV | RTSX_PHY_REV_RXIDLE_LATCHED | 953926ce35aSJung-uk Kim RTSX_PHY_REV_P1_EN | RTSX_PHY_REV_RXIDLE_EN | 954926ce35aSJung-uk Kim RTSX_PHY_REV_CLKREQ_TX_EN | RTSX_PHY_REV_RX_PWST | 955926ce35aSJung-uk Kim RTSX_PHY_REV_CLKREQ_DT_1_0 | RTSX_PHY_REV_STOP_CLKRD | 956926ce35aSJung-uk Kim RTSX_PHY_REV_STOP_CLKWR))) 957926ce35aSJung-uk Kim return (error); 9589d3bc163SHenri Hennebert DELAY(1000); 959926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_BPCR, 960926ce35aSJung-uk Kim RTSX_PHY_BPCR_IBRXSEL | RTSX_PHY_BPCR_IBTXSEL | 961926ce35aSJung-uk Kim RTSX_PHY_BPCR_IB_FILTER | RTSX_PHY_BPCR_CMIRROR_EN))) 962926ce35aSJung-uk Kim return (error); 963926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_PCR, 964926ce35aSJung-uk Kim RTSX_PHY_PCR_FORCE_CODE | RTSX_PHY_PCR_OOBS_CALI_50 | 965926ce35aSJung-uk Kim RTSX_PHY_PCR_OOBS_VCM_08 | RTSX_PHY_PCR_OOBS_SEN_90 | 966926ce35aSJung-uk Kim RTSX_PHY_PCR_RSSI_EN | RTSX_PHY_PCR_RX10K))) 967926ce35aSJung-uk Kim return (error); 968926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_RCR2, 969926ce35aSJung-uk Kim RTSX_PHY_RCR2_EMPHASE_EN | RTSX_PHY_RCR2_NADJR | 970926ce35aSJung-uk Kim RTSX_PHY_RCR2_CDR_SR_2 | RTSX_PHY_RCR2_FREQSEL_12 | 971926ce35aSJung-uk Kim RTSX_PHY_RCR2_CDR_SC_12P | RTSX_PHY_RCR2_CALIB_LATE))) 972926ce35aSJung-uk Kim return (error); 973926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_FLD4, 974926ce35aSJung-uk Kim RTSX_PHY_FLD4_FLDEN_SEL | RTSX_PHY_FLD4_REQ_REF | 975926ce35aSJung-uk Kim RTSX_PHY_FLD4_RXAMP_OFF | RTSX_PHY_FLD4_REQ_ADDA | 976926ce35aSJung-uk Kim RTSX_PHY_FLD4_BER_COUNT | RTSX_PHY_FLD4_BER_TIMER | 977926ce35aSJung-uk Kim RTSX_PHY_FLD4_BER_CHK_EN))) 978926ce35aSJung-uk Kim return (error); 979926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_RDR, 980926ce35aSJung-uk Kim RTSX_PHY_RDR_RXDSEL_1_9 | RTSX_PHY_SSC_AUTO_PWD))) 981926ce35aSJung-uk Kim return (error); 982926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_RCR1, 983926ce35aSJung-uk Kim RTSX_PHY_RCR1_ADP_TIME_4 | RTSX_PHY_RCR1_VCO_COARSE))) 984926ce35aSJung-uk Kim return (error); 985926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_FLD3, 986926ce35aSJung-uk Kim RTSX_PHY_FLD3_TIMER_4 | RTSX_PHY_FLD3_TIMER_6 | 987926ce35aSJung-uk Kim RTSX_PHY_FLD3_RXDELINK))) 988926ce35aSJung-uk Kim return (error); 989926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_TUNE, 990926ce35aSJung-uk Kim RTSX_PHY_TUNE_TUNEREF_1_0 | RTSX_PHY_TUNE_VBGSEL_1252 | 991926ce35aSJung-uk Kim RTSX_PHY_TUNE_SDBUS_33 | RTSX_PHY_TUNE_TUNED18 | 992926ce35aSJung-uk Kim RTSX_PHY_TUNE_TUNED12 | RTSX_PHY_TUNE_TUNEA12))) 993926ce35aSJung-uk Kim return (error); 994926ce35aSJung-uk Kim break; 995926ce35aSJung-uk Kim } 996926ce35aSJung-uk Kim 997926ce35aSJung-uk Kim /* Set mcu_cnt to 7 to ensure data can be sampled properly. */ 998926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CLK_DIV, 0x07, 0x07); 999926ce35aSJung-uk Kim 1000926ce35aSJung-uk Kim /* Disable sleep mode. */ 1001926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_HOST_SLEEP_STATE, 1002926ce35aSJung-uk Kim RTSX_HOST_ENTER_S1 | RTSX_HOST_ENTER_S3); 1003926ce35aSJung-uk Kim 1004926ce35aSJung-uk Kim /* Disable card clock. */ 1005926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_CLK_EN, RTSX_CARD_CLK_EN_ALL); 1006926ce35aSJung-uk Kim 1007926ce35aSJung-uk Kim /* Reset delink mode. */ 1008926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CHANGE_LINK_STATE, 1009926ce35aSJung-uk Kim RTSX_FORCE_RST_CORE_EN | RTSX_NON_STICKY_RST_N_DBG); 1010926ce35aSJung-uk Kim 1011926ce35aSJung-uk Kim /* Card driving select. */ 1012926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_DRIVE_SEL, sc->rtsx_card_drive_sel); 1013926ce35aSJung-uk Kim 1014926ce35aSJung-uk Kim /* Enable SSC clock. */ 1015926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SSC_CTL1, RTSX_SSC_8X_EN | RTSX_SSC_SEL_4M); 1016926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SSC_CTL2, 0x12); 1017926ce35aSJung-uk Kim 1018926ce35aSJung-uk Kim /* Disable cd_pwr_save. */ 1019926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CHANGE_LINK_STATE, 0x16, RTSX_MAC_PHY_RST_N_DBG); 1020926ce35aSJung-uk Kim 1021926ce35aSJung-uk Kim /* Clear Link Ready Interrupt. */ 1022926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_IRQSTAT0, RTSX_LINK_READY_INT, RTSX_LINK_READY_INT); 1023926ce35aSJung-uk Kim 1024926ce35aSJung-uk Kim /* Enlarge the estimation window of PERST# glitch 1025926ce35aSJung-uk Kim * to reduce the chance of invalid card interrupt. */ 1026926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PERST_GLITCH_WIDTH, 0x80); 1027926ce35aSJung-uk Kim 1028926ce35aSJung-uk Kim /* Set RC oscillator to 400K. */ 1029926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_RCCTL, RTSX_RCCTL_F_2M); 1030926ce35aSJung-uk Kim 1031926ce35aSJung-uk Kim /* Enable interrupt write-clear (default is read-clear). */ 1032926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_NFTS_TX_CTRL, RTSX_INT_READ_CLR); 1033926ce35aSJung-uk Kim 10348290c144SHenri Hennebert switch (sc->rtsx_device_id) { 10358290c144SHenri Hennebert case RTSX_RTS525A: 10368290c144SHenri Hennebert case RTSX_RTS5260: 1037926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PM_CLK_FORCE_CTL, 1, 1); 10388290c144SHenri Hennebert break; 10398290c144SHenri Hennebert } 1040926ce35aSJung-uk Kim 1041926ce35aSJung-uk Kim /* OC power down. */ 1042926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_FPDCTL, RTSX_SD_OC_POWER_DOWN, RTSX_SD_OC_POWER_DOWN); 1043926ce35aSJung-uk Kim 1044926ce35aSJung-uk Kim /* Enable clk_request_n to enable clock power management */ 1045926ce35aSJung-uk Kim pci_write_config(sc->rtsx_dev, sc->rtsx_pcie_cap + PCIER_LINK_CTL + 1, 1, 1); 1046926ce35aSJung-uk Kim 1047926ce35aSJung-uk Kim /* Enter L1 when host tx idle */ 1048926ce35aSJung-uk Kim pci_write_config(sc->rtsx_dev, 0x70F, 0x5B, 1); 1049926ce35aSJung-uk Kim 1050926ce35aSJung-uk Kim /* 1051926ce35aSJung-uk Kim * Specific extra init. 1052926ce35aSJung-uk Kim */ 1053926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1054926ce35aSJung-uk Kim uint16_t cap; 1055926ce35aSJung-uk Kim case RTSX_RTS5209: 1056926ce35aSJung-uk Kim /* Turn off LED. */ 1057926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_GPIO, 0x03); 1058926ce35aSJung-uk Kim /* Reset ASPM state to default value. */ 1059926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_ASPM_FORCE_CTL, RTSX_ASPM_FORCE_MASK); 1060926ce35aSJung-uk Kim /* Force CLKREQ# PIN to drive 0 to request clock. */ 1061926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0x08, 0x08); 1062926ce35aSJung-uk Kim /* Configure GPIO as output. */ 1063926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_GPIO_DIR, 0x03); 1064926ce35aSJung-uk Kim /* Configure driving. */ 1065926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, sc->rtsx_sd30_drive_sel_3v3); 1066926ce35aSJung-uk Kim break; 1067926ce35aSJung-uk Kim case RTSX_RTS5227: 1068926ce35aSJung-uk Kim /* Configure GPIO as output. */ 1069926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON, RTSX_GPIO_LED_ON); 1070926ce35aSJung-uk Kim /* Reset ASPM state to default value. */ 1071926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_ASPM_FORCE_CTL, RTSX_ASPM_FORCE_MASK, RTSX_FORCE_ASPM_NO_ASPM); 1072926ce35aSJung-uk Kim /* Switch LDO3318 source from DV33 to 3V3. */ 1073926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33); 1074926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33, RTSX_LDO_PWR_SEL_3V3); 1075926ce35aSJung-uk Kim /* Set default OLT blink period. */ 1076926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OLT_LED_CTL, 0x0F, RTSX_OLT_LED_PERIOD); 1077926ce35aSJung-uk Kim /* Configure LTR. */ 1078926ce35aSJung-uk Kim cap = pci_read_config(sc->rtsx_dev, sc->rtsx_pcie_cap + PCIER_DEVICE_CTL2, 2); 1079926ce35aSJung-uk Kim if (cap & PCIEM_CTL2_LTR_ENABLE) 1080926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_LTR_CTL, 0xa3); 1081926ce35aSJung-uk Kim /* Configure OBFF. */ 1082926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OBFF_CFG, RTSX_OBFF_EN_MASK, RTSX_OBFF_ENABLE); 1083926ce35aSJung-uk Kim /* Configure driving. */ 1084926ce35aSJung-uk Kim if ((error = rtsx_rts5227_fill_driving(sc))) 1085926ce35aSJung-uk Kim return (error); 1086926ce35aSJung-uk Kim /* Configure force_clock_req. */ 1087926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) 1088926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB8, 0xB8); 1089926ce35aSJung-uk Kim else 1090926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB8, 0x88); 1091926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_PM_CTRL3, RTSX_D3_DELINK_MODE_EN); 1092926ce35aSJung-uk Kim /*!!! Added for reboot after Windows. */ 1093926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PM_CTRL3, RTSX_PM_WAKE_EN, RTSX_PM_WAKE_EN); 1094926ce35aSJung-uk Kim break; 1095926ce35aSJung-uk Kim case RTSX_RTS5229: 1096926ce35aSJung-uk Kim /* Configure GPIO as output. */ 1097926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON, RTSX_GPIO_LED_ON); 1098926ce35aSJung-uk Kim /* Reset ASPM state to default value. */ 1099926ce35aSJung-uk Kim /* With this reset: dd if=/dev/random of=/dev/mmcsd0 encounter a timeout. */ 1100926ce35aSJung-uk Kim //!!! RTSX_BITOP(sc, RTSX_ASPM_FORCE_CTL, RTSX_ASPM_FORCE_MASK, RTSX_FORCE_ASPM_NO_ASPM); 1101926ce35aSJung-uk Kim /* Force CLKREQ# PIN to drive 0 to request clock. */ 1102926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0x08, 0x08); 1103926ce35aSJung-uk Kim /* Switch LDO3318 source from DV33 to card_3v3. */ 1104926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33); 1105926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33, RTSX_LDO_PWR_SEL_3V3); 1106926ce35aSJung-uk Kim /* Set default OLT blink period. */ 1107926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OLT_LED_CTL, 0x0F, RTSX_OLT_LED_PERIOD); 1108926ce35aSJung-uk Kim /* Configure driving. */ 1109926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, sc->rtsx_sd30_drive_sel_3v3); 1110926ce35aSJung-uk Kim break; 1111926ce35aSJung-uk Kim case RTSX_RTS522A: 1112926ce35aSJung-uk Kim /* Add specific init from RTS5227. */ 1113926ce35aSJung-uk Kim /* Configure GPIO as output. */ 1114926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON, RTSX_GPIO_LED_ON); 1115926ce35aSJung-uk Kim /* Reset ASPM state to default value. */ 1116926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_ASPM_FORCE_CTL, RTSX_ASPM_FORCE_MASK, RTSX_FORCE_ASPM_NO_ASPM); 1117926ce35aSJung-uk Kim /* Switch LDO3318 source from DV33 to 3V3. */ 1118926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33); 1119926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33, RTSX_LDO_PWR_SEL_3V3); 1120926ce35aSJung-uk Kim /* Set default OLT blink period. */ 1121926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OLT_LED_CTL, 0x0F, RTSX_OLT_LED_PERIOD); 1122926ce35aSJung-uk Kim /* Configure LTR. */ 1123926ce35aSJung-uk Kim cap = pci_read_config(sc->rtsx_dev, sc->rtsx_pcie_cap + PCIER_DEVICE_CTL2, 2); 1124926ce35aSJung-uk Kim if (cap & PCIEM_CTL2_LTR_ENABLE) 1125926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_LTR_CTL, 0xa3); 1126926ce35aSJung-uk Kim /* Configure OBFF. */ 1127926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OBFF_CFG, RTSX_OBFF_EN_MASK, RTSX_OBFF_ENABLE); 1128926ce35aSJung-uk Kim /* Configure driving. */ 1129926ce35aSJung-uk Kim if ((error = rtsx_rts5227_fill_driving(sc))) 1130926ce35aSJung-uk Kim return (error); 1131926ce35aSJung-uk Kim /* Configure force_clock_req. */ 1132926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) 1133926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB8, 0xB8); 1134926ce35aSJung-uk Kim else 1135926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB8, 0x88); 1136926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_RTS522A_PM_CTRL3, 0x10); 1137926ce35aSJung-uk Kim 1138926ce35aSJung-uk Kim /* specific for RTS522A. */ 1139926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_FUNC_FORCE_CTL, 1140926ce35aSJung-uk Kim RTSX_FUNC_FORCE_UPME_XMT_DBG, RTSX_FUNC_FORCE_UPME_XMT_DBG); 1141926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PCLK_CTL, 0x04, 0x04); 1142926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PM_EVENT_DEBUG, 1143926ce35aSJung-uk Kim RTSX_PME_DEBUG_0, RTSX_PME_DEBUG_0); 1144926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PM_CLK_FORCE_CTL, 0x11); 1145926ce35aSJung-uk Kim break; 1146926ce35aSJung-uk Kim case RTSX_RTS525A: 1147926ce35aSJung-uk Kim /* Add specific init from RTS5249. */ 1148926ce35aSJung-uk Kim /* Rest L1SUB Config. */ 1149926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_L1SUB_CONFIG3, 0xff); 1150926ce35aSJung-uk Kim /* Configure GPIO as output. */ 1151926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON, RTSX_GPIO_LED_ON); 1152926ce35aSJung-uk Kim /* Reset ASPM state to default value. */ 1153926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_ASPM_FORCE_CTL, RTSX_ASPM_FORCE_MASK, RTSX_FORCE_ASPM_NO_ASPM); 1154926ce35aSJung-uk Kim /* Switch LDO3318 source from DV33 to 3V3. */ 1155926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33); 1156926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33, RTSX_LDO_PWR_SEL_3V3); 1157926ce35aSJung-uk Kim /* Set default OLT blink period. */ 1158926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OLT_LED_CTL, 0x0F, RTSX_OLT_LED_PERIOD); 1159926ce35aSJung-uk Kim /* Configure driving. */ 1160926ce35aSJung-uk Kim if ((error = rtsx_rts5249_fill_driving(sc))) 1161926ce35aSJung-uk Kim return (error); 1162926ce35aSJung-uk Kim /* Configure force_clock_req. */ 1163926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) 1164926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB0, 0xB0); 1165926ce35aSJung-uk Kim else 1166926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB0, 0x80); 1167926ce35aSJung-uk Kim 1168926ce35aSJung-uk Kim /* Specifc for RTS525A. */ 1169926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PCLK_CTL, RTSX_PCLK_MODE_SEL, RTSX_PCLK_MODE_SEL); 1170926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_VERSION_A) { 1171926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_L1SUB_CONFIG2, RTSX_L1SUB_AUTO_CFG); 1172926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_RREF_CFG, 1173926ce35aSJung-uk Kim RTSX_RREF_VBGSEL_MASK, RTSX_RREF_VBGSEL_1V25); 1174926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_VIO_CFG, 1175926ce35aSJung-uk Kim RTSX_LDO_VIO_TUNE_MASK, RTSX_LDO_VIO_1V7); 1176926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_DV12S_CFG, 1177926ce35aSJung-uk Kim RTSX_LDO_D12_TUNE_MASK, RTSX_LDO_D12_TUNE_DF); 1178926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_AV12S_CFG, 1179926ce35aSJung-uk Kim RTSX_LDO_AV12S_TUNE_MASK, RTSX_LDO_AV12S_TUNE_DF); 1180926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_VCC_CFG0, 1181926ce35aSJung-uk Kim RTSX_LDO_VCC_LMTVTH_MASK, RTSX_LDO_VCC_LMTVTH_2A); 1182926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OOBS_CONFIG, 1183926ce35aSJung-uk Kim RTSX_OOBS_AUTOK_DIS | RTSX_OOBS_VAL_MASK, 0x89); 1184926ce35aSJung-uk Kim } 1185926ce35aSJung-uk Kim break; 1186926ce35aSJung-uk Kim case RTSX_RTS5249: 1187926ce35aSJung-uk Kim /* Rest L1SUB Config. */ 1188926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_L1SUB_CONFIG3, 0xff); 1189926ce35aSJung-uk Kim /* Configure GPIO as output. */ 1190926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON, RTSX_GPIO_LED_ON); 1191926ce35aSJung-uk Kim /* Reset ASPM state to default value. */ 1192926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_ASPM_FORCE_CTL, RTSX_ASPM_FORCE_MASK, RTSX_FORCE_ASPM_NO_ASPM); 1193926ce35aSJung-uk Kim /* Switch LDO3318 source from DV33 to 3V3. */ 1194926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33); 1195926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33, RTSX_LDO_PWR_SEL_3V3); 1196926ce35aSJung-uk Kim /* Set default OLT blink period. */ 1197926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_OLT_LED_CTL, 0x0F, RTSX_OLT_LED_PERIOD); 1198926ce35aSJung-uk Kim /* Configure driving. */ 1199926ce35aSJung-uk Kim if ((error = rtsx_rts5249_fill_driving(sc))) 1200926ce35aSJung-uk Kim return (error); 1201926ce35aSJung-uk Kim /* Configure force_clock_req. */ 1202926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) 1203926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB0, 0xB0); 1204926ce35aSJung-uk Kim else 1205926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PETXCFG, 0xB0, 0x80); 1206926ce35aSJung-uk Kim break; 1207577130e5SHenri Hennebert case RTSX_RTS5260: 1208577130e5SHenri Hennebert /* Set mcu_cnt to 7 to ensure data can be sampled properly. */ 1209577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_CLK_DIV, 0x07, 0x07); 1210577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_SSC_DIV_N_0, 0x5D); 12118290c144SHenri Hennebert /* Force no MDIO */ 1212577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_RTS5260_AUTOLOAD_CFG4, RTSX_RTS5260_MIMO_DISABLE); 1213577130e5SHenri Hennebert /* Modify SDVCC Tune Default Parameters! */ 1214577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_VCC_CFG0, RTSX_RTS5260_DVCC_TUNE_MASK, RTSX_RTS5260_DVCC_33); 12158290c144SHenri Hennebert 1216577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_PCLK_CTL, RTSX_PCLK_MODE_SEL, RTSX_PCLK_MODE_SEL); 12178290c144SHenri Hennebert 1218577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_L1SUB_CONFIG1, RTSX_AUX_CLK_ACTIVE_SEL_MASK, RTSX_MAC_CKSW_DONE); 1219577130e5SHenri Hennebert /* Rest L1SUB Config */ 1220577130e5SHenri Hennebert RTSX_CLR(sc, RTSX_L1SUB_CONFIG3, 0xFF); 1221577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_PM_CLK_FORCE_CTL, RTSX_CLK_PM_EN, RTSX_CLK_PM_EN); 12228290c144SHenri Hennebert RTSX_WRITE(sc, RTSX_PWD_SUSPEND_EN, 0xFF); 1223577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_PWR_GATE_EN, RTSX_PWR_GATE_EN); 12248290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_REG_VREF, RTSX_PWD_SUSPND_EN, RTSX_PWD_SUSPND_EN); 12258290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_RBCTL, RTSX_U_AUTO_DMA_EN_MASK, RTSX_U_AUTO_DMA_DISABLE); 1226577130e5SHenri Hennebert if (sc->rtsx_flags & RTSX_F_REVERSE_SOCKET) 1227577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_PETXCFG, 0xB0, 0xB0); 1228577130e5SHenri Hennebert else 1229577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_PETXCFG, 0xB0, 0x80); 1230577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_OBFF_CFG, RTSX_OBFF_EN_MASK, RTSX_OBFF_DISABLE); 12318290c144SHenri Hennebert 12328290c144SHenri Hennebert RTSX_CLR(sc, RTSX_RTS5260_DVCC_CTRL, RTSX_RTS5260_DVCC_OCP_EN | RTSX_RTS5260_DVCC_OCP_CL_EN); 12338290c144SHenri Hennebert 12348290c144SHenri Hennebert /* CLKREQ# PIN will be forced to drive low. */ 12358290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_PETXCFG, RTSX_FORCE_CLKREQ_DELINK_MASK, RTSX_FORCE_CLKREQ_LOW); 12368290c144SHenri Hennebert 12378290c144SHenri Hennebert RTSX_CLR(sc, RTSX_RTS522A_PM_CTRL3, 0x10); 1238577130e5SHenri Hennebert break; 1239926ce35aSJung-uk Kim case RTSX_RTL8402: 1240926ce35aSJung-uk Kim case RTSX_RTL8411: 1241926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, sc->rtsx_sd30_drive_sel_3v3); 1242926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PAD_CTL, RTSX_CD_DISABLE_MASK | RTSX_CD_AUTO_DISABLE, 1243926ce35aSJung-uk Kim RTSX_CD_ENABLE); 1244926ce35aSJung-uk Kim break; 1245926ce35aSJung-uk Kim case RTSX_RTL8411B: 1246926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_8411B_QFN48) 1247926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xf5); 1248926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, sc->rtsx_sd30_drive_sel_3v3); 1249926ce35aSJung-uk Kim /* Enable SD interrupt. */ 1250926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PAD_CTL, RTSX_CD_DISABLE_MASK | RTSX_CD_AUTO_DISABLE, 1251926ce35aSJung-uk Kim RTSX_CD_ENABLE); 1252926ce35aSJung-uk Kim /* Clear hw_pfm_en to disable hardware PFM mode. */ 1253926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_FUNC_FORCE_CTL, 0x06, 0x00); 1254926ce35aSJung-uk Kim break; 1255926ce35aSJung-uk Kim } 1256926ce35aSJung-uk Kim 1257926ce35aSJung-uk Kim /*!!! Added for reboot after Windows. */ 1258926ce35aSJung-uk Kim rtsx_bus_power_off(sc); 1259926ce35aSJung-uk Kim rtsx_set_sd_timing(sc, bus_timing_normal); 1260926ce35aSJung-uk Kim rtsx_set_sd_clock(sc, 0); 1261926ce35aSJung-uk Kim /*!!! Added for reboot after Windows. */ 1262926ce35aSJung-uk Kim 1263926ce35aSJung-uk Kim return (0); 1264926ce35aSJung-uk Kim } 1265926ce35aSJung-uk Kim 1266926ce35aSJung-uk Kim static int 1267926ce35aSJung-uk Kim rtsx_map_sd_drive(int index) 1268926ce35aSJung-uk Kim { 1269926ce35aSJung-uk Kim uint8_t sd_drive[4] = 1270926ce35aSJung-uk Kim { 1271926ce35aSJung-uk Kim 0x01, /* Type D */ 1272926ce35aSJung-uk Kim 0x02, /* Type C */ 1273926ce35aSJung-uk Kim 0x05, /* Type A */ 1274926ce35aSJung-uk Kim 0x03 /* Type B */ 1275926ce35aSJung-uk Kim }; 1276926ce35aSJung-uk Kim return (sd_drive[index]); 1277926ce35aSJung-uk Kim } 1278926ce35aSJung-uk Kim 1279926ce35aSJung-uk Kim /* For voltage 3v3. */ 1280926ce35aSJung-uk Kim static int 1281926ce35aSJung-uk Kim rtsx_rts5227_fill_driving(struct rtsx_softc *sc) 1282926ce35aSJung-uk Kim { 1283926ce35aSJung-uk Kim u_char driving_3v3[4][3] = { 1284926ce35aSJung-uk Kim {0x13, 0x13, 0x13}, 1285926ce35aSJung-uk Kim {0x96, 0x96, 0x96}, 1286926ce35aSJung-uk Kim {0x7F, 0x7F, 0x7F}, 1287926ce35aSJung-uk Kim {0x96, 0x96, 0x96}, 1288926ce35aSJung-uk Kim }; 1289926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CLK_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][0]); 1290926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][1]); 1291926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_DAT_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][2]); 1292926ce35aSJung-uk Kim 1293926ce35aSJung-uk Kim return (0); 1294926ce35aSJung-uk Kim } 1295926ce35aSJung-uk Kim 1296926ce35aSJung-uk Kim /* For voltage 3v3. */ 1297926ce35aSJung-uk Kim static int 1298926ce35aSJung-uk Kim rtsx_rts5249_fill_driving(struct rtsx_softc *sc) 1299926ce35aSJung-uk Kim { 1300926ce35aSJung-uk Kim u_char driving_3v3[4][3] = { 1301926ce35aSJung-uk Kim {0x11, 0x11, 0x18}, 1302926ce35aSJung-uk Kim {0x55, 0x55, 0x5C}, 1303926ce35aSJung-uk Kim {0xFF, 0xFF, 0xFF}, 1304926ce35aSJung-uk Kim {0x96, 0x96, 0x96}, 1305926ce35aSJung-uk Kim }; 1306926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CLK_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][0]); 1307926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][1]); 1308926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD30_DAT_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][2]); 1309926ce35aSJung-uk Kim 1310926ce35aSJung-uk Kim return (0); 1311926ce35aSJung-uk Kim } 1312926ce35aSJung-uk Kim 1313926ce35aSJung-uk Kim static int 1314577130e5SHenri Hennebert rtsx_rts5260_fill_driving(struct rtsx_softc *sc) 1315577130e5SHenri Hennebert { 1316577130e5SHenri Hennebert u_char driving_3v3[4][3] = { 1317577130e5SHenri Hennebert {0x11, 0x11, 0x11}, 1318577130e5SHenri Hennebert {0x22, 0x22, 0x22}, 1319577130e5SHenri Hennebert {0x55, 0x55, 0x55}, 1320577130e5SHenri Hennebert {0x33, 0x33, 0x33}, 1321577130e5SHenri Hennebert }; 1322577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_SD30_CLK_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][0]); 1323577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_SD30_CMD_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][1]); 1324577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_SD30_DAT_DRIVE_SEL, driving_3v3[sc->rtsx_sd30_drive_sel_3v3][2]); 1325577130e5SHenri Hennebert 1326577130e5SHenri Hennebert return (0); 1327577130e5SHenri Hennebert } 1328577130e5SHenri Hennebert 1329577130e5SHenri Hennebert static int 1330926ce35aSJung-uk Kim rtsx_read(struct rtsx_softc *sc, uint16_t addr, uint8_t *val) 1331926ce35aSJung-uk Kim { 1332926ce35aSJung-uk Kim int tries = 1024; 13339b261d2eSHenri Hennebert uint32_t arg; 1334926ce35aSJung-uk Kim uint32_t reg; 1335926ce35aSJung-uk Kim 13369b261d2eSHenri Hennebert arg = RTSX_HAIMR_BUSY | (uint32_t)((addr & 0x3FFF) << 16); 13379b261d2eSHenri Hennebert WRITE4(sc, RTSX_HAIMR, arg); 1338926ce35aSJung-uk Kim 1339926ce35aSJung-uk Kim while (tries--) { 1340926ce35aSJung-uk Kim reg = READ4(sc, RTSX_HAIMR); 1341926ce35aSJung-uk Kim if (!(reg & RTSX_HAIMR_BUSY)) 1342926ce35aSJung-uk Kim break; 1343926ce35aSJung-uk Kim } 1344926ce35aSJung-uk Kim *val = (reg & 0xff); 1345926ce35aSJung-uk Kim 13469b261d2eSHenri Hennebert if (tries > 0) { 13479b261d2eSHenri Hennebert return (0); 13489b261d2eSHenri Hennebert } else { 13499b261d2eSHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_read(0x%x) timeout\n", arg); 13509b261d2eSHenri Hennebert return (ETIMEDOUT); 13519b261d2eSHenri Hennebert } 1352926ce35aSJung-uk Kim } 1353926ce35aSJung-uk Kim 1354926ce35aSJung-uk Kim static int 1355926ce35aSJung-uk Kim rtsx_read_cfg(struct rtsx_softc *sc, uint8_t func, uint16_t addr, uint32_t *val) 1356926ce35aSJung-uk Kim { 1357926ce35aSJung-uk Kim int tries = 1024; 1358926ce35aSJung-uk Kim uint8_t data0, data1, data2, data3, rwctl; 1359926ce35aSJung-uk Kim 1360926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CFGADDR0, addr); 1361926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CFGADDR1, addr >> 8); 1362926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CFGRWCTL, RTSX_CFG_BUSY | (func & 0x03 << 4)); 1363926ce35aSJung-uk Kim 1364926ce35aSJung-uk Kim while (tries--) { 1365926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_CFGRWCTL, &rwctl); 1366926ce35aSJung-uk Kim if (!(rwctl & RTSX_CFG_BUSY)) 1367926ce35aSJung-uk Kim break; 1368926ce35aSJung-uk Kim } 1369926ce35aSJung-uk Kim 1370926ce35aSJung-uk Kim if (tries == 0) 1371926ce35aSJung-uk Kim return (ETIMEDOUT); 1372926ce35aSJung-uk Kim 1373926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_CFGDATA0, &data0); 1374926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_CFGDATA1, &data1); 1375926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_CFGDATA2, &data2); 1376926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_CFGDATA3, &data3); 1377926ce35aSJung-uk Kim 1378926ce35aSJung-uk Kim *val = (data3 << 24) | (data2 << 16) | (data1 << 8) | data0; 1379926ce35aSJung-uk Kim 1380926ce35aSJung-uk Kim return (0); 1381926ce35aSJung-uk Kim } 1382926ce35aSJung-uk Kim 1383926ce35aSJung-uk Kim static int 1384926ce35aSJung-uk Kim rtsx_write(struct rtsx_softc *sc, uint16_t addr, uint8_t mask, uint8_t val) 1385926ce35aSJung-uk Kim { 1386926ce35aSJung-uk Kim int tries = 1024; 13879b261d2eSHenri Hennebert uint32_t arg; 1388926ce35aSJung-uk Kim uint32_t reg; 1389926ce35aSJung-uk Kim 13909b261d2eSHenri Hennebert arg = RTSX_HAIMR_BUSY | RTSX_HAIMR_WRITE | 1391926ce35aSJung-uk Kim (uint32_t)(((addr & 0x3FFF) << 16) | 13929b261d2eSHenri Hennebert (mask << 8) | val); 13939b261d2eSHenri Hennebert WRITE4(sc, RTSX_HAIMR, arg); 1394926ce35aSJung-uk Kim 1395926ce35aSJung-uk Kim while (tries--) { 1396926ce35aSJung-uk Kim reg = READ4(sc, RTSX_HAIMR); 1397926ce35aSJung-uk Kim if (!(reg & RTSX_HAIMR_BUSY)) { 13989b261d2eSHenri Hennebert if (val != (reg & 0xff)) { 13999b261d2eSHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_write(0x%x) error reg=0x%x\n", arg, reg); 1400926ce35aSJung-uk Kim return (EIO); 14019b261d2eSHenri Hennebert } 1402926ce35aSJung-uk Kim return (0); 1403926ce35aSJung-uk Kim } 1404926ce35aSJung-uk Kim } 14059b261d2eSHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_write(0x%x) timeout\n", arg); 1406926ce35aSJung-uk Kim 1407926ce35aSJung-uk Kim return (ETIMEDOUT); 1408926ce35aSJung-uk Kim } 1409926ce35aSJung-uk Kim 1410926ce35aSJung-uk Kim static int 1411926ce35aSJung-uk Kim rtsx_read_phy(struct rtsx_softc *sc, uint8_t addr, uint16_t *val) 1412926ce35aSJung-uk Kim { 1413926ce35aSJung-uk Kim int tries = 100000; 1414926ce35aSJung-uk Kim uint8_t data0, data1, rwctl; 1415926ce35aSJung-uk Kim 1416926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PHY_ADDR, addr); 1417926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PHY_RWCTL, RTSX_PHY_BUSY | RTSX_PHY_READ); 1418926ce35aSJung-uk Kim 1419926ce35aSJung-uk Kim while (tries--) { 1420926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_PHY_RWCTL, &rwctl); 1421926ce35aSJung-uk Kim if (!(rwctl & RTSX_PHY_BUSY)) 1422926ce35aSJung-uk Kim break; 1423926ce35aSJung-uk Kim } 1424926ce35aSJung-uk Kim if (tries == 0) 1425926ce35aSJung-uk Kim return (ETIMEDOUT); 1426926ce35aSJung-uk Kim 1427926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_PHY_DATA0, &data0); 1428926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_PHY_DATA1, &data1); 1429926ce35aSJung-uk Kim *val = data1 << 8 | data0; 1430926ce35aSJung-uk Kim 1431926ce35aSJung-uk Kim return (0); 1432926ce35aSJung-uk Kim } 1433926ce35aSJung-uk Kim 1434926ce35aSJung-uk Kim static int 1435926ce35aSJung-uk Kim rtsx_write_phy(struct rtsx_softc *sc, uint8_t addr, uint16_t val) 1436926ce35aSJung-uk Kim { 1437926ce35aSJung-uk Kim int tries = 100000; 1438926ce35aSJung-uk Kim uint8_t rwctl; 1439926ce35aSJung-uk Kim 1440926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PHY_DATA0, val); 1441926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PHY_DATA1, val >> 8); 1442926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PHY_ADDR, addr); 1443926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_PHY_RWCTL, RTSX_PHY_BUSY | RTSX_PHY_WRITE); 1444926ce35aSJung-uk Kim 1445926ce35aSJung-uk Kim while (tries--) { 1446926ce35aSJung-uk Kim RTSX_READ(sc, RTSX_PHY_RWCTL, &rwctl); 1447926ce35aSJung-uk Kim if (!(rwctl & RTSX_PHY_BUSY)) 1448926ce35aSJung-uk Kim break; 1449926ce35aSJung-uk Kim } 1450926ce35aSJung-uk Kim 1451926ce35aSJung-uk Kim return ((tries == 0) ? ETIMEDOUT : 0); 1452926ce35aSJung-uk Kim } 1453926ce35aSJung-uk Kim 1454926ce35aSJung-uk Kim /* 1455926ce35aSJung-uk Kim * Notice that the meaning of RTSX_PWR_GATE_CTRL changes between RTS5209 and 1456926ce35aSJung-uk Kim * RTS5229. In RTS5209 it is a mask of disabled power gates, while in RTS5229 1457926ce35aSJung-uk Kim * it is a mask of *enabled* gates. 1458926ce35aSJung-uk Kim */ 1459926ce35aSJung-uk Kim static int 1460926ce35aSJung-uk Kim rtsx_bus_power_off(struct rtsx_softc *sc) 1461926ce35aSJung-uk Kim { 1462577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 1463926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_bus_power_off()\n"); 1464926ce35aSJung-uk Kim 1465926ce35aSJung-uk Kim /* Disable SD clock. */ 1466926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_CLK_EN, RTSX_SD_CLK_EN); 1467926ce35aSJung-uk Kim 1468926ce35aSJung-uk Kim /* Disable SD output. */ 1469926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_OE, RTSX_SD_OUTPUT_EN); 1470926ce35aSJung-uk Kim 1471926ce35aSJung-uk Kim /* Turn off power. */ 1472926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1473926ce35aSJung-uk Kim case RTSX_RTS5209: 1474926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK | RTSX_PMOS_STRG_MASK, 1475926ce35aSJung-uk Kim RTSX_SD_PWR_OFF | RTSX_PMOS_STRG_400mA); 1476926ce35aSJung-uk Kim RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF); 1477926ce35aSJung-uk Kim break; 1478926ce35aSJung-uk Kim case RTSX_RTS5227: 1479926ce35aSJung-uk Kim case RTSX_RTS5229: 1480926ce35aSJung-uk Kim case RTSX_RTS522A: 1481926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK | RTSX_PMOS_STRG_MASK, 1482926ce35aSJung-uk Kim RTSX_SD_PWR_OFF | RTSX_PMOS_STRG_400mA); 1483926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK); 1484926ce35aSJung-uk Kim break; 1485577130e5SHenri Hennebert case RTSX_RTS5260: 14868290c144SHenri Hennebert rtsx_stop_cmd(sc); 14878290c144SHenri Hennebert /* Switch vccq to 330 */ 14888290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_CONFIG2, RTSX_DV331812_VDD1, RTSX_DV331812_VDD1); 14898290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_DV18_CFG, RTSX_DV331812_MASK, RTSX_DV331812_33); 14908290c144SHenri Hennebert RTSX_CLR(sc, RTSX_SD_PAD_CTL, RTSX_SD_IO_USING_1V8); 14918290c144SHenri Hennebert rtsx_rts5260_fill_driving(sc); 14928290c144SHenri Hennebert 1493577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_VCC_CFG1, RTSX_LDO_POW_SDVDD1_MASK, RTSX_LDO_POW_SDVDD1_OFF); 1494577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_CONFIG2, RTSX_DV331812_POWERON, RTSX_DV331812_POWEROFF); 1495577130e5SHenri Hennebert break; 1496926ce35aSJung-uk Kim case RTSX_RTL8402: 1497926ce35aSJung-uk Kim case RTSX_RTL8411: 1498926ce35aSJung-uk Kim case RTSX_RTL8411B: 1499926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_BPP_POWER_MASK, 1500926ce35aSJung-uk Kim RTSX_BPP_POWER_OFF); 1501926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_CTL, RTSX_BPP_LDO_POWB, 1502926ce35aSJung-uk Kim RTSX_BPP_LDO_SUSPEND); 1503926ce35aSJung-uk Kim break; 1504926ce35aSJung-uk Kim default: 1505926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK); 1506926ce35aSJung-uk Kim RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF); 1507926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_PMOS_STRG_800mA); 1508926ce35aSJung-uk Kim break; 1509926ce35aSJung-uk Kim } 1510926ce35aSJung-uk Kim 1511926ce35aSJung-uk Kim /* Disable pull control. */ 1512926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1513926ce35aSJung-uk Kim case RTSX_RTS5209: 1514926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, RTSX_PULL_CTL_DISABLE12); 1515926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_DISABLE12); 1516926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_DISABLE3); 1517926ce35aSJung-uk Kim break; 1518926ce35aSJung-uk Kim case RTSX_RTS5227: 1519926ce35aSJung-uk Kim case RTSX_RTS522A: 1520926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_DISABLE12); 1521926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_DISABLE3); 1522926ce35aSJung-uk Kim break; 1523926ce35aSJung-uk Kim case RTSX_RTS5229: 1524926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_DISABLE12); 1525926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_VERSION_C) 1526926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_DISABLE3_TYPE_C); 1527926ce35aSJung-uk Kim else 1528926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_DISABLE3); 1529926ce35aSJung-uk Kim break; 1530926ce35aSJung-uk Kim case RTSX_RTS525A: 1531926ce35aSJung-uk Kim case RTSX_RTS5249: 1532577130e5SHenri Hennebert case RTSX_RTS5260: 1533926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0x66); 1534926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_DISABLE12); 1535926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_DISABLE3); 1536926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0x55); 1537926ce35aSJung-uk Kim break; 1538926ce35aSJung-uk Kim case RTSX_RTL8402: 1539926ce35aSJung-uk Kim case RTSX_RTL8411: 1540926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0x65); 1541926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0x55); 1542926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0x95); 1543926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0x09); 1544926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL5, 0x05); 1545926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x04); 1546926ce35aSJung-uk Kim break; 1547926ce35aSJung-uk Kim case RTSX_RTL8411B: 1548926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_8411B_QFN48) { 1549926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0x55); 1550926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xf5); 1551926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x15); 1552926ce35aSJung-uk Kim } else { 1553926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0x65); 1554926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0x55); 1555926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xd5); 1556926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0x59); 1557926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL5, 0x55); 1558926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x15); 1559926ce35aSJung-uk Kim } 1560926ce35aSJung-uk Kim break; 1561926ce35aSJung-uk Kim } 1562926ce35aSJung-uk Kim 1563926ce35aSJung-uk Kim return (0); 1564926ce35aSJung-uk Kim } 1565926ce35aSJung-uk Kim 1566926ce35aSJung-uk Kim static int 1567926ce35aSJung-uk Kim rtsx_bus_power_on(struct rtsx_softc *sc) 1568926ce35aSJung-uk Kim { 1569577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 1570926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_bus_power_on()\n"); 1571926ce35aSJung-uk Kim 1572926ce35aSJung-uk Kim /* Select SD card. */ 1573926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_SELECT, 0x07, RTSX_SD_MOD_SEL); 1574926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_SHARE_MODE, RTSX_CARD_SHARE_MASK, RTSX_CARD_SHARE_48_SD); 1575926ce35aSJung-uk Kim 1576926ce35aSJung-uk Kim /* Enable SD clock. */ 1577926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_CLK_EN, RTSX_SD_CLK_EN, RTSX_SD_CLK_EN); 1578926ce35aSJung-uk Kim 1579926ce35aSJung-uk Kim /* Enable pull control. */ 1580926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1581926ce35aSJung-uk Kim case RTSX_RTS5209: 1582926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, RTSX_PULL_CTL_ENABLE12); 1583926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_ENABLE12); 1584926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_ENABLE3); 1585926ce35aSJung-uk Kim break; 1586926ce35aSJung-uk Kim case RTSX_RTS5227: 1587926ce35aSJung-uk Kim case RTSX_RTS522A: 1588926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_ENABLE12); 1589926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_ENABLE3); 1590926ce35aSJung-uk Kim break; 1591926ce35aSJung-uk Kim case RTSX_RTS5229: 1592926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_ENABLE12); 1593926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_VERSION_C) 1594926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_ENABLE3_TYPE_C); 1595926ce35aSJung-uk Kim else 1596926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_ENABLE3); 1597926ce35aSJung-uk Kim break; 1598926ce35aSJung-uk Kim case RTSX_RTS525A: 1599926ce35aSJung-uk Kim case RTSX_RTS5249: 1600577130e5SHenri Hennebert case RTSX_RTS5260: 1601926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0x66); 1602926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_ENABLE12); 1603926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_ENABLE3); 1604926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0xaa); 1605926ce35aSJung-uk Kim break; 1606926ce35aSJung-uk Kim case RTSX_RTL8402: 1607926ce35aSJung-uk Kim case RTSX_RTL8411: 1608926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0xaa); 1609926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0xaa); 1610926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xa9); 1611926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0x09); 1612926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL5, 0x09); 1613926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x04); 1614926ce35aSJung-uk Kim break; 1615926ce35aSJung-uk Kim case RTSX_RTL8411B: 1616926ce35aSJung-uk Kim if (sc->rtsx_flags & RTSX_F_8411B_QFN48) { 1617926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0xaa); 1618926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xf9); 1619926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x19); 1620926ce35aSJung-uk Kim } else { 1621926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0xaa); 1622926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0xaa); 1623926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xd9); 1624926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0x59); 1625926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL5, 0x55); 1626926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x15); 1627926ce35aSJung-uk Kim } 1628926ce35aSJung-uk Kim break; 1629926ce35aSJung-uk Kim } 1630926ce35aSJung-uk Kim 1631926ce35aSJung-uk Kim /* 1632926ce35aSJung-uk Kim * To avoid a current peak, enable card power in two phases 1633926ce35aSJung-uk Kim * with a delay in between. 1634926ce35aSJung-uk Kim */ 1635926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1636926ce35aSJung-uk Kim case RTSX_RTS5209: 1637926ce35aSJung-uk Kim /* Partial power. */ 1638926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PARTIAL_PWR_ON); 1639926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, RTSX_LDO3318_VCC2); 1640926ce35aSJung-uk Kim 1641926ce35aSJung-uk Kim DELAY(200); 1642926ce35aSJung-uk Kim 1643926ce35aSJung-uk Kim /* Full power. */ 1644926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PWR_ON); 1645926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, RTSX_LDO3318_ON); 1646926ce35aSJung-uk Kim break; 1647926ce35aSJung-uk Kim case RTSX_RTS5227: 1648926ce35aSJung-uk Kim case RTSX_RTS522A: 1649926ce35aSJung-uk Kim /* Partial power. */ 1650926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PARTIAL_PWR_ON); 1651926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, RTSX_LDO3318_VCC1); 1652926ce35aSJung-uk Kim 16539d3bc163SHenri Hennebert DELAY(20000); 1654926ce35aSJung-uk Kim 1655926ce35aSJung-uk Kim /* Full power. */ 1656926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PWR_ON); 1657926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, 1658926ce35aSJung-uk Kim RTSX_LDO3318_VCC1 | RTSX_LDO3318_VCC2); 1659926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_OE, RTSX_SD_OUTPUT_EN, RTSX_SD_OUTPUT_EN); 1660926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_OE, RTSX_MS_OUTPUT_EN, RTSX_MS_OUTPUT_EN); 1661926ce35aSJung-uk Kim break; 1662926ce35aSJung-uk Kim case RTSX_RTS5229: 1663926ce35aSJung-uk Kim /* Partial power. */ 1664926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PARTIAL_PWR_ON); 1665926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, RTSX_LDO3318_VCC1); 1666926ce35aSJung-uk Kim 1667926ce35aSJung-uk Kim DELAY(200); 1668926ce35aSJung-uk Kim 1669926ce35aSJung-uk Kim /* Full power. */ 1670926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PWR_ON); 1671926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, 1672926ce35aSJung-uk Kim RTSX_LDO3318_VCC1 | RTSX_LDO3318_VCC2); 1673926ce35aSJung-uk Kim break; 1674926ce35aSJung-uk Kim case RTSX_RTS525A: 1675926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_VCC_CFG1, RTSX_LDO_VCC_TUNE_MASK, RTSX_LDO_VCC_3V3); 1676926ce35aSJung-uk Kim case RTSX_RTS5249: 1677926ce35aSJung-uk Kim /* Partial power. */ 1678926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PARTIAL_PWR_ON); 1679926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, RTSX_LDO3318_VCC1); 1680926ce35aSJung-uk Kim 16819d3bc163SHenri Hennebert DELAY(5000); 1682926ce35aSJung-uk Kim 1683926ce35aSJung-uk Kim /* Full power. */ 1684926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_MASK, RTSX_SD_PWR_ON); 1685926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_PWR_MASK, 1686926ce35aSJung-uk Kim RTSX_LDO3318_VCC1 | RTSX_LDO3318_VCC2); 1687926ce35aSJung-uk Kim break; 1688577130e5SHenri Hennebert case RTSX_RTS5260: 1689577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_CONFIG2, RTSX_DV331812_VDD1, RTSX_DV331812_VDD1); 1690577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_VCC_CFG0, RTSX_RTS5260_DVCC_TUNE_MASK, RTSX_RTS5260_DVCC_33); 1691577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_VCC_CFG1, RTSX_LDO_POW_SDVDD1_MASK, RTSX_LDO_POW_SDVDD1_ON); 1692577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_CONFIG2, RTSX_DV331812_POWERON, RTSX_DV331812_POWERON); 1693577130e5SHenri Hennebert 1694577130e5SHenri Hennebert DELAY(20000); 1695577130e5SHenri Hennebert 16968290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_SD_CFG1, RTSX_SD_MODE_MASK | RTSX_SD_ASYNC_FIFO_NOT_RST, 16978290c144SHenri Hennebert RTSX_SD30_MODE | RTSX_SD_ASYNC_FIFO_NOT_RST); 16988290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_CLK_CTL, RTSX_CHANGE_CLK, RTSX_CLK_LOW_FREQ); 16998290c144SHenri Hennebert RTSX_WRITE(sc, RTSX_CARD_CLK_SOURCE, 17008290c144SHenri Hennebert RTSX_CRC_VAR_CLK0 | RTSX_SD30_FIX_CLK | RTSX_SAMPLE_VAR_CLK1); 17018290c144SHenri Hennebert RTSX_CLR(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ); 17028290c144SHenri Hennebert 1703577130e5SHenri Hennebert /* Initialize SD_CFG1 register */ 1704577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_128 | RTSX_SD20_MODE); 1705577130e5SHenri Hennebert RTSX_WRITE(sc, RTSX_SD_SAMPLE_POINT_CTL, RTSX_SD20_RX_POS_EDGE); 1706577130e5SHenri Hennebert RTSX_CLR(sc, RTSX_SD_PUSH_POINT_CTL, 0xff); 17078290c144SHenri Hennebert RTSX_BITOP(sc, RTSX_CARD_STOP, RTSX_SD_STOP | RTSX_SD_CLR_ERR, 17088290c144SHenri Hennebert RTSX_SD_STOP | RTSX_SD_CLR_ERR); 1709577130e5SHenri Hennebert /* Reset SD_CFG3 register */ 1710577130e5SHenri Hennebert RTSX_CLR(sc, RTSX_SD_CFG3, RTSX_SD30_CLK_END_EN); 1711577130e5SHenri Hennebert RTSX_CLR(sc, RTSX_REG_SD_STOP_SDCLK_CFG, 1712577130e5SHenri Hennebert RTSX_SD30_CLK_STOP_CFG_EN | RTSX_SD30_CLK_STOP_CFG0 | RTSX_SD30_CLK_STOP_CFG1); 1713577130e5SHenri Hennebert RTSX_CLR(sc, RTSX_REG_PRE_RW_MODE, RTSX_EN_INFINITE_MODE); 1714577130e5SHenri Hennebert break; 1715926ce35aSJung-uk Kim case RTSX_RTL8402: 1716926ce35aSJung-uk Kim case RTSX_RTL8411: 1717926ce35aSJung-uk Kim case RTSX_RTL8411B: 1718926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_BPP_POWER_MASK, 1719926ce35aSJung-uk Kim RTSX_BPP_POWER_5_PERCENT_ON); 1720926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_CTL, RTSX_BPP_LDO_POWB, 1721926ce35aSJung-uk Kim RTSX_BPP_LDO_SUSPEND); 1722926ce35aSJung-uk Kim DELAY(150); 1723926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_BPP_POWER_MASK, 1724926ce35aSJung-uk Kim RTSX_BPP_POWER_10_PERCENT_ON); 1725926ce35aSJung-uk Kim DELAY(150); 1726926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_BPP_POWER_MASK, 1727926ce35aSJung-uk Kim RTSX_BPP_POWER_15_PERCENT_ON); 1728926ce35aSJung-uk Kim DELAY(150); 1729926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_PWR_CTL, RTSX_BPP_POWER_MASK, 1730926ce35aSJung-uk Kim RTSX_BPP_POWER_ON); 1731926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_CTL, RTSX_BPP_LDO_POWB, 1732926ce35aSJung-uk Kim RTSX_BPP_LDO_ON); 1733926ce35aSJung-uk Kim break; 1734926ce35aSJung-uk Kim } 1735926ce35aSJung-uk Kim 1736926ce35aSJung-uk Kim /* Enable SD card output. */ 1737926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_OE, RTSX_SD_OUTPUT_EN); 1738926ce35aSJung-uk Kim 1739926ce35aSJung-uk Kim DELAY(200); 1740926ce35aSJung-uk Kim 1741926ce35aSJung-uk Kim return (0); 1742926ce35aSJung-uk Kim } 1743926ce35aSJung-uk Kim 1744926ce35aSJung-uk Kim /* 1745926ce35aSJung-uk Kim * Set but width. 1746926ce35aSJung-uk Kim */ 1747926ce35aSJung-uk Kim static int 1748926ce35aSJung-uk Kim rtsx_set_bus_width(struct rtsx_softc *sc, enum mmc_bus_width width) 1749926ce35aSJung-uk Kim { 1750926ce35aSJung-uk Kim uint32_t bus_width; 1751926ce35aSJung-uk Kim 1752926ce35aSJung-uk Kim switch (width) { 1753926ce35aSJung-uk Kim case bus_width_1: 1754926ce35aSJung-uk Kim bus_width = RTSX_BUS_WIDTH_1; 1755926ce35aSJung-uk Kim break; 1756926ce35aSJung-uk Kim case bus_width_4: 1757926ce35aSJung-uk Kim bus_width = RTSX_BUS_WIDTH_4; 1758926ce35aSJung-uk Kim break; 1759926ce35aSJung-uk Kim case bus_width_8: 1760926ce35aSJung-uk Kim bus_width = RTSX_BUS_WIDTH_8; 1761926ce35aSJung-uk Kim break; 1762926ce35aSJung-uk Kim default: 1763926ce35aSJung-uk Kim return (MMC_ERR_INVALID); 1764926ce35aSJung-uk Kim } 1765926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_CFG1, RTSX_BUS_WIDTH_MASK, bus_width); 1766926ce35aSJung-uk Kim 1767577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 1768926ce35aSJung-uk Kim char *busw[] = { 1769926ce35aSJung-uk Kim "1 bit", 1770926ce35aSJung-uk Kim "4 bits", 1771926ce35aSJung-uk Kim "8 bits" 1772926ce35aSJung-uk Kim }; 1773926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Setting bus width to %s\n", busw[bus_width]); 1774926ce35aSJung-uk Kim } 1775926ce35aSJung-uk Kim return (0); 1776926ce35aSJung-uk Kim } 1777926ce35aSJung-uk Kim 1778926ce35aSJung-uk Kim static int 1779926ce35aSJung-uk Kim rtsx_set_sd_timing(struct rtsx_softc *sc, enum mmc_bus_timing timing) 1780926ce35aSJung-uk Kim { 1781926ce35aSJung-uk Kim if (timing == bus_timing_hs && sc->rtsx_force_timing) { 1782926ce35aSJung-uk Kim timing = bus_timing_uhs_sdr50; 1783926ce35aSJung-uk Kim sc->rtsx_ios_timing = timing; 1784926ce35aSJung-uk Kim } 1785926ce35aSJung-uk Kim 1786577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 1787926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_set_sd_timing(%u)\n", timing); 1788926ce35aSJung-uk Kim 1789926ce35aSJung-uk Kim switch (timing) { 1790926ce35aSJung-uk Kim case bus_timing_uhs_sdr50: 1791926ce35aSJung-uk Kim case bus_timing_uhs_sdr104: 1792926ce35aSJung-uk Kim sc->rtsx_double_clk = false; 1793926ce35aSJung-uk Kim sc->rtsx_vpclk = true; 1794926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_CFG1, 0x0c | RTSX_SD_ASYNC_FIFO_NOT_RST, 1795926ce35aSJung-uk Kim RTSX_SD30_MODE | RTSX_SD_ASYNC_FIFO_NOT_RST); 1796926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ, RTSX_CLK_LOW_FREQ); 1797926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_CLK_SOURCE, 1798926ce35aSJung-uk Kim RTSX_CRC_VAR_CLK0 | RTSX_SD30_FIX_CLK | RTSX_SAMPLE_VAR_CLK1); 1799926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ); 1800926ce35aSJung-uk Kim break; 1801926ce35aSJung-uk Kim case bus_timing_hs: 1802926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_CFG1, RTSX_SD_MODE_MASK, RTSX_SD20_MODE); 1803926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ, RTSX_CLK_LOW_FREQ); 1804926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_CLK_SOURCE, 1805926ce35aSJung-uk Kim RTSX_CRC_FIX_CLK | RTSX_SD30_VAR_CLK0 | RTSX_SAMPLE_VAR_CLK1); 1806926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ); 1807926ce35aSJung-uk Kim 1808926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_PUSH_POINT_CTL, 1809926ce35aSJung-uk Kim RTSX_SD20_TX_SEL_MASK, RTSX_SD20_TX_14_AHEAD); 1810926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_SAMPLE_POINT_CTL, 1811926ce35aSJung-uk Kim RTSX_SD20_RX_SEL_MASK, RTSX_SD20_RX_14_DELAY); 1812926ce35aSJung-uk Kim break; 1813926ce35aSJung-uk Kim default: 1814926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_CFG1, RTSX_SD_MODE_MASK, RTSX_SD20_MODE); 1815926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ, RTSX_CLK_LOW_FREQ); 1816926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_CLK_SOURCE, 1817926ce35aSJung-uk Kim RTSX_CRC_FIX_CLK | RTSX_SD30_VAR_CLK0 | RTSX_SAMPLE_VAR_CLK1); 1818926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ); 1819926ce35aSJung-uk Kim 1820926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SD_PUSH_POINT_CTL, RTSX_SD20_TX_NEG_EDGE); 1821926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_SAMPLE_POINT_CTL, 1822926ce35aSJung-uk Kim RTSX_SD20_RX_SEL_MASK, RTSX_SD20_RX_POS_EDGE); 1823926ce35aSJung-uk Kim break; 1824926ce35aSJung-uk Kim } 1825926ce35aSJung-uk Kim 1826926ce35aSJung-uk Kim return (0); 1827926ce35aSJung-uk Kim } 1828926ce35aSJung-uk Kim 1829926ce35aSJung-uk Kim /* 1830926ce35aSJung-uk Kim * Set or change SDCLK frequency or disable the SD clock. 1831926ce35aSJung-uk Kim * Return zero on success. 1832926ce35aSJung-uk Kim */ 1833926ce35aSJung-uk Kim static int 1834926ce35aSJung-uk Kim rtsx_set_sd_clock(struct rtsx_softc *sc, uint32_t freq) 1835926ce35aSJung-uk Kim { 1836926ce35aSJung-uk Kim uint8_t clk; 1837926ce35aSJung-uk Kim uint8_t clk_divider, n, div, mcu; 1838926ce35aSJung-uk Kim int error = 0; 1839926ce35aSJung-uk Kim 1840577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 1841926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_set_sd_clock(%u)\n", freq); 1842926ce35aSJung-uk Kim 1843926ce35aSJung-uk Kim if (freq == RTSX_SDCLK_OFF) { 1844926ce35aSJung-uk Kim error = rtsx_stop_sd_clock(sc); 1845926ce35aSJung-uk Kim return error; 1846926ce35aSJung-uk Kim } 1847926ce35aSJung-uk Kim 1848926ce35aSJung-uk Kim sc->rtsx_ssc_depth = RTSX_SSC_DEPTH_500K; 1849926ce35aSJung-uk Kim sc->rtsx_discovery_mode = (freq <= 1000000) ? true : false; 1850926ce35aSJung-uk Kim 1851926ce35aSJung-uk Kim if (sc->rtsx_discovery_mode) { 1852926ce35aSJung-uk Kim /* We use 250k(around) here, in discovery stage. */ 1853926ce35aSJung-uk Kim clk_divider = RTSX_CLK_DIVIDE_128; 1854926ce35aSJung-uk Kim freq = 30000000; 1855926ce35aSJung-uk Kim } else { 1856926ce35aSJung-uk Kim clk_divider = RTSX_CLK_DIVIDE_0; 1857926ce35aSJung-uk Kim } 1858926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_MASK, clk_divider); 1859926ce35aSJung-uk Kim 1860926ce35aSJung-uk Kim freq /= 1000000; 1861926ce35aSJung-uk Kim if (sc->rtsx_discovery_mode || !sc->rtsx_double_clk) 1862926ce35aSJung-uk Kim clk = freq; 1863926ce35aSJung-uk Kim else 1864926ce35aSJung-uk Kim clk = freq * 2; 1865926ce35aSJung-uk Kim 1866926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1867926ce35aSJung-uk Kim case RTSX_RTL8402: 1868926ce35aSJung-uk Kim case RTSX_RTL8411: 1869926ce35aSJung-uk Kim case RTSX_RTL8411B: 1870926ce35aSJung-uk Kim n = clk * 4 / 5 - 2; 1871926ce35aSJung-uk Kim break; 1872926ce35aSJung-uk Kim default: 1873926ce35aSJung-uk Kim n = clk - 2; 1874926ce35aSJung-uk Kim break; 1875926ce35aSJung-uk Kim } 1876926ce35aSJung-uk Kim if ((clk <= 2) || (n > RTSX_MAX_DIV_N)) 1877926ce35aSJung-uk Kim return (MMC_ERR_INVALID); 1878926ce35aSJung-uk Kim 1879926ce35aSJung-uk Kim mcu = 125 / clk + 3; 1880926ce35aSJung-uk Kim if (mcu > 15) 1881926ce35aSJung-uk Kim mcu = 15; 1882926ce35aSJung-uk Kim 1883926ce35aSJung-uk Kim /* Make sure that the SSC clock div_n is not less than RTSX_MIN_DIV_N. */ 1884926ce35aSJung-uk Kim div = RTSX_CLK_DIV_1; 1885926ce35aSJung-uk Kim while ((n < RTSX_MIN_DIV_N) && (div < RTSX_CLK_DIV_8)) { 1886926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 1887926ce35aSJung-uk Kim case RTSX_RTL8402: 1888926ce35aSJung-uk Kim case RTSX_RTL8411: 1889926ce35aSJung-uk Kim case RTSX_RTL8411B: 1890926ce35aSJung-uk Kim n = (((n + 2) * 5 / 4) * 2) * 4 / 5 - 2; 1891926ce35aSJung-uk Kim break; 1892926ce35aSJung-uk Kim default: 1893926ce35aSJung-uk Kim n = (n + 2) * 2 - 2; 1894926ce35aSJung-uk Kim break; 1895926ce35aSJung-uk Kim } 1896926ce35aSJung-uk Kim div++; 1897926ce35aSJung-uk Kim } 1898926ce35aSJung-uk Kim 1899926ce35aSJung-uk Kim if (sc->rtsx_double_clk && sc->rtsx_ssc_depth > 1) 1900926ce35aSJung-uk Kim sc->rtsx_ssc_depth -= 1; 1901926ce35aSJung-uk Kim 1902926ce35aSJung-uk Kim if (div > RTSX_CLK_DIV_1) { 1903926ce35aSJung-uk Kim if (sc->rtsx_ssc_depth > (div - 1)) 1904926ce35aSJung-uk Kim sc->rtsx_ssc_depth -= (div - 1); 1905926ce35aSJung-uk Kim else 1906926ce35aSJung-uk Kim sc->rtsx_ssc_depth = RTSX_SSC_DEPTH_4M; 1907926ce35aSJung-uk Kim } 1908926ce35aSJung-uk Kim 1909926ce35aSJung-uk Kim /* Enable SD clock. */ 1910926ce35aSJung-uk Kim error = rtsx_switch_sd_clock(sc, clk, n, div, mcu); 1911926ce35aSJung-uk Kim 1912926ce35aSJung-uk Kim return (error); 1913926ce35aSJung-uk Kim } 1914926ce35aSJung-uk Kim 1915926ce35aSJung-uk Kim static int 1916926ce35aSJung-uk Kim rtsx_stop_sd_clock(struct rtsx_softc *sc) 1917926ce35aSJung-uk Kim { 1918926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_CLK_EN, RTSX_CARD_CLK_EN_ALL); 1919926ce35aSJung-uk Kim RTSX_SET(sc, RTSX_SD_BUS_STAT, RTSX_SD_CLK_FORCE_STOP); 1920926ce35aSJung-uk Kim 1921926ce35aSJung-uk Kim return (0); 1922926ce35aSJung-uk Kim } 1923926ce35aSJung-uk Kim 1924926ce35aSJung-uk Kim static int 1925926ce35aSJung-uk Kim rtsx_switch_sd_clock(struct rtsx_softc *sc, uint8_t clk, uint8_t n, uint8_t div, uint8_t mcu) 1926926ce35aSJung-uk Kim { 1927577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) { 1928926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_switch_sd_clock() - discovery-mode is %s, ssc_depth: %d\n", 1929926ce35aSJung-uk Kim (sc->rtsx_discovery_mode) ? "true" : "false", sc->rtsx_ssc_depth); 1930926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_switch_sd_clock() - clk: %d, n: %d, div: %d, mcu: %d\n", 1931926ce35aSJung-uk Kim clk, n, div, mcu); 1932926ce35aSJung-uk Kim } 1933926ce35aSJung-uk Kim 1934926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ, RTSX_CLK_LOW_FREQ); 1935926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CLK_DIV, (div << 4) | mcu); 1936926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_SSC_CTL1, RTSX_RSTB); 1937926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SSC_CTL2, RTSX_SSC_DEPTH_MASK, sc->rtsx_ssc_depth); 1938926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_SSC_DIV_N_0, n); 1939926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SSC_CTL1, RTSX_RSTB, RTSX_RSTB); 1940926ce35aSJung-uk Kim if (sc->rtsx_vpclk) { 1941926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_SD_VPCLK0_CTL, RTSX_PHASE_NOT_RESET); 1942926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_VPCLK0_CTL, RTSX_PHASE_NOT_RESET, RTSX_PHASE_NOT_RESET); 1943926ce35aSJung-uk Kim } 1944926ce35aSJung-uk Kim 1945926ce35aSJung-uk Kim /* Wait SSC clock stable. */ 1946926ce35aSJung-uk Kim DELAY(200); 1947926ce35aSJung-uk Kim 1948926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CLK_CTL, RTSX_CLK_LOW_FREQ); 1949926ce35aSJung-uk Kim 1950926ce35aSJung-uk Kim return (0); 1951926ce35aSJung-uk Kim } 1952926ce35aSJung-uk Kim 19538e9740b6SHenri Hennebert #ifndef MMCCAM 1954926ce35aSJung-uk Kim static void 1955926ce35aSJung-uk Kim rtsx_sd_change_tx_phase(struct rtsx_softc *sc, uint8_t sample_point) 1956926ce35aSJung-uk Kim { 1957577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 1958926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_sd_change_tx_phase() - sample_point: %d\n", sample_point); 1959926ce35aSJung-uk Kim 1960926ce35aSJung-uk Kim rtsx_write(sc, RTSX_CLK_CTL, RTSX_CHANGE_CLK, RTSX_CHANGE_CLK); 1961926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_VPCLK0_CTL, RTSX_PHASE_SELECT_MASK, sample_point); 1962926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_VPCLK0_CTL, RTSX_PHASE_NOT_RESET, 0); 1963926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_VPCLK0_CTL, RTSX_PHASE_NOT_RESET, RTSX_PHASE_NOT_RESET); 1964926ce35aSJung-uk Kim rtsx_write(sc, RTSX_CLK_CTL, RTSX_CHANGE_CLK, 0); 1965926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG1, RTSX_SD_ASYNC_FIFO_NOT_RST, 0); 1966926ce35aSJung-uk Kim } 1967926ce35aSJung-uk Kim 1968926ce35aSJung-uk Kim static void 1969926ce35aSJung-uk Kim rtsx_sd_change_rx_phase(struct rtsx_softc *sc, uint8_t sample_point) 1970926ce35aSJung-uk Kim { 1971577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_TUNING) 1972926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_sd_change_rx_phase() - sample_point: %d\n", sample_point); 1973926ce35aSJung-uk Kim 1974926ce35aSJung-uk Kim rtsx_write(sc, RTSX_CLK_CTL, RTSX_CHANGE_CLK, RTSX_CHANGE_CLK); 1975926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_VPCLK1_CTL, RTSX_PHASE_SELECT_MASK, sample_point); 1976926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_VPCLK1_CTL, RTSX_PHASE_NOT_RESET, 0); 1977926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_VPCLK1_CTL, RTSX_PHASE_NOT_RESET, RTSX_PHASE_NOT_RESET); 1978926ce35aSJung-uk Kim rtsx_write(sc, RTSX_CLK_CTL, RTSX_CHANGE_CLK, 0); 1979926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG1, RTSX_SD_ASYNC_FIFO_NOT_RST, 0); 1980926ce35aSJung-uk Kim } 1981926ce35aSJung-uk Kim 1982926ce35aSJung-uk Kim static void 1983926ce35aSJung-uk Kim rtsx_sd_tuning_rx_phase(struct rtsx_softc *sc, uint32_t *phase_map) 1984926ce35aSJung-uk Kim { 1985926ce35aSJung-uk Kim uint32_t raw_phase_map = 0; 1986926ce35aSJung-uk Kim int i; 1987926ce35aSJung-uk Kim int error; 1988926ce35aSJung-uk Kim 1989926ce35aSJung-uk Kim for (i = 0; i < RTSX_RX_PHASE_MAX; i++) { 1990926ce35aSJung-uk Kim error = rtsx_sd_tuning_rx_cmd(sc, (uint8_t)i); 1991926ce35aSJung-uk Kim if (error == 0) 1992926ce35aSJung-uk Kim raw_phase_map |= 1 << i; 1993926ce35aSJung-uk Kim } 1994926ce35aSJung-uk Kim if (phase_map != NULL) 1995926ce35aSJung-uk Kim *phase_map = raw_phase_map; 1996926ce35aSJung-uk Kim } 1997926ce35aSJung-uk Kim 1998926ce35aSJung-uk Kim static int 1999926ce35aSJung-uk Kim rtsx_sd_tuning_rx_cmd(struct rtsx_softc *sc, uint8_t sample_point) 2000926ce35aSJung-uk Kim { 2001926ce35aSJung-uk Kim struct mmc_request req = {}; 2002926ce35aSJung-uk Kim struct mmc_command cmd = {}; 2003926ce35aSJung-uk Kim int error = 0; 2004926ce35aSJung-uk Kim 2005926ce35aSJung-uk Kim cmd.opcode = MMC_SEND_TUNING_BLOCK; 2006926ce35aSJung-uk Kim cmd.arg = 0; 2007926ce35aSJung-uk Kim req.cmd = &cmd; 2008926ce35aSJung-uk Kim 2009926ce35aSJung-uk Kim RTSX_LOCK(sc); 2010926ce35aSJung-uk Kim 2011926ce35aSJung-uk Kim sc->rtsx_req = &req; 2012926ce35aSJung-uk Kim 2013926ce35aSJung-uk Kim rtsx_sd_change_rx_phase(sc, sample_point); 2014926ce35aSJung-uk Kim 2015926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG3, RTSX_SD_RSP_80CLK_TIMEOUT_EN, 2016926ce35aSJung-uk Kim RTSX_SD_RSP_80CLK_TIMEOUT_EN); 2017926ce35aSJung-uk Kim 2018926ce35aSJung-uk Kim rtsx_init_cmd(sc, &cmd); 2019926ce35aSJung-uk Kim rtsx_set_cmd_data_len(sc, 1, 0x40); 2020926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CFG2, 0xff, 2021926ce35aSJung-uk Kim RTSX_SD_CALCULATE_CRC7 | RTSX_SD_CHECK_CRC16 | 2022926ce35aSJung-uk Kim RTSX_SD_NO_WAIT_BUSY_END | RTSX_SD_CHECK_CRC7 | RTSX_SD_RSP_LEN_6); 2023926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER, 2024926ce35aSJung-uk Kim 0xff, RTSX_TM_AUTO_TUNING | RTSX_SD_TRANSFER_START); 2025926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER, 2026926ce35aSJung-uk Kim RTSX_SD_TRANSFER_END, RTSX_SD_TRANSFER_END); 2027926ce35aSJung-uk Kim 2028926ce35aSJung-uk Kim /* Set interrupt post processing */ 2029926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_sd_tuning_rx_cmd_wakeup; 2030926ce35aSJung-uk Kim sc->rtsx_intr_trans_ko = rtsx_sd_tuning_rx_cmd_wakeup; 2031926ce35aSJung-uk Kim 2032926ce35aSJung-uk Kim /* Run the command queue. */ 2033926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2034926ce35aSJung-uk Kim 2035926ce35aSJung-uk Kim error = rtsx_sd_tuning_rx_cmd_wait(sc, &cmd); 2036926ce35aSJung-uk Kim 2037926ce35aSJung-uk Kim if (error) { 2038577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_TUNING) 2039926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_sd_tuning_rx_cmd() - error: %d\n", error); 2040926ce35aSJung-uk Kim rtsx_sd_wait_data_idle(sc); 2041926ce35aSJung-uk Kim rtsx_clear_error(sc); 2042926ce35aSJung-uk Kim } 2043926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG3, RTSX_SD_RSP_80CLK_TIMEOUT_EN, 0); 2044926ce35aSJung-uk Kim 2045926ce35aSJung-uk Kim sc->rtsx_req = NULL; 2046926ce35aSJung-uk Kim 2047926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 2048926ce35aSJung-uk Kim 2049926ce35aSJung-uk Kim return (error); 2050926ce35aSJung-uk Kim } 2051926ce35aSJung-uk Kim 2052926ce35aSJung-uk Kim static int 2053926ce35aSJung-uk Kim rtsx_sd_tuning_rx_cmd_wait(struct rtsx_softc *sc, struct mmc_command *cmd) 2054926ce35aSJung-uk Kim { 2055926ce35aSJung-uk Kim int status; 2056926ce35aSJung-uk Kim int mask = RTSX_TRANS_OK_INT | RTSX_TRANS_FAIL_INT; 2057926ce35aSJung-uk Kim 2058926ce35aSJung-uk Kim status = sc->rtsx_intr_status & mask; 2059926ce35aSJung-uk Kim while (status == 0) { 20609d3bc163SHenri Hennebert if (msleep(&sc->rtsx_intr_status, &sc->rtsx_mtx, 0, "rtsxintr", sc->rtsx_timeout_cmd) == EWOULDBLOCK) { 2061926ce35aSJung-uk Kim cmd->error = MMC_ERR_TIMEOUT; 2062926ce35aSJung-uk Kim return (MMC_ERR_TIMEOUT); 2063926ce35aSJung-uk Kim } 2064926ce35aSJung-uk Kim status = sc->rtsx_intr_status & mask; 2065926ce35aSJung-uk Kim } 2066926ce35aSJung-uk Kim return (cmd->error); 2067926ce35aSJung-uk Kim } 2068926ce35aSJung-uk Kim 2069926ce35aSJung-uk Kim static void 2070926ce35aSJung-uk Kim rtsx_sd_tuning_rx_cmd_wakeup(struct rtsx_softc *sc) 2071926ce35aSJung-uk Kim { 2072926ce35aSJung-uk Kim wakeup(&sc->rtsx_intr_status); 2073926ce35aSJung-uk Kim } 2074926ce35aSJung-uk Kim 2075926ce35aSJung-uk Kim static void 2076926ce35aSJung-uk Kim rtsx_sd_wait_data_idle(struct rtsx_softc *sc) 2077926ce35aSJung-uk Kim { 2078926ce35aSJung-uk Kim int i; 2079926ce35aSJung-uk Kim uint8_t val; 2080926ce35aSJung-uk Kim 2081926ce35aSJung-uk Kim for (i = 0; i < 100; i++) { 2082926ce35aSJung-uk Kim rtsx_read(sc, RTSX_SD_DATA_STATE, &val); 2083926ce35aSJung-uk Kim if (val & RTSX_SD_DATA_IDLE) 2084926ce35aSJung-uk Kim return; 2085926ce35aSJung-uk Kim DELAY(100); 2086926ce35aSJung-uk Kim } 2087926ce35aSJung-uk Kim } 2088926ce35aSJung-uk Kim 2089926ce35aSJung-uk Kim static uint8_t 2090926ce35aSJung-uk Kim rtsx_sd_search_final_rx_phase(struct rtsx_softc *sc, uint32_t phase_map) 2091926ce35aSJung-uk Kim { 2092926ce35aSJung-uk Kim int start = 0, len = 0; 2093926ce35aSJung-uk Kim int start_final = 0, len_final = 0; 2094926ce35aSJung-uk Kim uint8_t final_phase = 0xff; 2095926ce35aSJung-uk Kim 2096926ce35aSJung-uk Kim while (start < RTSX_RX_PHASE_MAX) { 2097926ce35aSJung-uk Kim len = rtsx_sd_get_rx_phase_len(phase_map, start); 2098926ce35aSJung-uk Kim if (len_final < len) { 2099926ce35aSJung-uk Kim start_final = start; 2100926ce35aSJung-uk Kim len_final = len; 2101926ce35aSJung-uk Kim } 2102926ce35aSJung-uk Kim start += len ? len : 1; 2103926ce35aSJung-uk Kim } 2104926ce35aSJung-uk Kim 2105926ce35aSJung-uk Kim final_phase = (start_final + len_final / 2) % RTSX_RX_PHASE_MAX; 2106926ce35aSJung-uk Kim 2107577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 2108926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, 2109926ce35aSJung-uk Kim "rtsx_sd_search_final_rx_phase() - phase_map: %x, start_final: %d, len_final: %d, final_phase: %d\n", 2110926ce35aSJung-uk Kim phase_map, start_final, len_final, final_phase); 2111926ce35aSJung-uk Kim 2112926ce35aSJung-uk Kim return final_phase; 2113926ce35aSJung-uk Kim } 2114926ce35aSJung-uk Kim 2115926ce35aSJung-uk Kim static int 2116926ce35aSJung-uk Kim rtsx_sd_get_rx_phase_len(uint32_t phase_map, int start_bit) 2117926ce35aSJung-uk Kim { 2118926ce35aSJung-uk Kim int i; 2119926ce35aSJung-uk Kim 2120926ce35aSJung-uk Kim for (i = 0; i < RTSX_RX_PHASE_MAX; i++) { 2121926ce35aSJung-uk Kim if ((phase_map & (1 << (start_bit + i) % RTSX_RX_PHASE_MAX)) == 0) 2122926ce35aSJung-uk Kim return i; 2123926ce35aSJung-uk Kim } 2124926ce35aSJung-uk Kim return RTSX_RX_PHASE_MAX; 2125926ce35aSJung-uk Kim } 21268e9740b6SHenri Hennebert #endif /* !MMCCAM */ 2127926ce35aSJung-uk Kim 2128926ce35aSJung-uk Kim #if 0 /* For led */ 2129926ce35aSJung-uk Kim static int 2130926ce35aSJung-uk Kim rtsx_led_enable(struct rtsx_softc *sc) 2131926ce35aSJung-uk Kim { 2132926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 2133926ce35aSJung-uk Kim case RTSX_RTS5209: 2134926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF); 2135926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_AUTO_BLINK, 2136926ce35aSJung-uk Kim RTSX_LED_BLINK_EN | RTSX_LED_BLINK_SPEED); 2137926ce35aSJung-uk Kim break; 2138926ce35aSJung-uk Kim case RTSX_RTL8411B: 2139926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_GPIO_CTL, 0x01); 2140926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_AUTO_BLINK, 2141926ce35aSJung-uk Kim RTSX_LED_BLINK_EN | RTSX_LED_BLINK_SPEED); 2142926ce35aSJung-uk Kim break; 2143926ce35aSJung-uk Kim default: 2144926ce35aSJung-uk Kim RTSX_SET(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON); 2145926ce35aSJung-uk Kim RTSX_SET(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK); 2146926ce35aSJung-uk Kim break; 2147926ce35aSJung-uk Kim } 2148926ce35aSJung-uk Kim 2149926ce35aSJung-uk Kim return (0); 2150926ce35aSJung-uk Kim } 2151926ce35aSJung-uk Kim 2152926ce35aSJung-uk Kim static int 2153926ce35aSJung-uk Kim rtsx_led_disable(struct rtsx_softc *sc) 2154926ce35aSJung-uk Kim { 2155926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 2156926ce35aSJung-uk Kim case RTSX_RTS5209: 2157926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_AUTO_BLINK, RTSX_LED_BLINK_EN); 2158926ce35aSJung-uk Kim RTSX_WRITE(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF); 2159926ce35aSJung-uk Kim break; 2160926ce35aSJung-uk Kim case RTSX_RTL8411B: 2161926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_CARD_AUTO_BLINK, RTSX_LED_BLINK_EN); 2162926ce35aSJung-uk Kim RTSX_SET(sc, RTSX_GPIO_CTL, 0x01); 2163926ce35aSJung-uk Kim break; 2164926ce35aSJung-uk Kim default: 2165926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK); 2166926ce35aSJung-uk Kim RTSX_CLR(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON); 2167926ce35aSJung-uk Kim break; 2168926ce35aSJung-uk Kim } 2169926ce35aSJung-uk Kim 2170926ce35aSJung-uk Kim return (0); 2171926ce35aSJung-uk Kim } 2172926ce35aSJung-uk Kim #endif /* For led */ 2173926ce35aSJung-uk Kim 2174926ce35aSJung-uk Kim static uint8_t 2175926ce35aSJung-uk Kim rtsx_response_type(uint16_t mmc_rsp) 2176926ce35aSJung-uk Kim { 2177926ce35aSJung-uk Kim int i; 2178926ce35aSJung-uk Kim struct rsp_type { 2179926ce35aSJung-uk Kim uint16_t mmc_rsp; 2180926ce35aSJung-uk Kim uint8_t rtsx_rsp; 2181926ce35aSJung-uk Kim } rsp_types[] = { 2182926ce35aSJung-uk Kim { MMC_RSP_NONE, RTSX_SD_RSP_TYPE_R0 }, 2183926ce35aSJung-uk Kim { MMC_RSP_R1, RTSX_SD_RSP_TYPE_R1 }, 2184926ce35aSJung-uk Kim { MMC_RSP_R1B, RTSX_SD_RSP_TYPE_R1B }, 2185926ce35aSJung-uk Kim { MMC_RSP_R2, RTSX_SD_RSP_TYPE_R2 }, 2186926ce35aSJung-uk Kim { MMC_RSP_R3, RTSX_SD_RSP_TYPE_R3 }, 2187926ce35aSJung-uk Kim { MMC_RSP_R4, RTSX_SD_RSP_TYPE_R4 }, 2188926ce35aSJung-uk Kim { MMC_RSP_R5, RTSX_SD_RSP_TYPE_R5 }, 2189926ce35aSJung-uk Kim { MMC_RSP_R6, RTSX_SD_RSP_TYPE_R6 }, 2190926ce35aSJung-uk Kim { MMC_RSP_R7, RTSX_SD_RSP_TYPE_R7 } 2191926ce35aSJung-uk Kim }; 2192926ce35aSJung-uk Kim 2193926ce35aSJung-uk Kim for (i = 0; i < nitems(rsp_types); i++) { 2194926ce35aSJung-uk Kim if (mmc_rsp == rsp_types[i].mmc_rsp) 2195926ce35aSJung-uk Kim return (rsp_types[i].rtsx_rsp); 2196926ce35aSJung-uk Kim } 2197926ce35aSJung-uk Kim 2198926ce35aSJung-uk Kim return (0); 2199926ce35aSJung-uk Kim } 2200926ce35aSJung-uk Kim 2201926ce35aSJung-uk Kim /* 2202926ce35aSJung-uk Kim * Init command buffer with SD command index and argument. 2203926ce35aSJung-uk Kim */ 2204926ce35aSJung-uk Kim static void 2205926ce35aSJung-uk Kim rtsx_init_cmd(struct rtsx_softc *sc, struct mmc_command *cmd) 2206926ce35aSJung-uk Kim { 2207926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2208926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CMD0, 2209926ce35aSJung-uk Kim 0xff, RTSX_SD_CMD_START | cmd->opcode); 2210926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CMD1, 2211926ce35aSJung-uk Kim 0xff, cmd->arg >> 24); 2212926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CMD2, 2213926ce35aSJung-uk Kim 0xff, cmd->arg >> 16); 2214926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CMD3, 2215926ce35aSJung-uk Kim 0xff, cmd->arg >> 8); 2216926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CMD4, 2217926ce35aSJung-uk Kim 0xff, cmd->arg); 2218926ce35aSJung-uk Kim } 2219926ce35aSJung-uk Kim 2220926ce35aSJung-uk Kim /* 2221926ce35aSJung-uk Kim * Append a properly encoded host command to the host command buffer. 2222926ce35aSJung-uk Kim */ 2223926ce35aSJung-uk Kim static void 2224926ce35aSJung-uk Kim rtsx_push_cmd(struct rtsx_softc *sc, uint8_t cmd, uint16_t reg, 2225926ce35aSJung-uk Kim uint8_t mask, uint8_t data) 2226926ce35aSJung-uk Kim { 2227926ce35aSJung-uk Kim KASSERT(sc->rtsx_cmd_index < RTSX_HOSTCMD_MAX, 2228926ce35aSJung-uk Kim ("rtsx: Too many host commands (%d)\n", sc->rtsx_cmd_index)); 2229926ce35aSJung-uk Kim 2230926ce35aSJung-uk Kim uint32_t *cmd_buffer = (uint32_t *)(sc->rtsx_cmd_dmamem); 2231926ce35aSJung-uk Kim cmd_buffer[sc->rtsx_cmd_index++] = 2232926ce35aSJung-uk Kim htole32((uint32_t)(cmd & 0x3) << 30) | 2233926ce35aSJung-uk Kim ((uint32_t)(reg & 0x3fff) << 16) | 2234926ce35aSJung-uk Kim ((uint32_t)(mask) << 8) | 2235926ce35aSJung-uk Kim ((uint32_t)data); 2236926ce35aSJung-uk Kim } 2237926ce35aSJung-uk Kim 2238926ce35aSJung-uk Kim /* 2239926ce35aSJung-uk Kim * Queue commands to configure data transfer size. 2240926ce35aSJung-uk Kim */ 2241926ce35aSJung-uk Kim static void 2242926ce35aSJung-uk Kim rtsx_set_cmd_data_len(struct rtsx_softc *sc, uint16_t block_cnt, uint16_t byte_cnt) 2243926ce35aSJung-uk Kim { 2244926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_BLOCK_CNT_L, 2245926ce35aSJung-uk Kim 0xff, block_cnt & 0xff); 2246926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_BLOCK_CNT_H, 2247926ce35aSJung-uk Kim 0xff, block_cnt >> 8); 2248926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_BYTE_CNT_L, 2249926ce35aSJung-uk Kim 0xff, byte_cnt & 0xff); 2250926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_BYTE_CNT_H, 2251926ce35aSJung-uk Kim 0xff, byte_cnt >> 8); 2252926ce35aSJung-uk Kim } 2253926ce35aSJung-uk Kim 2254926ce35aSJung-uk Kim /* 2255926ce35aSJung-uk Kim * Run the command queue. 2256926ce35aSJung-uk Kim */ 2257926ce35aSJung-uk Kim static void 2258926ce35aSJung-uk Kim rtsx_send_cmd(struct rtsx_softc *sc) 2259926ce35aSJung-uk Kim { 2260577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2261926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_send_cmd()\n"); 2262926ce35aSJung-uk Kim 2263926ce35aSJung-uk Kim sc->rtsx_intr_status = 0; 2264926ce35aSJung-uk Kim 2265926ce35aSJung-uk Kim /* Sync command DMA buffer. */ 2266926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_PREREAD); 2267926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_PREWRITE); 2268926ce35aSJung-uk Kim 2269926ce35aSJung-uk Kim /* Tell the chip where the command buffer is and run the commands. */ 2270926ce35aSJung-uk Kim WRITE4(sc, RTSX_HCBAR, (uint32_t)sc->rtsx_cmd_buffer); 2271926ce35aSJung-uk Kim WRITE4(sc, RTSX_HCBCTLR, 2272926ce35aSJung-uk Kim ((sc->rtsx_cmd_index * 4) & 0x00ffffff) | RTSX_START_CMD | RTSX_HW_AUTO_RSP); 2273926ce35aSJung-uk Kim } 2274926ce35aSJung-uk Kim 2275926ce35aSJung-uk Kim /* 2276926ce35aSJung-uk Kim * Stop previous command. 2277926ce35aSJung-uk Kim */ 2278926ce35aSJung-uk Kim static void 2279926ce35aSJung-uk Kim rtsx_stop_cmd(struct rtsx_softc *sc) 2280926ce35aSJung-uk Kim { 2281926ce35aSJung-uk Kim /* Stop command transfer. */ 2282926ce35aSJung-uk Kim WRITE4(sc, RTSX_HCBCTLR, RTSX_STOP_CMD); 2283926ce35aSJung-uk Kim 2284926ce35aSJung-uk Kim /* Stop DMA transfer. */ 2285926ce35aSJung-uk Kim WRITE4(sc, RTSX_HDBCTLR, RTSX_STOP_DMA); 2286926ce35aSJung-uk Kim 2287577130e5SHenri Hennebert switch (sc->rtsx_device_id) { 2288577130e5SHenri Hennebert case RTSX_RTS5260: 2289577130e5SHenri Hennebert rtsx_write(sc, RTSX_RTS5260_DMA_RST_CTL_0, 2290577130e5SHenri Hennebert RTSX_RTS5260_DMA_RST | RTSX_RTS5260_ADMA3_RST, 2291577130e5SHenri Hennebert RTSX_RTS5260_DMA_RST | RTSX_RTS5260_ADMA3_RST); 2292577130e5SHenri Hennebert rtsx_write(sc, RTSX_RBCTL, RTSX_RB_FLUSH, RTSX_RB_FLUSH); 2293577130e5SHenri Hennebert break; 22948290c144SHenri Hennebert default: 2295926ce35aSJung-uk Kim rtsx_write(sc, RTSX_DMACTL, RTSX_DMA_RST, RTSX_DMA_RST); 2296926ce35aSJung-uk Kim 2297926ce35aSJung-uk Kim rtsx_write(sc, RTSX_RBCTL, RTSX_RB_FLUSH, RTSX_RB_FLUSH); 22988290c144SHenri Hennebert break; 22998290c144SHenri Hennebert } 2300926ce35aSJung-uk Kim } 2301926ce35aSJung-uk Kim 2302926ce35aSJung-uk Kim /* 2303926ce35aSJung-uk Kim * Clear error. 2304926ce35aSJung-uk Kim */ 2305926ce35aSJung-uk Kim static void 2306926ce35aSJung-uk Kim rtsx_clear_error(struct rtsx_softc *sc) 2307926ce35aSJung-uk Kim { 2308926ce35aSJung-uk Kim /* Clear error. */ 2309926ce35aSJung-uk Kim rtsx_write(sc, RTSX_CARD_STOP, RTSX_SD_STOP | RTSX_SD_CLR_ERR, 2310926ce35aSJung-uk Kim RTSX_SD_STOP | RTSX_SD_CLR_ERR); 2311926ce35aSJung-uk Kim } 2312926ce35aSJung-uk Kim 2313926ce35aSJung-uk Kim /* 2314926ce35aSJung-uk Kim * Signal end of request to mmc/mmcsd. 2315926ce35aSJung-uk Kim */ 2316926ce35aSJung-uk Kim static void 2317926ce35aSJung-uk Kim rtsx_req_done(struct rtsx_softc *sc) 2318926ce35aSJung-uk Kim { 2319926ce35aSJung-uk Kim #ifdef MMCCAM 2320926ce35aSJung-uk Kim union ccb *ccb; 2321926ce35aSJung-uk Kim #endif /* MMCCAM */ 2322926ce35aSJung-uk Kim struct mmc_request *req; 2323926ce35aSJung-uk Kim 2324926ce35aSJung-uk Kim req = sc->rtsx_req; 2325926ce35aSJung-uk Kim if (req->cmd->error == MMC_ERR_NONE) { 2326926ce35aSJung-uk Kim if (req->cmd->opcode == MMC_READ_SINGLE_BLOCK || 2327926ce35aSJung-uk Kim req->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) 2328926ce35aSJung-uk Kim sc->rtsx_read_count++; 2329926ce35aSJung-uk Kim else if (req->cmd->opcode == MMC_WRITE_BLOCK || 2330926ce35aSJung-uk Kim req->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) 2331926ce35aSJung-uk Kim sc->rtsx_write_count++; 2332926ce35aSJung-uk Kim } else { 2333926ce35aSJung-uk Kim rtsx_clear_error(sc); 2334926ce35aSJung-uk Kim } 2335926ce35aSJung-uk Kim callout_stop(&sc->rtsx_timeout_callout); 2336926ce35aSJung-uk Kim sc->rtsx_req = NULL; 2337926ce35aSJung-uk Kim #ifdef MMCCAM 2338926ce35aSJung-uk Kim ccb = sc->rtsx_ccb; 2339926ce35aSJung-uk Kim sc->rtsx_ccb = NULL; 2340926ce35aSJung-uk Kim ccb->ccb_h.status = (req->cmd->error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR); 2341926ce35aSJung-uk Kim xpt_done(ccb); 23429d3bc163SHenri Hennebert #else /* !MMCCAM */ 2343926ce35aSJung-uk Kim req->done(req); 2344926ce35aSJung-uk Kim #endif /* MMCCAM */ 2345926ce35aSJung-uk Kim } 2346926ce35aSJung-uk Kim 2347926ce35aSJung-uk Kim /* 2348926ce35aSJung-uk Kim * Send request. 2349926ce35aSJung-uk Kim */ 2350926ce35aSJung-uk Kim static int 2351926ce35aSJung-uk Kim rtsx_send_req(struct rtsx_softc *sc, struct mmc_command *cmd) 2352926ce35aSJung-uk Kim { 2353926ce35aSJung-uk Kim uint8_t rsp_type; 2354926ce35aSJung-uk Kim uint16_t reg; 2355926ce35aSJung-uk Kim 2356577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2357926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_send_req() - CMD%d\n", cmd->opcode); 2358926ce35aSJung-uk Kim 2359926ce35aSJung-uk Kim /* Convert response type. */ 2360926ce35aSJung-uk Kim rsp_type = rtsx_response_type(cmd->flags & MMC_RSP_MASK); 2361926ce35aSJung-uk Kim if (rsp_type == 0) { 2362926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Unknown rsp_type: 0x%lx\n", (cmd->flags & MMC_RSP_MASK)); 2363926ce35aSJung-uk Kim cmd->error = MMC_ERR_INVALID; 2364926ce35aSJung-uk Kim return (MMC_ERR_INVALID); 2365926ce35aSJung-uk Kim } 2366926ce35aSJung-uk Kim 2367926ce35aSJung-uk Kim rtsx_init_cmd(sc, cmd); 2368926ce35aSJung-uk Kim 2369926ce35aSJung-uk Kim /* Queue command to set response type. */ 2370926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CFG2, 0xff, rsp_type); 2371926ce35aSJung-uk Kim 2372926ce35aSJung-uk Kim /* Use the ping-pong buffer (cmd buffer) for commands which do not transfer data. */ 2373926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_CARD_DATA_SOURCE, 2374926ce35aSJung-uk Kim 0x01, RTSX_PINGPONG_BUFFER); 2375926ce35aSJung-uk Kim 2376926ce35aSJung-uk Kim /* Queue commands to perform SD transfer. */ 2377926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER, 2378926ce35aSJung-uk Kim 0xff, RTSX_TM_CMD_RSP | RTSX_SD_TRANSFER_START); 2379926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER, 2380926ce35aSJung-uk Kim RTSX_SD_TRANSFER_END|RTSX_SD_STAT_IDLE, 2381926ce35aSJung-uk Kim RTSX_SD_TRANSFER_END|RTSX_SD_STAT_IDLE); 2382926ce35aSJung-uk Kim 2383926ce35aSJung-uk Kim /* If needed queue commands to read back card status response. */ 2384926ce35aSJung-uk Kim if (rsp_type == RTSX_SD_RSP_TYPE_R2) { 2385926ce35aSJung-uk Kim /* Read data from ping-pong buffer. */ 2386926ce35aSJung-uk Kim for (reg = RTSX_PPBUF_BASE2; reg < RTSX_PPBUF_BASE2 + 16; reg++) 2387926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_READ_REG_CMD, reg, 0, 0); 2388926ce35aSJung-uk Kim } else if (rsp_type != RTSX_SD_RSP_TYPE_R0) { 2389926ce35aSJung-uk Kim /* Read data from SD_CMDx registers. */ 2390926ce35aSJung-uk Kim for (reg = RTSX_SD_CMD0; reg <= RTSX_SD_CMD4; reg++) 2391926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_READ_REG_CMD, reg, 0, 0); 2392926ce35aSJung-uk Kim } 2393926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_READ_REG_CMD, RTSX_SD_STAT1, 0, 0); 2394926ce35aSJung-uk Kim 2395926ce35aSJung-uk Kim /* Set transfer OK function. */ 2396926ce35aSJung-uk Kim if (sc->rtsx_intr_trans_ok == NULL) 2397926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_ret_resp; 2398926ce35aSJung-uk Kim 2399926ce35aSJung-uk Kim /* Run the command queue. */ 2400926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2401926ce35aSJung-uk Kim 2402926ce35aSJung-uk Kim return (0); 2403926ce35aSJung-uk Kim } 2404926ce35aSJung-uk Kim 2405926ce35aSJung-uk Kim /* 2406926ce35aSJung-uk Kim * Return response of previous command (case cmd->data == NULL) and complete resquest. 2407926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2408926ce35aSJung-uk Kim */ 2409926ce35aSJung-uk Kim static void 2410926ce35aSJung-uk Kim rtsx_ret_resp(struct rtsx_softc *sc) 2411926ce35aSJung-uk Kim { 2412926ce35aSJung-uk Kim struct mmc_command *cmd; 2413926ce35aSJung-uk Kim 2414926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2415926ce35aSJung-uk Kim rtsx_set_resp(sc, cmd); 2416926ce35aSJung-uk Kim rtsx_req_done(sc); 2417926ce35aSJung-uk Kim } 2418926ce35aSJung-uk Kim 2419926ce35aSJung-uk Kim /* 2420926ce35aSJung-uk Kim * Set response of previous command. 2421926ce35aSJung-uk Kim */ 2422926ce35aSJung-uk Kim static void 2423926ce35aSJung-uk Kim rtsx_set_resp(struct rtsx_softc *sc, struct mmc_command *cmd) 2424926ce35aSJung-uk Kim { 2425926ce35aSJung-uk Kim uint8_t rsp_type; 2426926ce35aSJung-uk Kim 2427926ce35aSJung-uk Kim rsp_type = rtsx_response_type(cmd->flags & MMC_RSP_MASK); 2428926ce35aSJung-uk Kim 2429926ce35aSJung-uk Kim /* Sync command DMA buffer. */ 2430926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_POSTREAD); 2431926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_POSTWRITE); 2432926ce35aSJung-uk Kim 2433926ce35aSJung-uk Kim /* Copy card response into mmc response buffer. */ 2434926ce35aSJung-uk Kim if (ISSET(cmd->flags, MMC_RSP_PRESENT)) { 2435926ce35aSJung-uk Kim uint32_t *cmd_buffer = (uint32_t *)(sc->rtsx_cmd_dmamem); 2436926ce35aSJung-uk Kim 2437577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) { 2438926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "cmd_buffer: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 2439926ce35aSJung-uk Kim cmd_buffer[0], cmd_buffer[1], cmd_buffer[2], cmd_buffer[3], cmd_buffer[4]); 2440926ce35aSJung-uk Kim } 2441926ce35aSJung-uk Kim 2442926ce35aSJung-uk Kim if (rsp_type == RTSX_SD_RSP_TYPE_R2) { 2443926ce35aSJung-uk Kim /* First byte is CHECK_REG_CMD return value, skip it. */ 2444926ce35aSJung-uk Kim unsigned char *ptr = (unsigned char *)cmd_buffer + 1; 2445926ce35aSJung-uk Kim int i; 2446926ce35aSJung-uk Kim 2447926ce35aSJung-uk Kim /* 2448926ce35aSJung-uk Kim * The controller offloads the last byte {CRC-7, end bit 1} 2449926ce35aSJung-uk Kim * of response type R2. Assign dummy CRC, 0, and end bit to this 2450926ce35aSJung-uk Kim * byte (ptr[16], goes into the LSB of resp[3] later). 2451926ce35aSJung-uk Kim */ 2452926ce35aSJung-uk Kim ptr[16] = 0x01; 2453926ce35aSJung-uk Kim /* The second byte is the status of response, skip it. */ 2454926ce35aSJung-uk Kim for (i = 0; i < 4; i++) 2455926ce35aSJung-uk Kim cmd->resp[i] = be32dec(ptr + 1 + i * 4); 2456926ce35aSJung-uk Kim } else { 2457926ce35aSJung-uk Kim /* 2458926ce35aSJung-uk Kim * First byte is CHECK_REG_CMD return value, second 2459926ce35aSJung-uk Kim * one is the command op code -- we skip those. 2460926ce35aSJung-uk Kim */ 2461926ce35aSJung-uk Kim cmd->resp[0] = 2462926ce35aSJung-uk Kim ((be32toh(cmd_buffer[0]) & 0x0000ffff) << 16) | 2463926ce35aSJung-uk Kim ((be32toh(cmd_buffer[1]) & 0xffff0000) >> 16); 2464926ce35aSJung-uk Kim } 2465926ce35aSJung-uk Kim 2466577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2467926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "cmd->resp: 0x%08x 0x%08x 0x%08x 0x%08x\n", 2468926ce35aSJung-uk Kim cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); 2469926ce35aSJung-uk Kim } 2470926ce35aSJung-uk Kim } 2471926ce35aSJung-uk Kim 2472926ce35aSJung-uk Kim /* 2473926ce35aSJung-uk Kim * Use the ping-pong buffer (cmd buffer) for transfer <= 512 bytes. 2474926ce35aSJung-uk Kim */ 2475926ce35aSJung-uk Kim static int 2476926ce35aSJung-uk Kim rtsx_xfer_short(struct rtsx_softc *sc, struct mmc_command *cmd) 2477926ce35aSJung-uk Kim { 2478926ce35aSJung-uk Kim int read; 2479926ce35aSJung-uk Kim 2480926ce35aSJung-uk Kim if (cmd->data == NULL || cmd->data->len == 0) { 2481926ce35aSJung-uk Kim cmd->error = MMC_ERR_INVALID; 2482926ce35aSJung-uk Kim return (MMC_ERR_INVALID); 2483926ce35aSJung-uk Kim } 2484926ce35aSJung-uk Kim cmd->data->xfer_len = (cmd->data->len > RTSX_MAX_DATA_BLKLEN) ? 2485926ce35aSJung-uk Kim RTSX_MAX_DATA_BLKLEN : cmd->data->len; 2486926ce35aSJung-uk Kim 2487926ce35aSJung-uk Kim read = ISSET(cmd->data->flags, MMC_DATA_READ); 2488926ce35aSJung-uk Kim 2489577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2490926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_xfer_short() - %s xfer: %ld bytes with block size %ld\n", 2491926ce35aSJung-uk Kim read ? "Read" : "Write", 2492926ce35aSJung-uk Kim (unsigned long)cmd->data->len, (unsigned long)cmd->data->xfer_len); 2493926ce35aSJung-uk Kim 2494926ce35aSJung-uk Kim if (cmd->data->len > 512) { 2495926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_xfer_short() - length too large: %ld > 512\n", 2496926ce35aSJung-uk Kim (unsigned long)cmd->data->len); 2497926ce35aSJung-uk Kim cmd->error = MMC_ERR_INVALID; 2498926ce35aSJung-uk Kim return (MMC_ERR_INVALID); 2499926ce35aSJung-uk Kim } 2500926ce35aSJung-uk Kim 2501926ce35aSJung-uk Kim if (read) { 2502926ce35aSJung-uk Kim if (sc->rtsx_discovery_mode) 2503926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_MASK, RTSX_CLK_DIVIDE_0); 2504926ce35aSJung-uk Kim 2505926ce35aSJung-uk Kim rtsx_init_cmd(sc, cmd); 2506926ce35aSJung-uk Kim 2507926ce35aSJung-uk Kim /* Queue commands to configure data transfer size. */ 2508926ce35aSJung-uk Kim rtsx_set_cmd_data_len(sc, cmd->data->len / cmd->data->xfer_len, cmd->data->xfer_len); 2509926ce35aSJung-uk Kim 2510926ce35aSJung-uk Kim /* From Linux: rtsx_pci_sdmmc.c sd_read_data(). */ 2511926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CFG2, 0xff, 2512926ce35aSJung-uk Kim RTSX_SD_CALCULATE_CRC7 | RTSX_SD_CHECK_CRC16 | 2513926ce35aSJung-uk Kim RTSX_SD_NO_WAIT_BUSY_END | RTSX_SD_CHECK_CRC7 | RTSX_SD_RSP_LEN_6); 2514926ce35aSJung-uk Kim 2515926ce35aSJung-uk Kim /* Use the ping-pong buffer (cmd buffer). */ 2516926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_CARD_DATA_SOURCE, 2517926ce35aSJung-uk Kim 0x01, RTSX_PINGPONG_BUFFER); 2518926ce35aSJung-uk Kim 2519926ce35aSJung-uk Kim /* Queue commands to perform SD transfer. */ 2520926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER, 2521926ce35aSJung-uk Kim 0xff, RTSX_TM_NORMAL_READ | RTSX_SD_TRANSFER_START); 2522926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER, 2523926ce35aSJung-uk Kim RTSX_SD_TRANSFER_END, RTSX_SD_TRANSFER_END); 2524926ce35aSJung-uk Kim 2525926ce35aSJung-uk Kim /* Set transfer OK function. */ 2526926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_ask_ppbuf_part1; 2527926ce35aSJung-uk Kim 2528926ce35aSJung-uk Kim /* Run the command queue. */ 2529926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2530926ce35aSJung-uk Kim } else { 2531926ce35aSJung-uk Kim /* Set transfer OK function. */ 2532926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_put_ppbuf_part1; 2533926ce35aSJung-uk Kim 2534926ce35aSJung-uk Kim /* Run the command queue. */ 2535926ce35aSJung-uk Kim rtsx_send_req(sc, cmd); 2536926ce35aSJung-uk Kim } 2537926ce35aSJung-uk Kim 2538926ce35aSJung-uk Kim return (0); 2539926ce35aSJung-uk Kim } 2540926ce35aSJung-uk Kim 2541926ce35aSJung-uk Kim /* 2542926ce35aSJung-uk Kim * Use the ping-pong buffer (cmd buffer) for the transfer - first part <= 256 bytes. 2543926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2544926ce35aSJung-uk Kim */ 2545926ce35aSJung-uk Kim static void 2546926ce35aSJung-uk Kim rtsx_ask_ppbuf_part1(struct rtsx_softc *sc) 2547926ce35aSJung-uk Kim { 2548926ce35aSJung-uk Kim struct mmc_command *cmd; 2549926ce35aSJung-uk Kim uint16_t reg = RTSX_PPBUF_BASE2; 2550926ce35aSJung-uk Kim int len; 2551926ce35aSJung-uk Kim int i; 2552926ce35aSJung-uk Kim 2553926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2554926ce35aSJung-uk Kim len = (cmd->data->len > RTSX_HOSTCMD_MAX) ? RTSX_HOSTCMD_MAX : cmd->data->len; 2555926ce35aSJung-uk Kim 2556926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2557926ce35aSJung-uk Kim for (i = 0; i < len; i++) { 2558926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_READ_REG_CMD, reg++, 0, 0); 2559926ce35aSJung-uk Kim } 2560926ce35aSJung-uk Kim 2561926ce35aSJung-uk Kim /* Set transfer OK function. */ 2562926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_get_ppbuf_part1; 2563926ce35aSJung-uk Kim 2564926ce35aSJung-uk Kim /* Run the command queue. */ 2565926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2566926ce35aSJung-uk Kim } 2567926ce35aSJung-uk Kim 2568926ce35aSJung-uk Kim /* 2569926ce35aSJung-uk Kim * Get the data from the ping-pong buffer (cmd buffer) - first part <= 256 bytes. 2570926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2571926ce35aSJung-uk Kim */ 2572926ce35aSJung-uk Kim static void 2573926ce35aSJung-uk Kim rtsx_get_ppbuf_part1(struct rtsx_softc *sc) 2574926ce35aSJung-uk Kim { 2575926ce35aSJung-uk Kim struct mmc_command *cmd; 2576926ce35aSJung-uk Kim uint8_t *ptr; 2577926ce35aSJung-uk Kim int len; 2578926ce35aSJung-uk Kim 2579926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2580926ce35aSJung-uk Kim ptr = cmd->data->data; 2581926ce35aSJung-uk Kim len = (cmd->data->len > RTSX_HOSTCMD_MAX) ? RTSX_HOSTCMD_MAX : cmd->data->len; 2582926ce35aSJung-uk Kim 2583926ce35aSJung-uk Kim /* Sync command DMA buffer. */ 2584926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_POSTREAD); 2585926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_POSTWRITE); 2586926ce35aSJung-uk Kim 2587926ce35aSJung-uk Kim memcpy(ptr, sc->rtsx_cmd_dmamem, len); 2588926ce35aSJung-uk Kim 2589926ce35aSJung-uk Kim len = (cmd->data->len > RTSX_HOSTCMD_MAX) ? cmd->data->len - RTSX_HOSTCMD_MAX : 0; 2590926ce35aSJung-uk Kim 2591926ce35aSJung-uk Kim /* Use the ping-pong buffer (cmd buffer) for the transfer - second part > 256 bytes. */ 2592926ce35aSJung-uk Kim if (len > 0) { 2593926ce35aSJung-uk Kim uint16_t reg = RTSX_PPBUF_BASE2 + RTSX_HOSTCMD_MAX; 2594926ce35aSJung-uk Kim int i; 2595926ce35aSJung-uk Kim 2596926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2597926ce35aSJung-uk Kim for (i = 0; i < len; i++) { 2598926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_READ_REG_CMD, reg++, 0, 0); 2599926ce35aSJung-uk Kim } 2600926ce35aSJung-uk Kim 2601926ce35aSJung-uk Kim /* Set transfer OK function. */ 2602926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_get_ppbuf_part2; 2603926ce35aSJung-uk Kim 2604926ce35aSJung-uk Kim /* Run the command queue. */ 2605926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2606926ce35aSJung-uk Kim } else { 2607577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD && cmd->opcode == ACMD_SEND_SCR) { 2608926ce35aSJung-uk Kim uint8_t *ptr = cmd->data->data; 2609926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "SCR: 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", 2610926ce35aSJung-uk Kim ptr[0], ptr[1], ptr[2], ptr[3], 2611926ce35aSJung-uk Kim ptr[4], ptr[5], ptr[6], ptr[7]); 2612926ce35aSJung-uk Kim } 2613926ce35aSJung-uk Kim 2614926ce35aSJung-uk Kim if (sc->rtsx_discovery_mode) 2615926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_MASK, RTSX_CLK_DIVIDE_128); 2616926ce35aSJung-uk Kim 2617926ce35aSJung-uk Kim rtsx_req_done(sc); 2618926ce35aSJung-uk Kim } 2619926ce35aSJung-uk Kim } 2620926ce35aSJung-uk Kim 2621926ce35aSJung-uk Kim /* 2622926ce35aSJung-uk Kim * Get the data from the ping-pong buffer (cmd buffer) - second part > 256 bytes. 2623926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2624926ce35aSJung-uk Kim */ 2625926ce35aSJung-uk Kim static void 2626926ce35aSJung-uk Kim rtsx_get_ppbuf_part2(struct rtsx_softc *sc) 2627926ce35aSJung-uk Kim { 2628926ce35aSJung-uk Kim struct mmc_command *cmd; 2629926ce35aSJung-uk Kim uint8_t *ptr; 2630926ce35aSJung-uk Kim int len; 2631926ce35aSJung-uk Kim 2632926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2633926ce35aSJung-uk Kim ptr = cmd->data->data; 2634926ce35aSJung-uk Kim ptr += RTSX_HOSTCMD_MAX; 2635926ce35aSJung-uk Kim len = cmd->data->len - RTSX_HOSTCMD_MAX; 2636926ce35aSJung-uk Kim 2637926ce35aSJung-uk Kim /* Sync command DMA buffer. */ 2638926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_POSTREAD); 2639926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_cmd_dma_tag, sc->rtsx_cmd_dmamap, BUS_DMASYNC_POSTWRITE); 2640926ce35aSJung-uk Kim 2641926ce35aSJung-uk Kim memcpy(ptr, sc->rtsx_cmd_dmamem, len); 2642926ce35aSJung-uk Kim 2643926ce35aSJung-uk Kim if (sc->rtsx_discovery_mode) 2644926ce35aSJung-uk Kim rtsx_write(sc, RTSX_SD_CFG1, RTSX_CLK_DIVIDE_MASK, RTSX_CLK_DIVIDE_128); 2645926ce35aSJung-uk Kim 2646926ce35aSJung-uk Kim rtsx_req_done(sc); 2647926ce35aSJung-uk Kim } 2648926ce35aSJung-uk Kim 2649926ce35aSJung-uk Kim /* 2650926ce35aSJung-uk Kim * Use the ping-pong buffer (cmd buffer) for transfer - first part <= 256 bytes. 2651926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2652926ce35aSJung-uk Kim */ 2653926ce35aSJung-uk Kim static void 2654926ce35aSJung-uk Kim rtsx_put_ppbuf_part1(struct rtsx_softc *sc) 2655926ce35aSJung-uk Kim { 2656926ce35aSJung-uk Kim struct mmc_command *cmd; 2657926ce35aSJung-uk Kim uint16_t reg = RTSX_PPBUF_BASE2; 2658926ce35aSJung-uk Kim uint8_t *ptr; 2659926ce35aSJung-uk Kim int len; 2660926ce35aSJung-uk Kim int i; 2661926ce35aSJung-uk Kim 2662926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2663926ce35aSJung-uk Kim ptr = cmd->data->data; 2664926ce35aSJung-uk Kim len = (cmd->data->len > RTSX_HOSTCMD_MAX) ? RTSX_HOSTCMD_MAX : cmd->data->len; 2665926ce35aSJung-uk Kim 2666926ce35aSJung-uk Kim rtsx_set_resp(sc, cmd); 2667926ce35aSJung-uk Kim 2668926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2669926ce35aSJung-uk Kim for (i = 0; i < len; i++) { 2670926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, reg++, 0xff, *ptr); 2671926ce35aSJung-uk Kim ptr++; 2672926ce35aSJung-uk Kim } 2673926ce35aSJung-uk Kim 2674926ce35aSJung-uk Kim /* Set transfer OK function. */ 2675926ce35aSJung-uk Kim if (cmd->data->len > RTSX_HOSTCMD_MAX) 2676926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_put_ppbuf_part2; 2677926ce35aSJung-uk Kim else 2678926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_write_ppbuf; 2679926ce35aSJung-uk Kim 2680926ce35aSJung-uk Kim /* Run the command queue. */ 2681926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2682926ce35aSJung-uk Kim } 2683926ce35aSJung-uk Kim 2684926ce35aSJung-uk Kim /* 2685926ce35aSJung-uk Kim * Use the ping-pong buffer (cmd buffer) for transfer - second part > 256 bytes. 2686926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2687926ce35aSJung-uk Kim */ 2688926ce35aSJung-uk Kim static void 2689926ce35aSJung-uk Kim rtsx_put_ppbuf_part2(struct rtsx_softc *sc) 2690926ce35aSJung-uk Kim { 2691926ce35aSJung-uk Kim struct mmc_command *cmd; 2692926ce35aSJung-uk Kim uint16_t reg = RTSX_PPBUF_BASE2 + RTSX_HOSTCMD_MAX; 2693926ce35aSJung-uk Kim uint8_t *ptr; 2694926ce35aSJung-uk Kim int len; 2695926ce35aSJung-uk Kim int i; 2696926ce35aSJung-uk Kim 2697926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2698926ce35aSJung-uk Kim ptr = cmd->data->data; 2699926ce35aSJung-uk Kim ptr += RTSX_HOSTCMD_MAX; 2700926ce35aSJung-uk Kim len = cmd->data->len - RTSX_HOSTCMD_MAX; 2701926ce35aSJung-uk Kim 2702926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2703926ce35aSJung-uk Kim for (i = 0; i < len; i++) { 2704926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, reg++, 0xff, *ptr); 2705926ce35aSJung-uk Kim ptr++; 2706926ce35aSJung-uk Kim } 2707926ce35aSJung-uk Kim 2708926ce35aSJung-uk Kim /* Set transfer OK function. */ 2709926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_write_ppbuf; 2710926ce35aSJung-uk Kim 2711926ce35aSJung-uk Kim /* Run the command queue. */ 2712926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2713926ce35aSJung-uk Kim } 2714926ce35aSJung-uk Kim 2715926ce35aSJung-uk Kim /* 2716926ce35aSJung-uk Kim * Write the data previously given via the ping-pong buffer on the card. 2717926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2718926ce35aSJung-uk Kim */ 2719926ce35aSJung-uk Kim static void 2720926ce35aSJung-uk Kim rtsx_write_ppbuf(struct rtsx_softc *sc) 2721926ce35aSJung-uk Kim { 2722926ce35aSJung-uk Kim struct mmc_command *cmd; 2723926ce35aSJung-uk Kim 2724926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2725926ce35aSJung-uk Kim 2726926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2727926ce35aSJung-uk Kim 2728926ce35aSJung-uk Kim /* Queue commands to configure data transfer size. */ 2729926ce35aSJung-uk Kim rtsx_set_cmd_data_len(sc, cmd->data->len / cmd->data->xfer_len, cmd->data->xfer_len); 2730926ce35aSJung-uk Kim 2731926ce35aSJung-uk Kim /* From Linux: rtsx_pci_sdmmc.c sd_write_data(). */ 2732926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CFG2, 0xff, 2733926ce35aSJung-uk Kim RTSX_SD_CALCULATE_CRC7 | RTSX_SD_CHECK_CRC16 | 2734926ce35aSJung-uk Kim RTSX_SD_NO_WAIT_BUSY_END | RTSX_SD_CHECK_CRC7 | RTSX_SD_RSP_LEN_0); 2735926ce35aSJung-uk Kim 2736926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER, 0xff, 2737926ce35aSJung-uk Kim RTSX_TM_AUTO_WRITE3 | RTSX_SD_TRANSFER_START); 2738926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER, 2739926ce35aSJung-uk Kim RTSX_SD_TRANSFER_END, RTSX_SD_TRANSFER_END); 2740926ce35aSJung-uk Kim 2741926ce35aSJung-uk Kim /* Set transfer OK function. */ 2742926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_req_done; 2743926ce35aSJung-uk Kim 2744926ce35aSJung-uk Kim /* Run the command queue. */ 2745926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2746926ce35aSJung-uk Kim } 2747926ce35aSJung-uk Kim 2748926ce35aSJung-uk Kim /* 2749926ce35aSJung-uk Kim * Use the data buffer for transfer > 512 bytes. 2750926ce35aSJung-uk Kim */ 2751926ce35aSJung-uk Kim static int 2752926ce35aSJung-uk Kim rtsx_xfer(struct rtsx_softc *sc, struct mmc_command *cmd) 2753926ce35aSJung-uk Kim { 2754926ce35aSJung-uk Kim int read = ISSET(cmd->data->flags, MMC_DATA_READ); 2755926ce35aSJung-uk Kim 2756926ce35aSJung-uk Kim cmd->data->xfer_len = (cmd->data->len > RTSX_MAX_DATA_BLKLEN) ? 2757926ce35aSJung-uk Kim RTSX_MAX_DATA_BLKLEN : cmd->data->len; 2758926ce35aSJung-uk Kim 2759577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2760926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_xfer() - %s xfer: %ld bytes with block size %ld\n", 2761926ce35aSJung-uk Kim read ? "Read" : "Write", 2762926ce35aSJung-uk Kim (unsigned long)cmd->data->len, (unsigned long)cmd->data->xfer_len); 2763926ce35aSJung-uk Kim 2764926ce35aSJung-uk Kim if (cmd->data->len > RTSX_DMA_DATA_BUFSIZE) { 276513a5a46cSAndrew Gallatin device_printf(sc->rtsx_dev, "rtsx_xfer() length too large: %ld > %ld\n", 2766926ce35aSJung-uk Kim (unsigned long)cmd->data->len, RTSX_DMA_DATA_BUFSIZE); 2767926ce35aSJung-uk Kim cmd->error = MMC_ERR_INVALID; 2768926ce35aSJung-uk Kim return (MMC_ERR_INVALID); 2769926ce35aSJung-uk Kim } 2770926ce35aSJung-uk Kim 2771926ce35aSJung-uk Kim if (!read) { 2772926ce35aSJung-uk Kim /* Set transfer OK function. */ 2773926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_xfer_begin; 2774926ce35aSJung-uk Kim 2775926ce35aSJung-uk Kim /* Run the command queue. */ 2776926ce35aSJung-uk Kim rtsx_send_req(sc, cmd); 2777926ce35aSJung-uk Kim } else { 2778926ce35aSJung-uk Kim rtsx_xfer_start(sc); 2779926ce35aSJung-uk Kim } 2780926ce35aSJung-uk Kim 2781926ce35aSJung-uk Kim return (0); 2782926ce35aSJung-uk Kim } 2783926ce35aSJung-uk Kim 2784926ce35aSJung-uk Kim /* 2785926ce35aSJung-uk Kim * Get request response and start dma data transfer (write command). 2786926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2787926ce35aSJung-uk Kim */ 2788926ce35aSJung-uk Kim static void 2789926ce35aSJung-uk Kim rtsx_xfer_begin(struct rtsx_softc *sc) 2790926ce35aSJung-uk Kim { 2791926ce35aSJung-uk Kim struct mmc_command *cmd; 2792926ce35aSJung-uk Kim 2793926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2794926ce35aSJung-uk Kim 2795577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2796926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_xfer_begin() - CMD%d\n", cmd->opcode); 2797926ce35aSJung-uk Kim 2798926ce35aSJung-uk Kim rtsx_set_resp(sc, cmd); 2799926ce35aSJung-uk Kim rtsx_xfer_start(sc); 2800926ce35aSJung-uk Kim } 2801926ce35aSJung-uk Kim 2802926ce35aSJung-uk Kim /* 2803926ce35aSJung-uk Kim * Start dma data transfer. 2804926ce35aSJung-uk Kim */ 2805926ce35aSJung-uk Kim static void 2806926ce35aSJung-uk Kim rtsx_xfer_start(struct rtsx_softc *sc) 2807926ce35aSJung-uk Kim { 2808926ce35aSJung-uk Kim struct mmc_command *cmd; 2809926ce35aSJung-uk Kim int read; 2810926ce35aSJung-uk Kim uint8_t cfg2; 2811926ce35aSJung-uk Kim int dma_dir; 2812926ce35aSJung-uk Kim int tmode; 2813926ce35aSJung-uk Kim 2814926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2815926ce35aSJung-uk Kim read = ISSET(cmd->data->flags, MMC_DATA_READ); 2816926ce35aSJung-uk Kim 2817926ce35aSJung-uk Kim /* Configure DMA transfer mode parameters. */ 2818926ce35aSJung-uk Kim if (cmd->opcode == MMC_READ_MULTIPLE_BLOCK) 2819926ce35aSJung-uk Kim cfg2 = RTSX_SD_CHECK_CRC16 | RTSX_SD_NO_WAIT_BUSY_END | RTSX_SD_RSP_LEN_6; 2820926ce35aSJung-uk Kim else 2821926ce35aSJung-uk Kim cfg2 = RTSX_SD_CHECK_CRC16 | RTSX_SD_NO_WAIT_BUSY_END | RTSX_SD_RSP_LEN_0; 2822926ce35aSJung-uk Kim if (read) { 2823926ce35aSJung-uk Kim dma_dir = RTSX_DMA_DIR_FROM_CARD; 2824926ce35aSJung-uk Kim /* 2825926ce35aSJung-uk Kim * Use transfer mode AUTO_READ1, which assume we not 2826926ce35aSJung-uk Kim * already send the read command and don't need to send 2827926ce35aSJung-uk Kim * CMD 12 manually after read. 2828926ce35aSJung-uk Kim */ 2829926ce35aSJung-uk Kim tmode = RTSX_TM_AUTO_READ1; 2830926ce35aSJung-uk Kim cfg2 |= RTSX_SD_CALCULATE_CRC7 | RTSX_SD_CHECK_CRC7; 2831926ce35aSJung-uk Kim 2832926ce35aSJung-uk Kim rtsx_init_cmd(sc, cmd); 2833926ce35aSJung-uk Kim } else { 2834926ce35aSJung-uk Kim dma_dir = RTSX_DMA_DIR_TO_CARD; 2835926ce35aSJung-uk Kim /* 2836926ce35aSJung-uk Kim * Use transfer mode AUTO_WRITE3, wich assumes we've already 2837926ce35aSJung-uk Kim * sent the write command and gotten the response, and will 2838926ce35aSJung-uk Kim * send CMD 12 manually after writing. 2839926ce35aSJung-uk Kim */ 2840926ce35aSJung-uk Kim tmode = RTSX_TM_AUTO_WRITE3; 2841926ce35aSJung-uk Kim cfg2 |= RTSX_SD_NO_CALCULATE_CRC7 | RTSX_SD_NO_CHECK_CRC7; 2842926ce35aSJung-uk Kim 2843926ce35aSJung-uk Kim sc->rtsx_cmd_index = 0; 2844926ce35aSJung-uk Kim } 2845926ce35aSJung-uk Kim 2846926ce35aSJung-uk Kim /* Queue commands to configure data transfer size. */ 2847926ce35aSJung-uk Kim rtsx_set_cmd_data_len(sc, cmd->data->len / cmd->data->xfer_len, cmd->data->xfer_len); 2848926ce35aSJung-uk Kim 2849926ce35aSJung-uk Kim /* Configure DMA controller. */ 2850926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_IRQSTAT0, 2851926ce35aSJung-uk Kim RTSX_DMA_DONE_INT, RTSX_DMA_DONE_INT); 2852926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_DMATC3, 2853926ce35aSJung-uk Kim 0xff, cmd->data->len >> 24); 2854926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_DMATC2, 2855926ce35aSJung-uk Kim 0xff, cmd->data->len >> 16); 2856926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_DMATC1, 2857926ce35aSJung-uk Kim 0xff, cmd->data->len >> 8); 2858926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_DMATC0, 2859926ce35aSJung-uk Kim 0xff, cmd->data->len); 2860926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_DMACTL, 2861926ce35aSJung-uk Kim RTSX_DMA_EN | RTSX_DMA_DIR | RTSX_DMA_PACK_SIZE_MASK, 2862926ce35aSJung-uk Kim RTSX_DMA_EN | dma_dir | RTSX_DMA_512); 2863926ce35aSJung-uk Kim 2864926ce35aSJung-uk Kim /* Use the DMA ring buffer for commands which transfer data. */ 2865926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_CARD_DATA_SOURCE, 2866926ce35aSJung-uk Kim 0x01, RTSX_RING_BUFFER); 2867926ce35aSJung-uk Kim 2868926ce35aSJung-uk Kim /* Queue command to set response type. */ 2869926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_CFG2, 0xff, cfg2); 2870926ce35aSJung-uk Kim 2871926ce35aSJung-uk Kim /* Queue commands to perform SD transfer. */ 2872926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_WRITE_REG_CMD, RTSX_SD_TRANSFER, 2873926ce35aSJung-uk Kim 0xff, tmode | RTSX_SD_TRANSFER_START); 2874926ce35aSJung-uk Kim rtsx_push_cmd(sc, RTSX_CHECK_REG_CMD, RTSX_SD_TRANSFER, 2875926ce35aSJung-uk Kim RTSX_SD_TRANSFER_END, RTSX_SD_TRANSFER_END); 2876926ce35aSJung-uk Kim 2877926ce35aSJung-uk Kim /* Run the command queue. */ 2878926ce35aSJung-uk Kim rtsx_send_cmd(sc); 2879926ce35aSJung-uk Kim 2880926ce35aSJung-uk Kim if (!read) 2881926ce35aSJung-uk Kim memcpy(sc->rtsx_data_dmamem, cmd->data->data, cmd->data->len); 2882926ce35aSJung-uk Kim 2883926ce35aSJung-uk Kim /* Sync data DMA buffer. */ 2884926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_data_dma_tag, sc->rtsx_data_dmamap, BUS_DMASYNC_PREREAD); 2885926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_data_dma_tag, sc->rtsx_data_dmamap, BUS_DMASYNC_PREWRITE); 2886926ce35aSJung-uk Kim 2887926ce35aSJung-uk Kim /* Set transfer OK function. */ 2888926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = rtsx_xfer_finish; 2889926ce35aSJung-uk Kim 2890926ce35aSJung-uk Kim /* Tell the chip where the data buffer is and run the transfer. */ 2891926ce35aSJung-uk Kim WRITE4(sc, RTSX_HDBAR, sc->rtsx_data_buffer); 2892926ce35aSJung-uk Kim WRITE4(sc, RTSX_HDBCTLR, RTSX_TRIG_DMA | (read ? RTSX_DMA_READ : 0) | 2893926ce35aSJung-uk Kim (cmd->data->len & 0x00ffffff)); 2894926ce35aSJung-uk Kim } 2895926ce35aSJung-uk Kim 2896926ce35aSJung-uk Kim /* 2897926ce35aSJung-uk Kim * Finish dma data transfer. 2898926ce35aSJung-uk Kim * This Function is called by the interrupt handler via sc->rtsx_intr_trans_ok. 2899926ce35aSJung-uk Kim */ 2900926ce35aSJung-uk Kim static void 2901926ce35aSJung-uk Kim rtsx_xfer_finish(struct rtsx_softc *sc) 2902926ce35aSJung-uk Kim { 2903926ce35aSJung-uk Kim struct mmc_command *cmd; 2904926ce35aSJung-uk Kim int read; 2905926ce35aSJung-uk Kim 2906926ce35aSJung-uk Kim cmd = sc->rtsx_req->cmd; 2907926ce35aSJung-uk Kim 2908577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 2909926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_xfer_finish() - CMD%d\n", cmd->opcode); 2910926ce35aSJung-uk Kim 2911926ce35aSJung-uk Kim read = ISSET(cmd->data->flags, MMC_DATA_READ); 2912926ce35aSJung-uk Kim 2913926ce35aSJung-uk Kim /* Sync data DMA buffer. */ 2914926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_data_dma_tag, sc->rtsx_data_dmamap, BUS_DMASYNC_POSTREAD); 2915926ce35aSJung-uk Kim bus_dmamap_sync(sc->rtsx_data_dma_tag, sc->rtsx_data_dmamap, BUS_DMASYNC_POSTWRITE); 2916926ce35aSJung-uk Kim 2917926ce35aSJung-uk Kim if (read) { 2918926ce35aSJung-uk Kim memcpy(cmd->data->data, sc->rtsx_data_dmamem, cmd->data->len); 2919926ce35aSJung-uk Kim rtsx_req_done(sc); 2920926ce35aSJung-uk Kim } else { 2921926ce35aSJung-uk Kim /* Send CMD12 after AUTO_WRITE3 (see mmcsd_rw() in mmcsd.c) */ 2922926ce35aSJung-uk Kim /* and complete request. */ 2923926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = NULL; 2924926ce35aSJung-uk Kim rtsx_send_req(sc, sc->rtsx_req->stop); 2925926ce35aSJung-uk Kim } 2926926ce35aSJung-uk Kim } 2927926ce35aSJung-uk Kim 2928926ce35aSJung-uk Kim /* 2929926ce35aSJung-uk Kim * Manage request timeout. 2930926ce35aSJung-uk Kim */ 2931926ce35aSJung-uk Kim static void 2932926ce35aSJung-uk Kim rtsx_timeout(void *arg) 2933926ce35aSJung-uk Kim { 2934926ce35aSJung-uk Kim struct rtsx_softc *sc; 2935926ce35aSJung-uk Kim 2936926ce35aSJung-uk Kim sc = (struct rtsx_softc *)arg; 2937926ce35aSJung-uk Kim if (sc->rtsx_req != NULL) { 2938926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Controller timeout for CMD%u\n", 2939926ce35aSJung-uk Kim sc->rtsx_req->cmd->opcode); 2940926ce35aSJung-uk Kim sc->rtsx_req->cmd->error = MMC_ERR_TIMEOUT; 2941926ce35aSJung-uk Kim rtsx_stop_cmd(sc); 2942926ce35aSJung-uk Kim rtsx_req_done(sc); 2943926ce35aSJung-uk Kim } else { 2944926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "Controller timeout!\n"); 2945926ce35aSJung-uk Kim } 2946926ce35aSJung-uk Kim } 2947926ce35aSJung-uk Kim 2948926ce35aSJung-uk Kim #ifdef MMCCAM 29498e9740b6SHenri Hennebert static int 29508e9740b6SHenri Hennebert rtsx_get_tran_settings(device_t dev, struct ccb_trans_settings_mmc *cts) 2951926ce35aSJung-uk Kim { 2952926ce35aSJung-uk Kim struct rtsx_softc *sc; 2953926ce35aSJung-uk Kim 29548e9740b6SHenri Hennebert sc = device_get_softc(dev); 2955926ce35aSJung-uk Kim 29568e9740b6SHenri Hennebert cts->host_ocr = sc->rtsx_host.host_ocr; 29578e9740b6SHenri Hennebert cts->host_f_min = sc->rtsx_host.f_min; 29588e9740b6SHenri Hennebert cts->host_f_max = sc->rtsx_host.f_max; 29598e9740b6SHenri Hennebert cts->host_caps = sc->rtsx_host.caps; 29608e9740b6SHenri Hennebert cts->host_max_data = RTSX_DMA_DATA_BUFSIZE / MMC_SECTOR_SIZE; 29618e9740b6SHenri Hennebert memcpy(&cts->ios, &sc->rtsx_host.ios, sizeof(struct mmc_ios)); 2962926ce35aSJung-uk Kim 29638e9740b6SHenri Hennebert return (0); 2964926ce35aSJung-uk Kim } 2965926ce35aSJung-uk Kim 2966926ce35aSJung-uk Kim /* 29678e9740b6SHenri Hennebert * Apply settings and return status accordingly. 2968926ce35aSJung-uk Kim */ 29698e9740b6SHenri Hennebert static int 29708e9740b6SHenri Hennebert rtsx_set_tran_settings(device_t dev, struct ccb_trans_settings_mmc *cts) 2971926ce35aSJung-uk Kim { 29728e9740b6SHenri Hennebert struct rtsx_softc *sc; 2973926ce35aSJung-uk Kim struct mmc_ios *ios; 2974926ce35aSJung-uk Kim struct mmc_ios *new_ios; 29758e9740b6SHenri Hennebert 29768e9740b6SHenri Hennebert sc = device_get_softc(dev); 2977926ce35aSJung-uk Kim 2978926ce35aSJung-uk Kim ios = &sc->rtsx_host.ios; 2979926ce35aSJung-uk Kim new_ios = &cts->ios; 2980926ce35aSJung-uk Kim 2981926ce35aSJung-uk Kim /* Update only requested fields */ 2982926ce35aSJung-uk Kim if (cts->ios_valid & MMC_CLK) { 2983926ce35aSJung-uk Kim ios->clock = new_ios->clock; 2984926ce35aSJung-uk Kim sc->rtsx_ios_clock = -1; /* To be updated by rtsx_mmcbr_update_ios(). */ 2985577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 29868e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - clock: %u\n", ios->clock); 2987926ce35aSJung-uk Kim } 2988926ce35aSJung-uk Kim if (cts->ios_valid & MMC_VDD) { 2989926ce35aSJung-uk Kim ios->vdd = new_ios->vdd; 2990577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 29918e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - vdd: %d\n", ios->vdd); 2992926ce35aSJung-uk Kim } 2993926ce35aSJung-uk Kim if (cts->ios_valid & MMC_CS) { 2994926ce35aSJung-uk Kim ios->chip_select = new_ios->chip_select; 2995577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 29968e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - chip_select: %d\n", ios->chip_select); 2997926ce35aSJung-uk Kim } 2998926ce35aSJung-uk Kim if (cts->ios_valid & MMC_BW) { 2999926ce35aSJung-uk Kim ios->bus_width = new_ios->bus_width; 3000926ce35aSJung-uk Kim sc->rtsx_ios_bus_width = -1; /* To be updated by rtsx_mmcbr_update_ios(). */ 3001577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 30028e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - bus width: %d\n", ios->bus_width); 3003926ce35aSJung-uk Kim } 3004926ce35aSJung-uk Kim if (cts->ios_valid & MMC_PM) { 3005926ce35aSJung-uk Kim ios->power_mode = new_ios->power_mode; 3006926ce35aSJung-uk Kim sc->rtsx_ios_power_mode = -1; /* To be updated by rtsx_mmcbr_update_ios(). */ 3007577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 30088e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - power mode: %d\n", ios->power_mode); 3009926ce35aSJung-uk Kim } 3010926ce35aSJung-uk Kim if (cts->ios_valid & MMC_BT) { 3011926ce35aSJung-uk Kim ios->timing = new_ios->timing; 3012926ce35aSJung-uk Kim sc->rtsx_ios_timing = -1; /* To be updated by rtsx_mmcbr_update_ios(). */ 3013577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 30148e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - timing: %d\n", ios->timing); 3015926ce35aSJung-uk Kim } 3016926ce35aSJung-uk Kim if (cts->ios_valid & MMC_BM) { 3017926ce35aSJung-uk Kim ios->bus_mode = new_ios->bus_mode; 3018577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 30198e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - bus mode: %d\n", ios->bus_mode); 3020926ce35aSJung-uk Kim } 30217e5933b3SHenri Hennebert #if __FreeBSD_version >= 1300000 3022926ce35aSJung-uk Kim if (cts->ios_valid & MMC_VCCQ) { 3023926ce35aSJung-uk Kim ios->vccq = new_ios->vccq; 3024926ce35aSJung-uk Kim sc->rtsx_ios_vccq = -1; /* To be updated by rtsx_mmcbr_update_ios(). */ 3025577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 30268e9740b6SHenri Hennebert device_printf(sc->rtsx_dev, "rtsx_set_tran_settings() - vccq: %d\n", ios->vccq); 3027926ce35aSJung-uk Kim } 30287e5933b3SHenri Hennebert #endif /* __FreeBSD_version >= 1300000 */ 3029926ce35aSJung-uk Kim if (rtsx_mmcbr_update_ios(sc->rtsx_dev, NULL) == 0) 30308e9740b6SHenri Hennebert return (CAM_REQ_CMP); 3031926ce35aSJung-uk Kim else 30328e9740b6SHenri Hennebert return (CAM_REQ_CMP_ERR); 3033926ce35aSJung-uk Kim } 3034926ce35aSJung-uk Kim 3035926ce35aSJung-uk Kim /* 3036926ce35aSJung-uk Kim * Build a request and run it. 3037926ce35aSJung-uk Kim */ 30388e9740b6SHenri Hennebert static int 30398e9740b6SHenri Hennebert rtsx_cam_request(device_t dev, union ccb *ccb) 3040926ce35aSJung-uk Kim { 30418e9740b6SHenri Hennebert struct rtsx_softc *sc; 30428e9740b6SHenri Hennebert 30438e9740b6SHenri Hennebert sc = device_get_softc(dev); 30448e9740b6SHenri Hennebert 3045926ce35aSJung-uk Kim RTSX_LOCK(sc); 3046926ce35aSJung-uk Kim if (sc->rtsx_ccb != NULL) { 3047926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 30488e9740b6SHenri Hennebert return (CAM_BUSY); 3049926ce35aSJung-uk Kim } 3050926ce35aSJung-uk Kim sc->rtsx_ccb = ccb; 3051926ce35aSJung-uk Kim sc->rtsx_cam_req.cmd = &ccb->mmcio.cmd; 3052926ce35aSJung-uk Kim sc->rtsx_cam_req.stop = &ccb->mmcio.stop; 3053926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 3054926ce35aSJung-uk Kim 3055926ce35aSJung-uk Kim rtsx_mmcbr_request(sc->rtsx_dev, NULL, &sc->rtsx_cam_req); 30568e9740b6SHenri Hennebert return (0); 3057926ce35aSJung-uk Kim } 3058926ce35aSJung-uk Kim #endif /* MMCCAM */ 3059926ce35aSJung-uk Kim 3060926ce35aSJung-uk Kim static int 3061926ce35aSJung-uk Kim rtsx_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) 3062926ce35aSJung-uk Kim { 3063926ce35aSJung-uk Kim struct rtsx_softc *sc; 3064926ce35aSJung-uk Kim 3065926ce35aSJung-uk Kim sc = device_get_softc(bus); 3066926ce35aSJung-uk Kim switch (which) { 3067926ce35aSJung-uk Kim case MMCBR_IVAR_BUS_MODE: /* ivar 0 - 1 = opendrain, 2 = pushpull */ 3068926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.bus_mode; 3069926ce35aSJung-uk Kim break; 3070926ce35aSJung-uk Kim case MMCBR_IVAR_BUS_WIDTH: /* ivar 1 - 0 = 1b 2 = 4b, 3 = 8b */ 3071926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.bus_width; 3072926ce35aSJung-uk Kim break; 3073926ce35aSJung-uk Kim case MMCBR_IVAR_CHIP_SELECT: /* ivar 2 - O = dontcare, 1 = cs_high, 2 = cs_low */ 3074926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.chip_select; 3075926ce35aSJung-uk Kim break; 3076926ce35aSJung-uk Kim case MMCBR_IVAR_CLOCK: /* ivar 3 - clock in Hz */ 3077926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.clock; 3078926ce35aSJung-uk Kim break; 3079926ce35aSJung-uk Kim case MMCBR_IVAR_F_MIN: /* ivar 4 */ 3080926ce35aSJung-uk Kim *result = sc->rtsx_host.f_min; 3081926ce35aSJung-uk Kim break; 3082926ce35aSJung-uk Kim case MMCBR_IVAR_F_MAX: /* ivar 5 */ 3083926ce35aSJung-uk Kim *result = sc->rtsx_host.f_max; 3084926ce35aSJung-uk Kim break; 3085926ce35aSJung-uk Kim case MMCBR_IVAR_HOST_OCR: /* ivar 6 - host operation conditions register */ 3086926ce35aSJung-uk Kim *result = sc->rtsx_host.host_ocr; 3087926ce35aSJung-uk Kim break; 3088926ce35aSJung-uk Kim case MMCBR_IVAR_MODE: /* ivar 7 - 0 = mode_mmc, 1 = mode_sd */ 3089926ce35aSJung-uk Kim *result = sc->rtsx_host.mode; 3090926ce35aSJung-uk Kim break; 3091926ce35aSJung-uk Kim case MMCBR_IVAR_OCR: /* ivar 8 - operation conditions register */ 3092926ce35aSJung-uk Kim *result = sc->rtsx_host.ocr; 3093926ce35aSJung-uk Kim break; 3094926ce35aSJung-uk Kim case MMCBR_IVAR_POWER_MODE: /* ivar 9 - 0 = off, 1 = up, 2 = on */ 3095926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.power_mode; 3096926ce35aSJung-uk Kim break; 3097926ce35aSJung-uk Kim case MMCBR_IVAR_VDD: /* ivar 11 - voltage power pin */ 3098926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.vdd; 3099926ce35aSJung-uk Kim break; 3100926ce35aSJung-uk Kim case MMCBR_IVAR_VCCQ: /* ivar 12 - signaling: 0 = 1.20V, 1 = 1.80V, 2 = 3.30V */ 3101926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.vccq; 3102926ce35aSJung-uk Kim break; 3103926ce35aSJung-uk Kim case MMCBR_IVAR_CAPS: /* ivar 13 */ 3104926ce35aSJung-uk Kim *result = sc->rtsx_host.caps; 3105926ce35aSJung-uk Kim break; 3106926ce35aSJung-uk Kim case MMCBR_IVAR_TIMING: /* ivar 14 - 0 = normal, 1 = timing_hs, ... */ 3107926ce35aSJung-uk Kim *result = sc->rtsx_host.ios.timing; 3108926ce35aSJung-uk Kim break; 3109926ce35aSJung-uk Kim case MMCBR_IVAR_MAX_DATA: /* ivar 15 */ 3110926ce35aSJung-uk Kim *result = RTSX_DMA_DATA_BUFSIZE / MMC_SECTOR_SIZE; 3111926ce35aSJung-uk Kim break; 3112926ce35aSJung-uk Kim case MMCBR_IVAR_RETUNE_REQ: /* ivar 10 */ 3113926ce35aSJung-uk Kim case MMCBR_IVAR_MAX_BUSY_TIMEOUT: /* ivar 16 */ 3114926ce35aSJung-uk Kim default: 3115926ce35aSJung-uk Kim return (EINVAL); 3116926ce35aSJung-uk Kim } 3117926ce35aSJung-uk Kim 3118577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3119926ce35aSJung-uk Kim device_printf(bus, "Read ivar #%d, value %#x / #%d\n", 3120926ce35aSJung-uk Kim which, *(int *)result, *(int *)result); 3121926ce35aSJung-uk Kim 3122926ce35aSJung-uk Kim return (0); 3123926ce35aSJung-uk Kim } 3124926ce35aSJung-uk Kim 3125926ce35aSJung-uk Kim static int 3126926ce35aSJung-uk Kim rtsx_write_ivar(device_t bus, device_t child, int which, uintptr_t value) 3127926ce35aSJung-uk Kim { 3128926ce35aSJung-uk Kim struct rtsx_softc *sc; 3129926ce35aSJung-uk Kim 3130577130e5SHenri Hennebert sc = device_get_softc(bus); 3131577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3132926ce35aSJung-uk Kim device_printf(bus, "Write ivar #%d, value %#x / #%d\n", 3133926ce35aSJung-uk Kim which, (int)value, (int)value); 3134926ce35aSJung-uk Kim 3135926ce35aSJung-uk Kim switch (which) { 3136926ce35aSJung-uk Kim case MMCBR_IVAR_BUS_MODE: /* ivar 0 - 1 = opendrain, 2 = pushpull */ 3137926ce35aSJung-uk Kim sc->rtsx_host.ios.bus_mode = value; 3138926ce35aSJung-uk Kim break; 3139926ce35aSJung-uk Kim case MMCBR_IVAR_BUS_WIDTH: /* ivar 1 - 0 = 1b 2 = 4b, 3 = 8b */ 3140926ce35aSJung-uk Kim sc->rtsx_host.ios.bus_width = value; 3141926ce35aSJung-uk Kim sc->rtsx_ios_bus_width = -1; /* To be updated on next rtsx_mmcbr_update_ios(). */ 3142926ce35aSJung-uk Kim break; 3143926ce35aSJung-uk Kim case MMCBR_IVAR_CHIP_SELECT: /* ivar 2 - O = dontcare, 1 = cs_high, 2 = cs_low */ 3144926ce35aSJung-uk Kim sc->rtsx_host.ios.chip_select = value; 3145926ce35aSJung-uk Kim break; 3146926ce35aSJung-uk Kim case MMCBR_IVAR_CLOCK: /* ivar 3 - clock in Hz */ 3147926ce35aSJung-uk Kim sc->rtsx_host.ios.clock = value; 3148926ce35aSJung-uk Kim sc->rtsx_ios_clock = -1; /* To be updated on next rtsx_mmcbr_update_ios(). */ 3149926ce35aSJung-uk Kim break; 3150926ce35aSJung-uk Kim case MMCBR_IVAR_MODE: /* ivar 7 - 0 = mode_mmc, 1 = mode_sd */ 3151926ce35aSJung-uk Kim sc->rtsx_host.mode = value; 3152926ce35aSJung-uk Kim break; 3153926ce35aSJung-uk Kim case MMCBR_IVAR_OCR: /* ivar 8 - operation conditions register */ 3154926ce35aSJung-uk Kim sc->rtsx_host.ocr = value; 3155926ce35aSJung-uk Kim break; 3156926ce35aSJung-uk Kim case MMCBR_IVAR_POWER_MODE: /* ivar 9 - 0 = off, 1 = up, 2 = on */ 3157926ce35aSJung-uk Kim sc->rtsx_host.ios.power_mode = value; 3158926ce35aSJung-uk Kim sc->rtsx_ios_power_mode = -1; /* To be updated on next rtsx_mmcbr_update_ios(). */ 3159926ce35aSJung-uk Kim break; 3160926ce35aSJung-uk Kim case MMCBR_IVAR_VDD: /* ivar 11 - voltage power pin */ 3161926ce35aSJung-uk Kim sc->rtsx_host.ios.vdd = value; 3162926ce35aSJung-uk Kim break; 3163926ce35aSJung-uk Kim case MMCBR_IVAR_VCCQ: /* ivar 12 - signaling: 0 = 1.20V, 1 = 1.80V, 2 = 3.30V */ 3164926ce35aSJung-uk Kim sc->rtsx_host.ios.vccq = value; 3165926ce35aSJung-uk Kim sc->rtsx_ios_vccq = value; /* rtsx_mmcbr_switch_vccq() will be called by mmc.c (MMCCAM undef). */ 3166926ce35aSJung-uk Kim break; 3167926ce35aSJung-uk Kim case MMCBR_IVAR_TIMING: /* ivar 14 - 0 = normal, 1 = timing_hs, ... */ 3168926ce35aSJung-uk Kim sc->rtsx_host.ios.timing = value; 3169926ce35aSJung-uk Kim sc->rtsx_ios_timing = -1; /* To be updated on next rtsx_mmcbr_update_ios(). */ 3170926ce35aSJung-uk Kim break; 3171926ce35aSJung-uk Kim /* These are read-only. */ 3172926ce35aSJung-uk Kim case MMCBR_IVAR_F_MIN: /* ivar 4 */ 3173926ce35aSJung-uk Kim case MMCBR_IVAR_F_MAX: /* ivar 5 */ 3174926ce35aSJung-uk Kim case MMCBR_IVAR_HOST_OCR: /* ivar 6 - host operation conditions register */ 3175926ce35aSJung-uk Kim case MMCBR_IVAR_RETUNE_REQ: /* ivar 10 */ 3176926ce35aSJung-uk Kim case MMCBR_IVAR_CAPS: /* ivar 13 */ 3177926ce35aSJung-uk Kim case MMCBR_IVAR_MAX_DATA: /* ivar 15 */ 3178926ce35aSJung-uk Kim case MMCBR_IVAR_MAX_BUSY_TIMEOUT: /* ivar 16 */ 3179926ce35aSJung-uk Kim default: 3180926ce35aSJung-uk Kim return (EINVAL); 3181926ce35aSJung-uk Kim } 3182926ce35aSJung-uk Kim 3183926ce35aSJung-uk Kim return (0); 3184926ce35aSJung-uk Kim } 3185926ce35aSJung-uk Kim 3186926ce35aSJung-uk Kim static int 3187926ce35aSJung-uk Kim rtsx_mmcbr_update_ios(device_t bus, device_t child__unused) 3188926ce35aSJung-uk Kim { 3189926ce35aSJung-uk Kim struct rtsx_softc *sc; 3190926ce35aSJung-uk Kim struct mmc_ios *ios; 3191926ce35aSJung-uk Kim int error; 3192926ce35aSJung-uk Kim 3193926ce35aSJung-uk Kim sc = device_get_softc(bus); 3194926ce35aSJung-uk Kim ios = &sc->rtsx_host.ios; 3195926ce35aSJung-uk Kim 3196577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3197926ce35aSJung-uk Kim device_printf(bus, "rtsx_mmcbr_update_ios()\n"); 3198926ce35aSJung-uk Kim 3199926ce35aSJung-uk Kim /* if MMCBR_IVAR_BUS_WIDTH updated. */ 3200926ce35aSJung-uk Kim if (sc->rtsx_ios_bus_width < 0) { 3201926ce35aSJung-uk Kim sc->rtsx_ios_bus_width = ios->bus_width; 3202926ce35aSJung-uk Kim if ((error = rtsx_set_bus_width(sc, ios->bus_width))) 3203926ce35aSJung-uk Kim return (error); 3204926ce35aSJung-uk Kim } 3205926ce35aSJung-uk Kim 3206926ce35aSJung-uk Kim /* if MMCBR_IVAR_POWER_MODE updated. */ 3207926ce35aSJung-uk Kim if (sc->rtsx_ios_power_mode < 0) { 3208926ce35aSJung-uk Kim sc->rtsx_ios_power_mode = ios->power_mode; 3209926ce35aSJung-uk Kim switch (ios->power_mode) { 3210926ce35aSJung-uk Kim case power_off: 3211926ce35aSJung-uk Kim if ((error = rtsx_bus_power_off(sc))) 3212926ce35aSJung-uk Kim return (error); 3213926ce35aSJung-uk Kim break; 3214926ce35aSJung-uk Kim case power_up: 3215926ce35aSJung-uk Kim if ((error = rtsx_bus_power_on(sc))) 3216926ce35aSJung-uk Kim return (error); 3217926ce35aSJung-uk Kim break; 3218926ce35aSJung-uk Kim case power_on: 3219926ce35aSJung-uk Kim if ((error = rtsx_bus_power_on(sc))) 3220926ce35aSJung-uk Kim return (error); 3221926ce35aSJung-uk Kim break; 3222926ce35aSJung-uk Kim } 3223926ce35aSJung-uk Kim } 3224926ce35aSJung-uk Kim 3225926ce35aSJung-uk Kim sc->rtsx_double_clk = true; 3226926ce35aSJung-uk Kim sc->rtsx_vpclk = false; 3227926ce35aSJung-uk Kim 3228926ce35aSJung-uk Kim /* if MMCBR_IVAR_TIMING updated. */ 3229926ce35aSJung-uk Kim if (sc->rtsx_ios_timing < 0) { 3230926ce35aSJung-uk Kim sc->rtsx_ios_timing = ios->timing; 3231926ce35aSJung-uk Kim if ((error = rtsx_set_sd_timing(sc, ios->timing))) 3232926ce35aSJung-uk Kim return (error); 3233926ce35aSJung-uk Kim } 3234926ce35aSJung-uk Kim 3235926ce35aSJung-uk Kim /* if MMCBR_IVAR_CLOCK updated, must be after rtsx_set_sd_timing() */ 3236926ce35aSJung-uk Kim if (sc->rtsx_ios_clock < 0) { 3237926ce35aSJung-uk Kim sc->rtsx_ios_clock = ios->clock; 3238926ce35aSJung-uk Kim if ((error = rtsx_set_sd_clock(sc, ios->clock))) 3239926ce35aSJung-uk Kim return (error); 3240926ce35aSJung-uk Kim } 3241926ce35aSJung-uk Kim 3242926ce35aSJung-uk Kim /* if MMCCAM and vccq updated */ 3243926ce35aSJung-uk Kim if (sc->rtsx_ios_vccq < 0) { 3244926ce35aSJung-uk Kim sc->rtsx_ios_vccq = ios->vccq; 3245926ce35aSJung-uk Kim if ((error = rtsx_mmcbr_switch_vccq(sc->rtsx_dev, NULL))) 3246926ce35aSJung-uk Kim return (error); 3247926ce35aSJung-uk Kim } 3248926ce35aSJung-uk Kim 3249926ce35aSJung-uk Kim return (0); 3250926ce35aSJung-uk Kim } 3251926ce35aSJung-uk Kim 3252926ce35aSJung-uk Kim /* 3253926ce35aSJung-uk Kim * Set output stage logic power voltage. 3254926ce35aSJung-uk Kim */ 3255926ce35aSJung-uk Kim static int 3256926ce35aSJung-uk Kim rtsx_mmcbr_switch_vccq(device_t bus, device_t child __unused) 3257926ce35aSJung-uk Kim { 3258926ce35aSJung-uk Kim struct rtsx_softc *sc; 3259926ce35aSJung-uk Kim int vccq = 0; 3260926ce35aSJung-uk Kim int error; 3261926ce35aSJung-uk Kim 3262926ce35aSJung-uk Kim sc = device_get_softc(bus); 3263926ce35aSJung-uk Kim 3264926ce35aSJung-uk Kim switch (sc->rtsx_host.ios.vccq) { 3265926ce35aSJung-uk Kim case vccq_120: 3266926ce35aSJung-uk Kim vccq = 120; 3267926ce35aSJung-uk Kim break; 3268926ce35aSJung-uk Kim case vccq_180: 3269926ce35aSJung-uk Kim vccq = 180; 3270926ce35aSJung-uk Kim break; 3271926ce35aSJung-uk Kim case vccq_330: 3272926ce35aSJung-uk Kim vccq = 330; 3273926ce35aSJung-uk Kim break; 3274926ce35aSJung-uk Kim }; 3275926ce35aSJung-uk Kim /* It seems it is always vccq_330. */ 3276926ce35aSJung-uk Kim if (vccq == 330) { 3277926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 3278926ce35aSJung-uk Kim uint16_t val; 3279926ce35aSJung-uk Kim case RTSX_RTS5227: 3280926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, 0x08, 0x4FE4))) 3281926ce35aSJung-uk Kim return (error); 3282926ce35aSJung-uk Kim if ((error = rtsx_rts5227_fill_driving(sc))) 3283926ce35aSJung-uk Kim return (error); 3284926ce35aSJung-uk Kim break; 3285926ce35aSJung-uk Kim case RTSX_RTS5209: 3286926ce35aSJung-uk Kim case RTSX_RTS5229: 3287926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD30_CMD_DRIVE_SEL, RTSX_SD30_DRIVE_SEL_MASK, sc->rtsx_sd30_drive_sel_3v3); 3288926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, 0x08, 0x4FE4))) 3289926ce35aSJung-uk Kim return (error); 3290926ce35aSJung-uk Kim break; 3291926ce35aSJung-uk Kim case RTSX_RTS522A: 3292926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, 0x08, 0x57E4))) 3293926ce35aSJung-uk Kim return (error); 3294926ce35aSJung-uk Kim if ((error = rtsx_rts5227_fill_driving(sc))) 3295926ce35aSJung-uk Kim return (error); 3296926ce35aSJung-uk Kim break; 3297926ce35aSJung-uk Kim case RTSX_RTS525A: 3298926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_CONFIG2, RTSX_LDO_D3318_MASK, RTSX_LDO_D3318_33V); 3299926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD_PAD_CTL, RTSX_SD_IO_USING_1V8, 0); 3300926ce35aSJung-uk Kim if ((error = rtsx_rts5249_fill_driving(sc))) 3301926ce35aSJung-uk Kim return (error); 3302926ce35aSJung-uk Kim break; 3303926ce35aSJung-uk Kim case RTSX_RTS5249: 3304926ce35aSJung-uk Kim if ((error = rtsx_read_phy(sc, RTSX_PHY_TUNE, &val))) 3305926ce35aSJung-uk Kim return (error); 3306926ce35aSJung-uk Kim if ((error = rtsx_write_phy(sc, RTSX_PHY_TUNE, 3307926ce35aSJung-uk Kim (val & RTSX_PHY_TUNE_VOLTAGE_MASK) | RTSX_PHY_TUNE_VOLTAGE_3V3))) 3308926ce35aSJung-uk Kim return (error); 3309926ce35aSJung-uk Kim if ((error = rtsx_rts5249_fill_driving(sc))) 3310926ce35aSJung-uk Kim return (error); 3311926ce35aSJung-uk Kim break; 3312577130e5SHenri Hennebert case RTSX_RTS5260: 3313577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_CONFIG2, RTSX_DV331812_VDD1, RTSX_DV331812_VDD1); 3314577130e5SHenri Hennebert RTSX_BITOP(sc, RTSX_LDO_DV18_CFG, RTSX_DV331812_MASK, RTSX_DV331812_33); 33158290c144SHenri Hennebert RTSX_CLR(sc, RTSX_SD_PAD_CTL, RTSX_SD_IO_USING_1V8); 3316577130e5SHenri Hennebert if ((error = rtsx_rts5260_fill_driving(sc))) 3317577130e5SHenri Hennebert return (error); 3318577130e5SHenri Hennebert break; 3319926ce35aSJung-uk Kim case RTSX_RTL8402: 3320926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD30_CMD_DRIVE_SEL, RTSX_SD30_DRIVE_SEL_MASK, sc->rtsx_sd30_drive_sel_3v3); 3321926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_CTL, 3322926ce35aSJung-uk Kim (RTSX_BPP_ASIC_MASK << RTSX_BPP_SHIFT_8402) | RTSX_BPP_PAD_MASK, 3323926ce35aSJung-uk Kim (RTSX_BPP_ASIC_3V3 << RTSX_BPP_SHIFT_8402) | RTSX_BPP_PAD_3V3); 3324926ce35aSJung-uk Kim break; 3325926ce35aSJung-uk Kim case RTSX_RTL8411: 3326926ce35aSJung-uk Kim case RTSX_RTL8411B: 3327926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_SD30_CMD_DRIVE_SEL, RTSX_SD30_DRIVE_SEL_MASK, sc->rtsx_sd30_drive_sel_3v3); 3328926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_LDO_CTL, 3329926ce35aSJung-uk Kim (RTSX_BPP_ASIC_MASK << RTSX_BPP_SHIFT_8411) | RTSX_BPP_PAD_MASK, 3330926ce35aSJung-uk Kim (RTSX_BPP_ASIC_3V3 << RTSX_BPP_SHIFT_8411) | RTSX_BPP_PAD_3V3); 3331926ce35aSJung-uk Kim break; 3332926ce35aSJung-uk Kim } 3333926ce35aSJung-uk Kim DELAY(300); 3334926ce35aSJung-uk Kim } 3335926ce35aSJung-uk Kim 3336577130e5SHenri Hennebert if (sc->rtsx_debug_mask & (RTSX_DEBUG_BASIC | RTSX_TRACE_SD_CMD)) 3337926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_mmcbr_switch_vccq(%d)\n", vccq); 3338926ce35aSJung-uk Kim 3339926ce35aSJung-uk Kim return (0); 3340926ce35aSJung-uk Kim } 3341926ce35aSJung-uk Kim 33428e9740b6SHenri Hennebert #ifndef MMCCAM 3343926ce35aSJung-uk Kim /* 3344926ce35aSJung-uk Kim * Tune card if bus_timing_uhs_sdr50. 3345926ce35aSJung-uk Kim */ 3346926ce35aSJung-uk Kim static int 3347926ce35aSJung-uk Kim rtsx_mmcbr_tune(device_t bus, device_t child __unused, bool hs400) 3348926ce35aSJung-uk Kim { 3349926ce35aSJung-uk Kim struct rtsx_softc *sc; 3350926ce35aSJung-uk Kim uint32_t raw_phase_map[RTSX_RX_TUNING_CNT] = {0}; 3351926ce35aSJung-uk Kim uint32_t phase_map; 3352926ce35aSJung-uk Kim uint8_t final_phase; 3353926ce35aSJung-uk Kim int i; 3354926ce35aSJung-uk Kim 3355926ce35aSJung-uk Kim sc = device_get_softc(bus); 3356926ce35aSJung-uk Kim 3357577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 3358926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_mmcbr_tune() - hs400 is %s\n", 3359926ce35aSJung-uk Kim (hs400) ? "true" : "false"); 3360926ce35aSJung-uk Kim 3361926ce35aSJung-uk Kim if (sc->rtsx_ios_timing != bus_timing_uhs_sdr50) 3362926ce35aSJung-uk Kim return (0); 3363926ce35aSJung-uk Kim 3364926ce35aSJung-uk Kim sc->rtsx_tuning_mode = true; 3365926ce35aSJung-uk Kim 3366926ce35aSJung-uk Kim switch (sc->rtsx_device_id) { 3367926ce35aSJung-uk Kim case RTSX_RTS5209: 3368926ce35aSJung-uk Kim case RTSX_RTS5227: 3369926ce35aSJung-uk Kim rtsx_sd_change_tx_phase(sc, 27); 3370926ce35aSJung-uk Kim break; 3371926ce35aSJung-uk Kim case RTSX_RTS522A: 3372926ce35aSJung-uk Kim rtsx_sd_change_tx_phase(sc, 20); 3373926ce35aSJung-uk Kim break; 3374926ce35aSJung-uk Kim case RTSX_RTS5229: 3375926ce35aSJung-uk Kim rtsx_sd_change_tx_phase(sc, 27); 3376926ce35aSJung-uk Kim break; 3377926ce35aSJung-uk Kim case RTSX_RTS525A: 3378926ce35aSJung-uk Kim case RTSX_RTS5249: 3379926ce35aSJung-uk Kim rtsx_sd_change_tx_phase(sc, 29); 3380926ce35aSJung-uk Kim break; 3381926ce35aSJung-uk Kim case RTSX_RTL8402: 3382926ce35aSJung-uk Kim case RTSX_RTL8411: 3383926ce35aSJung-uk Kim case RTSX_RTL8411B: 3384926ce35aSJung-uk Kim rtsx_sd_change_tx_phase(sc, 7); 3385926ce35aSJung-uk Kim break; 3386926ce35aSJung-uk Kim } 3387926ce35aSJung-uk Kim 3388926ce35aSJung-uk Kim /* trying rx tuning for bus_timing_uhs_sdr50. */ 3389926ce35aSJung-uk Kim for (i = 0; i < RTSX_RX_TUNING_CNT; i++) { 3390926ce35aSJung-uk Kim rtsx_sd_tuning_rx_phase(sc, &(raw_phase_map[i])); 3391926ce35aSJung-uk Kim if (raw_phase_map[i] == 0) 3392926ce35aSJung-uk Kim break; 3393926ce35aSJung-uk Kim } 3394926ce35aSJung-uk Kim 3395926ce35aSJung-uk Kim phase_map = 0xffffffff; 3396926ce35aSJung-uk Kim for (i = 0; i < RTSX_RX_TUNING_CNT; i++) { 3397577130e5SHenri Hennebert if (sc->rtsx_debug_mask & (RTSX_DEBUG_BASIC | RTSX_DEBUG_TUNING)) 3398926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_mmcbr_tune() - RX raw_phase_map[%d]: 0x%08x\n", 3399926ce35aSJung-uk Kim i, raw_phase_map[i]); 3400926ce35aSJung-uk Kim phase_map &= raw_phase_map[i]; 3401926ce35aSJung-uk Kim } 3402577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 3403926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_mmcbr_tune() - RX phase_map: 0x%08x\n", phase_map); 3404926ce35aSJung-uk Kim 3405926ce35aSJung-uk Kim if (phase_map) { 3406926ce35aSJung-uk Kim final_phase = rtsx_sd_search_final_rx_phase(sc, phase_map); 3407926ce35aSJung-uk Kim if (final_phase != 0xff) { 3408926ce35aSJung-uk Kim rtsx_sd_change_rx_phase(sc, final_phase); 3409926ce35aSJung-uk Kim } 3410926ce35aSJung-uk Kim } 3411926ce35aSJung-uk Kim 3412926ce35aSJung-uk Kim sc->rtsx_tuning_mode = false; 3413926ce35aSJung-uk Kim 3414926ce35aSJung-uk Kim return (0); 3415926ce35aSJung-uk Kim } 3416926ce35aSJung-uk Kim 3417926ce35aSJung-uk Kim static int 3418926ce35aSJung-uk Kim rtsx_mmcbr_retune(device_t bus, device_t child __unused, bool reset __unused) 3419926ce35aSJung-uk Kim { 3420926ce35aSJung-uk Kim struct rtsx_softc *sc; 3421926ce35aSJung-uk Kim 3422926ce35aSJung-uk Kim sc = device_get_softc(bus); 3423926ce35aSJung-uk Kim 3424577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3425926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_mmcbr_retune()\n"); 3426926ce35aSJung-uk Kim 3427926ce35aSJung-uk Kim return (0); 3428926ce35aSJung-uk Kim } 34298e9740b6SHenri Hennebert #endif /* !MMCCAM */ 3430926ce35aSJung-uk Kim 3431926ce35aSJung-uk Kim static int 3432926ce35aSJung-uk Kim rtsx_mmcbr_request(device_t bus, device_t child __unused, struct mmc_request *req) 3433926ce35aSJung-uk Kim { 3434926ce35aSJung-uk Kim struct rtsx_softc *sc; 3435926ce35aSJung-uk Kim struct mmc_command *cmd; 34369d3bc163SHenri Hennebert int timeout; 3437926ce35aSJung-uk Kim int error; 3438926ce35aSJung-uk Kim 3439926ce35aSJung-uk Kim sc = device_get_softc(bus); 3440926ce35aSJung-uk Kim 3441926ce35aSJung-uk Kim RTSX_LOCK(sc); 3442926ce35aSJung-uk Kim if (sc->rtsx_req != NULL) { 3443926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 3444926ce35aSJung-uk Kim return (EBUSY); 3445926ce35aSJung-uk Kim } 3446926ce35aSJung-uk Kim sc->rtsx_req = req; 3447926ce35aSJung-uk Kim cmd = req->cmd; 3448926ce35aSJung-uk Kim cmd->error = error = MMC_ERR_NONE; 3449926ce35aSJung-uk Kim sc->rtsx_intr_status = 0; 3450926ce35aSJung-uk Kim sc->rtsx_intr_trans_ok = NULL; 3451926ce35aSJung-uk Kim sc->rtsx_intr_trans_ko = rtsx_req_done; 3452926ce35aSJung-uk Kim 3453577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3454926ce35aSJung-uk Kim device_printf(sc->rtsx_dev, "rtsx_mmcbr_request(CMD%u arg %#x, flags %#x, dlen %u, dflags %#x)\n", 3455926ce35aSJung-uk Kim cmd->opcode, cmd->arg, cmd->flags, 3456926ce35aSJung-uk Kim cmd->data != NULL ? (unsigned int)cmd->data->len : 0, 3457926ce35aSJung-uk Kim cmd->data != NULL ? cmd->data->flags : 0); 3458926ce35aSJung-uk Kim 3459926ce35aSJung-uk Kim /* Check if card present. */ 3460926ce35aSJung-uk Kim if (!ISSET(sc->rtsx_flags, RTSX_F_CARD_PRESENT)) { 3461926ce35aSJung-uk Kim cmd->error = error = MMC_ERR_FAILED; 3462926ce35aSJung-uk Kim goto end; 3463926ce35aSJung-uk Kim } 3464926ce35aSJung-uk Kim 3465926ce35aSJung-uk Kim /* Refuse SDIO probe if the chip doesn't support SDIO. */ 3466926ce35aSJung-uk Kim if (cmd->opcode == IO_SEND_OP_COND && 3467926ce35aSJung-uk Kim !ISSET(sc->rtsx_flags, RTSX_F_SDIO_SUPPORT)) { 3468926ce35aSJung-uk Kim cmd->error = error = MMC_ERR_INVALID; 3469926ce35aSJung-uk Kim goto end; 3470926ce35aSJung-uk Kim } 3471926ce35aSJung-uk Kim 3472926ce35aSJung-uk Kim /* Return MMC_ERR_TIMEOUT for SD_IO_RW_DIRECT and IO_SEND_OP_COND. */ 3473926ce35aSJung-uk Kim if (cmd->opcode == SD_IO_RW_DIRECT || cmd->opcode == IO_SEND_OP_COND) { 3474926ce35aSJung-uk Kim cmd->error = error = MMC_ERR_TIMEOUT; 3475926ce35aSJung-uk Kim goto end; 3476926ce35aSJung-uk Kim } 3477926ce35aSJung-uk Kim 3478926ce35aSJung-uk Kim /* Select SD card. */ 3479926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_SELECT, 0x07, RTSX_SD_MOD_SEL); 3480926ce35aSJung-uk Kim RTSX_BITOP(sc, RTSX_CARD_SHARE_MODE, RTSX_CARD_SHARE_MASK, RTSX_CARD_SHARE_48_SD); 3481926ce35aSJung-uk Kim 3482926ce35aSJung-uk Kim if (cmd->data == NULL) { 3483926ce35aSJung-uk Kim DELAY(200); 34849d3bc163SHenri Hennebert timeout = sc->rtsx_timeout_cmd; 3485926ce35aSJung-uk Kim error = rtsx_send_req(sc, cmd); 3486926ce35aSJung-uk Kim } else if (cmd->data->len <= 512) { 34879d3bc163SHenri Hennebert timeout = sc->rtsx_timeout_io; 3488926ce35aSJung-uk Kim error = rtsx_xfer_short(sc, cmd); 3489926ce35aSJung-uk Kim } else { 34909d3bc163SHenri Hennebert timeout = sc->rtsx_timeout_io; 3491926ce35aSJung-uk Kim error = rtsx_xfer(sc, cmd); 3492926ce35aSJung-uk Kim } 3493926ce35aSJung-uk Kim end: 3494926ce35aSJung-uk Kim if (error == MMC_ERR_NONE) { 34959d3bc163SHenri Hennebert callout_reset(&sc->rtsx_timeout_callout, timeout * hz, rtsx_timeout, sc); 3496926ce35aSJung-uk Kim } else { 3497926ce35aSJung-uk Kim rtsx_req_done(sc); 3498926ce35aSJung-uk Kim } 3499926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 3500926ce35aSJung-uk Kim 3501926ce35aSJung-uk Kim return (error); 3502926ce35aSJung-uk Kim } 3503926ce35aSJung-uk Kim 35048e9740b6SHenri Hennebert #ifndef MMCCAM 3505926ce35aSJung-uk Kim static int 3506926ce35aSJung-uk Kim rtsx_mmcbr_get_ro(device_t bus, device_t child __unused) 3507926ce35aSJung-uk Kim { 3508926ce35aSJung-uk Kim struct rtsx_softc *sc; 3509926ce35aSJung-uk Kim 3510926ce35aSJung-uk Kim sc = device_get_softc(bus); 3511926ce35aSJung-uk Kim 3512926ce35aSJung-uk Kim if (sc->rtsx_inversion == 0) 3513926ce35aSJung-uk Kim return (sc->rtsx_read_only); 3514926ce35aSJung-uk Kim else 3515926ce35aSJung-uk Kim return !(sc->rtsx_read_only); 3516926ce35aSJung-uk Kim } 3517926ce35aSJung-uk Kim 3518926ce35aSJung-uk Kim static int 3519926ce35aSJung-uk Kim rtsx_mmcbr_acquire_host(device_t bus, device_t child __unused) 3520926ce35aSJung-uk Kim { 3521926ce35aSJung-uk Kim struct rtsx_softc *sc; 3522926ce35aSJung-uk Kim 3523577130e5SHenri Hennebert sc = device_get_softc(bus); 3524577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3525926ce35aSJung-uk Kim device_printf(bus, "rtsx_mmcbr_acquire_host()\n"); 3526926ce35aSJung-uk Kim 3527926ce35aSJung-uk Kim RTSX_LOCK(sc); 3528926ce35aSJung-uk Kim while (sc->rtsx_bus_busy) 3529926ce35aSJung-uk Kim msleep(&sc->rtsx_bus_busy, &sc->rtsx_mtx, 0, "rtsxah", 0); 3530926ce35aSJung-uk Kim sc->rtsx_bus_busy++; 3531926ce35aSJung-uk Kim RTSX_UNLOCK(sc); 3532926ce35aSJung-uk Kim 3533926ce35aSJung-uk Kim return (0); 3534926ce35aSJung-uk Kim } 3535926ce35aSJung-uk Kim 3536926ce35aSJung-uk Kim static int 3537926ce35aSJung-uk Kim rtsx_mmcbr_release_host(device_t bus, device_t child __unused) 3538926ce35aSJung-uk Kim { 3539926ce35aSJung-uk Kim struct rtsx_softc *sc; 3540926ce35aSJung-uk Kim 3541577130e5SHenri Hennebert sc = device_get_softc(bus); 3542577130e5SHenri Hennebert if (sc->rtsx_debug_mask & RTSX_TRACE_SD_CMD) 3543926ce35aSJung-uk Kim device_printf(bus, "rtsx_mmcbr_release_host()\n"); 3544926ce35aSJung-uk Kim 3545926ce35aSJung-uk Kim RTSX_LOCK(sc); 3546926ce35aSJung-uk Kim sc->rtsx_bus_busy--; 3547926ce35aSJung-uk Kim wakeup(&sc->rtsx_bus_busy); 35489339e7c0SWarner Losh RTSX_UNLOCK(sc); 3549926ce35aSJung-uk Kim 3550926ce35aSJung-uk Kim return (0); 3551926ce35aSJung-uk Kim } 35528e9740b6SHenri Hennebert #endif /* !MMCCAM */ 3553926ce35aSJung-uk Kim 3554926ce35aSJung-uk Kim /* 3555926ce35aSJung-uk Kim * 3556926ce35aSJung-uk Kim * PCI Support Functions 3557926ce35aSJung-uk Kim * 3558926ce35aSJung-uk Kim */ 3559926ce35aSJung-uk Kim 3560926ce35aSJung-uk Kim /* 3561926ce35aSJung-uk Kim * Compare the device ID (chip) of this device against the IDs that this driver 3562926ce35aSJung-uk Kim * supports. If there is a match, set the description and return success. 3563926ce35aSJung-uk Kim */ 3564926ce35aSJung-uk Kim static int 3565926ce35aSJung-uk Kim rtsx_probe(device_t dev) 3566926ce35aSJung-uk Kim { 3567926ce35aSJung-uk Kim uint16_t vendor_id; 3568926ce35aSJung-uk Kim uint16_t device_id; 3569926ce35aSJung-uk Kim int i; 3570926ce35aSJung-uk Kim 3571926ce35aSJung-uk Kim vendor_id = pci_get_vendor(dev); 3572926ce35aSJung-uk Kim device_id = pci_get_device(dev); 3573926ce35aSJung-uk Kim 357471883128SHenri Hennebert if (vendor_id != RTSX_REALTEK) 357571883128SHenri Hennebert return (ENXIO); 357671883128SHenri Hennebert for (i = 0; i < nitems(rtsx_ids); i++) { 357771883128SHenri Hennebert if (rtsx_ids[i].device_id == device_id) { 357871883128SHenri Hennebert device_set_desc(dev, rtsx_ids[i].desc); 357971883128SHenri Hennebert return (BUS_PROBE_DEFAULT); 3580926ce35aSJung-uk Kim } 3581926ce35aSJung-uk Kim } 358271883128SHenri Hennebert return (ENXIO); 3583926ce35aSJung-uk Kim } 3584926ce35aSJung-uk Kim 3585926ce35aSJung-uk Kim /* 3586926ce35aSJung-uk Kim * Attach function is only called if the probe is successful. 3587926ce35aSJung-uk Kim */ 3588926ce35aSJung-uk Kim static int 3589926ce35aSJung-uk Kim rtsx_attach(device_t dev) 3590926ce35aSJung-uk Kim { 3591926ce35aSJung-uk Kim struct rtsx_softc *sc = device_get_softc(dev); 35922e883067SHenri Hennebert uint16_t vendor_id; 35932e883067SHenri Hennebert uint16_t device_id; 3594926ce35aSJung-uk Kim struct sysctl_ctx_list *ctx; 3595926ce35aSJung-uk Kim struct sysctl_oid_list *tree; 3596926ce35aSJung-uk Kim int msi_count = 1; 3597926ce35aSJung-uk Kim uint32_t sdio_cfg; 3598926ce35aSJung-uk Kim int error; 35999d3bc163SHenri Hennebert char *maker; 36009d3bc163SHenri Hennebert char *family; 36019d3bc163SHenri Hennebert char *product; 36029d3bc163SHenri Hennebert int i; 3603926ce35aSJung-uk Kim 36042e883067SHenri Hennebert vendor_id = pci_get_vendor(dev); 36052e883067SHenri Hennebert device_id = pci_get_device(dev); 3606926ce35aSJung-uk Kim if (bootverbose) 3607926ce35aSJung-uk Kim device_printf(dev, "Attach - Vendor ID: 0x%x - Device ID: 0x%x\n", 36082e883067SHenri Hennebert vendor_id, device_id); 3609926ce35aSJung-uk Kim 3610926ce35aSJung-uk Kim sc->rtsx_dev = dev; 36112e883067SHenri Hennebert sc->rtsx_device_id = device_id; 3612926ce35aSJung-uk Kim sc->rtsx_req = NULL; 36139d3bc163SHenri Hennebert sc->rtsx_timeout_cmd = 1; 36149d3bc163SHenri Hennebert sc->rtsx_timeout_io = 10; 3615926ce35aSJung-uk Kim sc->rtsx_read_only = 0; 36169d3bc163SHenri Hennebert sc->rtsx_inversion = 0; 3617926ce35aSJung-uk Kim sc->rtsx_force_timing = 0; 3618577130e5SHenri Hennebert sc->rtsx_debug_mask = 0; 3619926ce35aSJung-uk Kim sc->rtsx_read_count = 0; 3620926ce35aSJung-uk Kim sc->rtsx_write_count = 0; 3621926ce35aSJung-uk Kim 36229d3bc163SHenri Hennebert maker = kern_getenv("smbios.system.maker"); 36239d3bc163SHenri Hennebert family = kern_getenv("smbios.system.family"); 36249d3bc163SHenri Hennebert product = kern_getenv("smbios.system.product"); 36259d3bc163SHenri Hennebert for (i = 0; rtsx_inversion_models[i].maker != NULL; i++) { 36269d3bc163SHenri Hennebert if (strcmp(rtsx_inversion_models[i].maker, maker) == 0 && 36279d3bc163SHenri Hennebert strcmp(rtsx_inversion_models[i].family, family) == 0 && 36289d3bc163SHenri Hennebert strcmp(rtsx_inversion_models[i].product, product) == 0) { 36299d3bc163SHenri Hennebert device_printf(dev, "Inversion activated for %s/%s/%s, see BUG in rtsx(4)\n", maker, family, product); 36309d3bc163SHenri Hennebert device_printf(dev, "If a card is detected without an SD card present," 36319d3bc163SHenri Hennebert " add dev.rtsx.0.inversion=0 in loader.conf(5)\n"); 36329d3bc163SHenri Hennebert sc->rtsx_inversion = 1; 3633459404cbSWarner Losh break; 36349d3bc163SHenri Hennebert } 36359d3bc163SHenri Hennebert } 36369d3bc163SHenri Hennebert 3637926ce35aSJung-uk Kim RTSX_LOCK_INIT(sc); 3638926ce35aSJung-uk Kim 3639926ce35aSJung-uk Kim ctx = device_get_sysctl_ctx(dev); 3640926ce35aSJung-uk Kim tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); 36419d3bc163SHenri Hennebert SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "timeout_io", CTLFLAG_RW, 36429d3bc163SHenri Hennebert &sc->rtsx_timeout_io, 0, "Request timeout for I/O commands in seconds"); 36439d3bc163SHenri Hennebert SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "timeout_cmd", CTLFLAG_RW, 36449d3bc163SHenri Hennebert &sc->rtsx_timeout_cmd, 0, "Request timeout for setup commands in seconds"); 3645926ce35aSJung-uk Kim SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "read_only", CTLFLAG_RD, 3646926ce35aSJung-uk Kim &sc->rtsx_read_only, 0, "Card is write protected"); 3647926ce35aSJung-uk Kim SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "inversion", CTLFLAG_RWTUN, 3648926ce35aSJung-uk Kim &sc->rtsx_inversion, 0, "Inversion of card detection and read only status"); 3649926ce35aSJung-uk Kim SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "force_timing", CTLFLAG_RW, 3650926ce35aSJung-uk Kim &sc->rtsx_force_timing, 0, "Force bus_timing_uhs_sdr50"); 3651577130e5SHenri Hennebert SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "debug_mask", CTLFLAG_RWTUN, 3652577130e5SHenri Hennebert &sc->rtsx_debug_mask, 0, "debugging mask, see rtsx(4)"); 3653ec1f122bSHenri Hennebert SYSCTL_ADD_U64(ctx, tree, OID_AUTO, "read_count", CTLFLAG_RD | CTLFLAG_STATS, 3654926ce35aSJung-uk Kim &sc->rtsx_read_count, 0, "Count of read operations"); 3655ec1f122bSHenri Hennebert SYSCTL_ADD_U64(ctx, tree, OID_AUTO, "write_count", CTLFLAG_RD | CTLFLAG_STATS, 3656926ce35aSJung-uk Kim &sc->rtsx_write_count, 0, "Count of write operations"); 3657926ce35aSJung-uk Kim 3658577130e5SHenri Hennebert if (bootverbose || sc->rtsx_debug_mask & RTSX_DEBUG_BASIC) 36599d3bc163SHenri Hennebert device_printf(dev, "We are running with inversion: %d\n", sc->rtsx_inversion); 36609d3bc163SHenri Hennebert 3661926ce35aSJung-uk Kim /* Allocate IRQ. */ 3662926ce35aSJung-uk Kim sc->rtsx_irq_res_id = 0; 3663926ce35aSJung-uk Kim if (pci_alloc_msi(dev, &msi_count) == 0) 3664926ce35aSJung-uk Kim sc->rtsx_irq_res_id = 1; 3665926ce35aSJung-uk Kim sc->rtsx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rtsx_irq_res_id, 3666926ce35aSJung-uk Kim RF_ACTIVE | (sc->rtsx_irq_res_id != 0 ? 0 : RF_SHAREABLE)); 3667926ce35aSJung-uk Kim if (sc->rtsx_irq_res == NULL) { 3668926ce35aSJung-uk Kim device_printf(dev, "Can't allocate IRQ resources for %d\n", sc->rtsx_irq_res_id); 3669926ce35aSJung-uk Kim pci_release_msi(dev); 3670926ce35aSJung-uk Kim return (ENXIO); 3671926ce35aSJung-uk Kim } 3672926ce35aSJung-uk Kim 3673926ce35aSJung-uk Kim callout_init_mtx(&sc->rtsx_timeout_callout, &sc->rtsx_mtx, 0); 3674926ce35aSJung-uk Kim 3675926ce35aSJung-uk Kim /* Allocate memory resource. */ 3676926ce35aSJung-uk Kim if (sc->rtsx_device_id == RTSX_RTS525A) 36772e883067SHenri Hennebert sc->rtsx_mem_res_id = PCIR_BAR(1); 3678926ce35aSJung-uk Kim else 36792e883067SHenri Hennebert sc->rtsx_mem_res_id = PCIR_BAR(0); 36802e883067SHenri Hennebert sc->rtsx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rtsx_mem_res_id, RF_ACTIVE); 36812e883067SHenri Hennebert if (sc->rtsx_mem_res == NULL) { 36822e883067SHenri Hennebert device_printf(dev, "Can't allocate memory resource for %d\n", sc->rtsx_mem_res_id); 3683926ce35aSJung-uk Kim goto destroy_rtsx_irq_res; 3684926ce35aSJung-uk Kim } 3685926ce35aSJung-uk Kim 3686926ce35aSJung-uk Kim if (bootverbose) 36872e883067SHenri Hennebert device_printf(dev, "rtsx_irq_res_id: %d, rtsx_mem_res_id: %d\n", 36882e883067SHenri Hennebert sc->rtsx_irq_res_id, sc->rtsx_mem_res_id); 3689926ce35aSJung-uk Kim 36902e883067SHenri Hennebert sc->rtsx_mem_btag = rman_get_bustag(sc->rtsx_mem_res); 36912e883067SHenri Hennebert sc->rtsx_mem_bhandle = rman_get_bushandle(sc->rtsx_mem_res); 3692926ce35aSJung-uk Kim 36939d3bc163SHenri Hennebert TIMEOUT_TASK_INIT(taskqueue_swi_giant, &sc->rtsx_card_insert_task, 0, 36949d3bc163SHenri Hennebert rtsx_card_task, sc); 36959d3bc163SHenri Hennebert TASK_INIT(&sc->rtsx_card_remove_task, 0, rtsx_card_task, sc); 36969d3bc163SHenri Hennebert 36979d3bc163SHenri Hennebert /* Allocate two DMA buffers: a command buffer and a data buffer. */ 36989d3bc163SHenri Hennebert error = rtsx_dma_alloc(sc); 36999d3bc163SHenri Hennebert if (error) 37009d3bc163SHenri Hennebert goto destroy_rtsx_irq_res; 37019d3bc163SHenri Hennebert 3702926ce35aSJung-uk Kim /* Activate the interrupt. */ 3703926ce35aSJung-uk Kim error = bus_setup_intr(dev, sc->rtsx_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 3704926ce35aSJung-uk Kim NULL, rtsx_intr, sc, &sc->rtsx_irq_cookie); 3705926ce35aSJung-uk Kim if (error) { 3706926ce35aSJung-uk Kim device_printf(dev, "Can't set up irq [0x%x]!\n", error); 37072e883067SHenri Hennebert goto destroy_rtsx_mem_res; 3708926ce35aSJung-uk Kim } 3709926ce35aSJung-uk Kim pci_enable_busmaster(dev); 3710926ce35aSJung-uk Kim 3711926ce35aSJung-uk Kim if (rtsx_read_cfg(sc, 0, RTSX_SDIOCFG_REG, &sdio_cfg) == 0) { 3712926ce35aSJung-uk Kim if ((sdio_cfg & RTSX_SDIOCFG_SDIO_ONLY) || 3713926ce35aSJung-uk Kim (sdio_cfg & RTSX_SDIOCFG_HAVE_SDIO)) 3714926ce35aSJung-uk Kim sc->rtsx_flags |= RTSX_F_SDIO_SUPPORT; 3715926ce35aSJung-uk Kim } 3716926ce35aSJung-uk Kim 3717926ce35aSJung-uk Kim #ifdef MMCCAM 3718926ce35aSJung-uk Kim sc->rtsx_ccb = NULL; 3719926ce35aSJung-uk Kim sc->rtsx_cam_status = 0; 3720926ce35aSJung-uk Kim 3721926ce35aSJung-uk Kim SYSCTL_ADD_U8(ctx, tree, OID_AUTO, "cam_status", CTLFLAG_RD, 3722926ce35aSJung-uk Kim &sc->rtsx_cam_status, 0, "driver cam card present"); 37238e9740b6SHenri Hennebert 37248e9740b6SHenri Hennebert if (mmc_cam_sim_alloc(dev, "rtsx_mmc", &sc->rtsx_mmc_sim) != 0) { 3725926ce35aSJung-uk Kim device_printf(dev, "Can't allocate CAM SIM\n"); 3726926ce35aSJung-uk Kim goto destroy_rtsx_irq; 3727926ce35aSJung-uk Kim } 3728926ce35aSJung-uk Kim #endif /* MMCCAM */ 3729926ce35aSJung-uk Kim 3730926ce35aSJung-uk Kim /* Initialize device. */ 37319b261d2eSHenri Hennebert error = rtsx_init(sc); 37329b261d2eSHenri Hennebert if (error) { 37339b261d2eSHenri Hennebert device_printf(dev, "Error %d during rtsx_init()\n", error); 3734926ce35aSJung-uk Kim goto destroy_rtsx_irq; 3735926ce35aSJung-uk Kim } 3736926ce35aSJung-uk Kim 3737926ce35aSJung-uk Kim /* 3738926ce35aSJung-uk Kim * Schedule a card detection as we won't get an interrupt 37399d3bc163SHenri Hennebert * if the card is inserted when we attach. We wait a quarter 37409d3bc163SHenri Hennebert * of a second to allow for a "spontaneous" interrupt which may 37419d3bc163SHenri Hennebert * change the card presence state. This delay avoid a panic 37429d3bc163SHenri Hennebert * on some configuration (e.g. Lenovo T540p). 3743926ce35aSJung-uk Kim */ 37449d3bc163SHenri Hennebert DELAY(250000); 3745926ce35aSJung-uk Kim if (rtsx_is_card_present(sc)) 37469d3bc163SHenri Hennebert device_printf(sc->rtsx_dev, "A card is detected\n"); 3747926ce35aSJung-uk Kim else 37489d3bc163SHenri Hennebert device_printf(sc->rtsx_dev, "No card is detected\n"); 3749926ce35aSJung-uk Kim rtsx_card_task(sc, 0); 3750926ce35aSJung-uk Kim 3751926ce35aSJung-uk Kim if (bootverbose) 3752926ce35aSJung-uk Kim device_printf(dev, "Device attached\n"); 3753926ce35aSJung-uk Kim 3754926ce35aSJung-uk Kim return (0); 3755926ce35aSJung-uk Kim 3756926ce35aSJung-uk Kim destroy_rtsx_irq: 3757926ce35aSJung-uk Kim bus_teardown_intr(dev, sc->rtsx_irq_res, sc->rtsx_irq_cookie); 37582e883067SHenri Hennebert destroy_rtsx_mem_res: 37592e883067SHenri Hennebert bus_release_resource(dev, SYS_RES_MEMORY, sc->rtsx_mem_res_id, 37602e883067SHenri Hennebert sc->rtsx_mem_res); 37619d3bc163SHenri Hennebert rtsx_dma_free(sc); 3762926ce35aSJung-uk Kim destroy_rtsx_irq_res: 3763926ce35aSJung-uk Kim callout_drain(&sc->rtsx_timeout_callout); 3764926ce35aSJung-uk Kim bus_release_resource(dev, SYS_RES_IRQ, sc->rtsx_irq_res_id, 3765926ce35aSJung-uk Kim sc->rtsx_irq_res); 3766926ce35aSJung-uk Kim pci_release_msi(dev); 3767926ce35aSJung-uk Kim RTSX_LOCK_DESTROY(sc); 3768926ce35aSJung-uk Kim 3769926ce35aSJung-uk Kim return (ENXIO); 3770926ce35aSJung-uk Kim } 3771926ce35aSJung-uk Kim 3772926ce35aSJung-uk Kim static int 3773926ce35aSJung-uk Kim rtsx_detach(device_t dev) 3774926ce35aSJung-uk Kim { 3775926ce35aSJung-uk Kim struct rtsx_softc *sc = device_get_softc(dev); 3776926ce35aSJung-uk Kim int error; 3777926ce35aSJung-uk Kim 3778926ce35aSJung-uk Kim if (bootverbose) 3779926ce35aSJung-uk Kim device_printf(dev, "Detach - Vendor ID: 0x%x - Device ID: 0x%x\n", 37802e883067SHenri Hennebert pci_get_vendor(dev), sc->rtsx_device_id); 3781926ce35aSJung-uk Kim 3782926ce35aSJung-uk Kim /* Disable interrupts. */ 3783926ce35aSJung-uk Kim sc->rtsx_intr_enabled = 0; 3784926ce35aSJung-uk Kim WRITE4(sc, RTSX_BIER, sc->rtsx_intr_enabled); 3785926ce35aSJung-uk Kim 3786926ce35aSJung-uk Kim /* Stop device. */ 3787*3ddaf820SJohn Baldwin error = bus_generic_detach(sc->rtsx_dev); 3788926ce35aSJung-uk Kim if (error) 3789926ce35aSJung-uk Kim return (error); 3790*3ddaf820SJohn Baldwin sc->rtsx_mmc_dev = NULL; 3791926ce35aSJung-uk Kim 3792926ce35aSJung-uk Kim taskqueue_drain_timeout(taskqueue_swi_giant, &sc->rtsx_card_insert_task); 3793926ce35aSJung-uk Kim taskqueue_drain(taskqueue_swi_giant, &sc->rtsx_card_remove_task); 3794926ce35aSJung-uk Kim 3795926ce35aSJung-uk Kim /* Teardown the state in our softc created in our attach routine. */ 3796926ce35aSJung-uk Kim rtsx_dma_free(sc); 37972e883067SHenri Hennebert if (sc->rtsx_mem_res != NULL) 37982e883067SHenri Hennebert bus_release_resource(dev, SYS_RES_MEMORY, sc->rtsx_mem_res_id, 37992e883067SHenri Hennebert sc->rtsx_mem_res); 3800926ce35aSJung-uk Kim if (sc->rtsx_irq_cookie != NULL) 3801926ce35aSJung-uk Kim bus_teardown_intr(dev, sc->rtsx_irq_res, sc->rtsx_irq_cookie); 3802926ce35aSJung-uk Kim if (sc->rtsx_irq_res != NULL) { 3803926ce35aSJung-uk Kim callout_drain(&sc->rtsx_timeout_callout); 3804926ce35aSJung-uk Kim bus_release_resource(dev, SYS_RES_IRQ, sc->rtsx_irq_res_id, 3805926ce35aSJung-uk Kim sc->rtsx_irq_res); 3806926ce35aSJung-uk Kim pci_release_msi(dev); 3807926ce35aSJung-uk Kim } 3808926ce35aSJung-uk Kim RTSX_LOCK_DESTROY(sc); 3809926ce35aSJung-uk Kim #ifdef MMCCAM 38108e9740b6SHenri Hennebert mmc_cam_sim_free(&sc->rtsx_mmc_sim); 3811926ce35aSJung-uk Kim #endif /* MMCCAM */ 3812926ce35aSJung-uk Kim 3813926ce35aSJung-uk Kim return (0); 3814926ce35aSJung-uk Kim } 3815926ce35aSJung-uk Kim 3816926ce35aSJung-uk Kim static int 3817926ce35aSJung-uk Kim rtsx_shutdown(device_t dev) 3818926ce35aSJung-uk Kim { 3819926ce35aSJung-uk Kim if (bootverbose) 3820926ce35aSJung-uk Kim device_printf(dev, "Shutdown\n"); 3821926ce35aSJung-uk Kim 3822926ce35aSJung-uk Kim return (0); 3823926ce35aSJung-uk Kim } 3824926ce35aSJung-uk Kim 3825926ce35aSJung-uk Kim /* 3826926ce35aSJung-uk Kim * Device suspend routine. 3827926ce35aSJung-uk Kim */ 3828926ce35aSJung-uk Kim static int 3829926ce35aSJung-uk Kim rtsx_suspend(device_t dev) 3830926ce35aSJung-uk Kim { 3831926ce35aSJung-uk Kim struct rtsx_softc *sc = device_get_softc(dev); 3832926ce35aSJung-uk Kim 3833926ce35aSJung-uk Kim device_printf(dev, "Suspend\n"); 3834926ce35aSJung-uk Kim 3835926ce35aSJung-uk Kim #ifdef MMCCAM 3836926ce35aSJung-uk Kim if (sc->rtsx_ccb != NULL) { 3837926ce35aSJung-uk Kim device_printf(dev, "Request in progress: CMD%u, rtsr_intr_status: 0x%08x\n", 3838926ce35aSJung-uk Kim sc->rtsx_ccb->mmcio.cmd.opcode, sc->rtsx_intr_status); 3839926ce35aSJung-uk Kim } 38409d3bc163SHenri Hennebert #else /* !MMCCAM */ 3841926ce35aSJung-uk Kim if (sc->rtsx_req != NULL) { 3842926ce35aSJung-uk Kim device_printf(dev, "Request in progress: CMD%u, rtsr_intr_status: 0x%08x\n", 3843926ce35aSJung-uk Kim sc->rtsx_req->cmd->opcode, sc->rtsx_intr_status); 3844926ce35aSJung-uk Kim } 3845926ce35aSJung-uk Kim #endif /* MMCCAM */ 3846926ce35aSJung-uk Kim 3847926ce35aSJung-uk Kim bus_generic_suspend(dev); 3848926ce35aSJung-uk Kim 3849926ce35aSJung-uk Kim return (0); 3850926ce35aSJung-uk Kim } 3851926ce35aSJung-uk Kim 3852926ce35aSJung-uk Kim /* 3853926ce35aSJung-uk Kim * Device resume routine. 3854926ce35aSJung-uk Kim */ 3855926ce35aSJung-uk Kim static int 3856926ce35aSJung-uk Kim rtsx_resume(device_t dev) 3857926ce35aSJung-uk Kim { 3858926ce35aSJung-uk Kim device_printf(dev, "Resume\n"); 3859926ce35aSJung-uk Kim 38601b1bab00Shlh-restart rtsx_init(device_get_softc(dev)); 38611b1bab00Shlh-restart 3862926ce35aSJung-uk Kim bus_generic_resume(dev); 3863926ce35aSJung-uk Kim 3864926ce35aSJung-uk Kim return (0); 3865926ce35aSJung-uk Kim } 3866926ce35aSJung-uk Kim 3867926ce35aSJung-uk Kim static device_method_t rtsx_methods[] = { 3868926ce35aSJung-uk Kim /* Device interface */ 3869926ce35aSJung-uk Kim DEVMETHOD(device_probe, rtsx_probe), 3870926ce35aSJung-uk Kim DEVMETHOD(device_attach, rtsx_attach), 3871926ce35aSJung-uk Kim DEVMETHOD(device_detach, rtsx_detach), 3872926ce35aSJung-uk Kim DEVMETHOD(device_shutdown, rtsx_shutdown), 3873926ce35aSJung-uk Kim DEVMETHOD(device_suspend, rtsx_suspend), 3874926ce35aSJung-uk Kim DEVMETHOD(device_resume, rtsx_resume), 3875926ce35aSJung-uk Kim 3876926ce35aSJung-uk Kim /* Bus interface */ 3877926ce35aSJung-uk Kim DEVMETHOD(bus_read_ivar, rtsx_read_ivar), 3878926ce35aSJung-uk Kim DEVMETHOD(bus_write_ivar, rtsx_write_ivar), 3879926ce35aSJung-uk Kim 38808e9740b6SHenri Hennebert #ifndef MMCCAM 3881926ce35aSJung-uk Kim /* MMC bridge interface */ 3882926ce35aSJung-uk Kim DEVMETHOD(mmcbr_update_ios, rtsx_mmcbr_update_ios), 3883926ce35aSJung-uk Kim DEVMETHOD(mmcbr_switch_vccq, rtsx_mmcbr_switch_vccq), 3884926ce35aSJung-uk Kim DEVMETHOD(mmcbr_tune, rtsx_mmcbr_tune), 3885926ce35aSJung-uk Kim DEVMETHOD(mmcbr_retune, rtsx_mmcbr_retune), 3886926ce35aSJung-uk Kim DEVMETHOD(mmcbr_request, rtsx_mmcbr_request), 3887926ce35aSJung-uk Kim DEVMETHOD(mmcbr_get_ro, rtsx_mmcbr_get_ro), 3888926ce35aSJung-uk Kim DEVMETHOD(mmcbr_acquire_host, rtsx_mmcbr_acquire_host), 3889926ce35aSJung-uk Kim DEVMETHOD(mmcbr_release_host, rtsx_mmcbr_release_host), 38908e9740b6SHenri Hennebert #endif /* !MMCCAM */ 38918e9740b6SHenri Hennebert 38928e9740b6SHenri Hennebert #ifdef MMCCAM 38938e9740b6SHenri Hennebert /* MMCCAM interface */ 38948e9740b6SHenri Hennebert DEVMETHOD(mmc_sim_get_tran_settings, rtsx_get_tran_settings), 38958e9740b6SHenri Hennebert DEVMETHOD(mmc_sim_set_tran_settings, rtsx_set_tran_settings), 38968e9740b6SHenri Hennebert DEVMETHOD(mmc_sim_cam_request, rtsx_cam_request), 38978e9740b6SHenri Hennebert #endif /* MMCCAM */ 3898926ce35aSJung-uk Kim 3899926ce35aSJung-uk Kim DEVMETHOD_END 3900926ce35aSJung-uk Kim }; 3901926ce35aSJung-uk Kim 3902926ce35aSJung-uk Kim DEFINE_CLASS_0(rtsx, rtsx_driver, rtsx_methods, sizeof(struct rtsx_softc)); 390303cfce6fSJohn Baldwin DRIVER_MODULE(rtsx, pci, rtsx_driver, NULL, NULL); 390471883128SHenri Hennebert 390571883128SHenri Hennebert /* For Plug and Play */ 390671883128SHenri Hennebert MODULE_PNP_INFO("U16:device;D:#;T:vendor=0x10ec", pci, rtsx, 390771883128SHenri Hennebert rtsx_ids, nitems(rtsx_ids)); 390871883128SHenri Hennebert 3909926ce35aSJung-uk Kim #ifndef MMCCAM 3910926ce35aSJung-uk Kim MMC_DECLARE_BRIDGE(rtsx); 39118e9740b6SHenri Hennebert #endif /* !MMCCAM */ 3912