From owner-svn-src-head@freebsd.org Thu Aug 23 17:50:43 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D35881093936; Thu, 23 Aug 2018 17:50:42 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 869AE7CAF8; Thu, 23 Aug 2018 17:50:42 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 692FA2558D; Thu, 23 Aug 2018 17:50:42 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w7NHog3E052750; Thu, 23 Aug 2018 17:50:42 GMT (envelope-from marius@FreeBSD.org) Received: (from marius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w7NHogAT052749; Thu, 23 Aug 2018 17:50:42 GMT (envelope-from marius@FreeBSD.org) Message-Id: <201808231750.w7NHogAT052749@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: marius set sender to marius@FreeBSD.org using -f From: Marius Strobl Date: Thu, 23 Aug 2018 17:50:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r338261 - head/sys/dev/sdhci X-SVN-Group: head X-SVN-Commit-Author: marius X-SVN-Commit-Paths: head/sys/dev/sdhci X-SVN-Commit-Revision: 338261 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Aug 2018 17:50:43 -0000 Author: marius Date: Thu Aug 23 17:50:41 2018 New Revision: 338261 URL: https://svnweb.freebsd.org/changeset/base/338261 Log: - According to section 2.2.5 of the SDHCI specification version 4.20, SDHCI_TRNS_ACMD12 is to be set only for multiple-block read/write commands without data length information, so don't unconditionally set this bit. The result matches what e. g. Linux does. - Section 2.2.19 of the SDHCI specification version 4.20 states that SDHCI_ACMD12_ERR should be only valid if SDHCI_INT_ACMD12ERR is set and hardware may clear SDHCI_ACMD12_ERR when SDHCI_INT_ACMD12ERR is cleared (differing silicon behavior is specifically allowed, though). Thus, read SDHCI_ACMD12_ERR before clearing SDHCI_INT_ACMD12ERR. While at it, use the 16-bit accessor rather than the 32-bit one for reading the 16-bit SDHCI_ACMD12_ERR. - SDHCI_INT_TUNEERR isn't one of the ROC bits in SDHCI_INT_STATUS so clear it explicitly. - Add missing prototypes and sort them. Modified: head/sys/dev/sdhci/sdhci.c Modified: head/sys/dev/sdhci/sdhci.c ============================================================================== --- head/sys/dev/sdhci/sdhci.c Thu Aug 23 17:41:39 2018 (r338260) +++ head/sys/dev/sdhci/sdhci.c Thu Aug 23 17:50:41 2018 (r338261) @@ -90,27 +90,49 @@ SYSCTL_INT(_hw_sdhci, OID_AUTO, quirk_set, CTLFLAG_RWT #define WR_MULTI_4(slot, off, ptr, count) \ SDHCI_WRITE_MULTI_4((slot)->bus, (slot), (off), (ptr), (count)) +static void sdhci_acmd_irq(struct sdhci_slot *slot, uint16_t acmd_err); static void sdhci_card_poll(void *arg); static void sdhci_card_task(void *arg, int pending); +static void sdhci_cmd_irq(struct sdhci_slot *slot, uint32_t intmask); +static void sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask); static int sdhci_exec_tuning(struct sdhci_slot *slot, bool reset); +static void sdhci_handle_card_present_locked(struct sdhci_slot *slot, + bool is_present); +static void sdhci_finish_command(struct sdhci_slot *slot); +static void sdhci_init(struct sdhci_slot *slot); +static void sdhci_read_block_pio(struct sdhci_slot *slot); +static void sdhci_req_done(struct sdhci_slot *slot); static void sdhci_req_wakeup(struct mmc_request *req); +static void sdhci_reset(struct sdhci_slot *slot, uint8_t mask); static void sdhci_retune(void *arg); static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock); +static void sdhci_set_power(struct sdhci_slot *slot, u_char power); +static void sdhci_set_transfer_mode(struct sdhci_slot *slot, + struct mmc_data *data); static void sdhci_start(struct sdhci_slot *slot); +static void sdhci_timeout(void *arg); +static void sdhci_start_command(struct sdhci_slot *slot, + struct mmc_command *cmd); static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data); +static void sdhci_write_block_pio(struct sdhci_slot *slot); +static void sdhci_transfer_pio(struct sdhci_slot *slot); #ifdef MMCCAM /* CAM-related */ -int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock); -static int sdhci_cam_update_ios(struct sdhci_slot *slot); -static int sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb); static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb); +static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, + int proposed_clock); +static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb); static void sdhci_cam_poll(struct cam_sim *sim); +static int sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb); static int sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb); +static int sdhci_cam_update_ios(struct sdhci_slot *slot); #endif /* helper routines */ static void sdhci_dumpregs(struct sdhci_slot *slot); +static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, + int error); static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...) __printflike(2, 3); static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot); @@ -1547,20 +1569,20 @@ sdhci_set_transfer_mode(struct sdhci_slot *slot, struc return; mode = SDHCI_TRNS_BLK_CNT_EN; - if (data->len > 512) + if (data->len > 512) { mode |= SDHCI_TRNS_MULTI; - if (data->flags & MMC_DATA_READ) - mode |= SDHCI_TRNS_READ; + if (__predict_true( #ifdef MMCCAM - struct ccb_mmcio *mmcio; - mmcio = &slot->ccb->mmcio; - if (mmcio->stop.opcode == MMC_STOP_TRANSMISSION - && !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP)) - mode |= SDHCI_TRNS_ACMD12; + slot->ccb->mmcio.stop.opcode == MMC_STOP_TRANSMISSION && #else - if (slot->req->stop && !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP)) - mode |= SDHCI_TRNS_ACMD12; + slot->req->stop && #endif + !(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP))) + mode |= SDHCI_TRNS_ACMD12; + + } + if (data->flags & MMC_DATA_READ) + mode |= SDHCI_TRNS_READ; if (slot->flags & SDHCI_USE_DMA) mode |= SDHCI_TRNS_DMA; @@ -2143,18 +2165,16 @@ done: } static void -sdhci_acmd_irq(struct sdhci_slot *slot) +sdhci_acmd_irq(struct sdhci_slot *slot, uint16_t acmd_err) { - uint16_t err; - err = RD4(slot, SDHCI_ACMD12_ERR); if (!slot->curcmd) { slot_printf(slot, "Got AutoCMD12 error 0x%04x, but " - "there is no active command.\n", err); + "there is no active command.\n", acmd_err); sdhci_dumpregs(slot); return; } - slot_printf(slot, "Got AutoCMD12 error 0x%04x\n", err); + slot_printf(slot, "Got AutoCMD12 error 0x%04x\n", acmd_err); sdhci_reset(slot, SDHCI_RESET_CMD); } @@ -2162,6 +2182,7 @@ void sdhci_generic_intr(struct sdhci_slot *slot) { uint32_t intmask, present; + uint16_t val16; SDHCI_LOCK(slot); /* Read slot interrupt status. */ @@ -2175,6 +2196,7 @@ sdhci_generic_intr(struct sdhci_slot *slot) /* Handle tuning error interrupt. */ if (__predict_false(intmask & SDHCI_INT_TUNEERR)) { + WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_TUNEERR); slot_printf(slot, "Tuning error indicated\n"); slot->retune_req |= SDHCI_RETUNE_REQ_RESET; if (slot->curcmd) { @@ -2212,8 +2234,10 @@ sdhci_generic_intr(struct sdhci_slot *slot) } /* Handle AutoCMD12 error interrupt. */ if (intmask & SDHCI_INT_ACMD12ERR) { + /* Clearing SDHCI_INT_ACMD12ERR may clear SDHCI_ACMD12_ERR. */ + val16 = RD2(slot, SDHCI_ACMD12_ERR); WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_ACMD12ERR); - sdhci_acmd_irq(slot); + sdhci_acmd_irq(slot, val16); } /* Handle bus power interrupt. */ if (intmask & SDHCI_INT_BUS_POWER) { @@ -2559,7 +2583,9 @@ sdhci_cam_poll(struct cam_sim *sim) return; } -int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) { +static int +sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock) +{ int max_clock, clock, i; if (proposed_clock == 0)