mmcsd.c revision 184034
1163516Simp/*- 2163516Simp * Copyright (c) 2006 Bernd Walter. All rights reserved. 3163516Simp * Copyright (c) 2006 M. Warner Losh. All rights reserved. 4163516Simp * 5163516Simp * Redistribution and use in source and binary forms, with or without 6163516Simp * modification, are permitted provided that the following conditions 7163516Simp * are met: 8163516Simp * 1. Redistributions of source code must retain the above copyright 9163516Simp * notice, this list of conditions and the following disclaimer. 10163516Simp * 2. Redistributions in binary form must reproduce the above copyright 11163516Simp * notice, this list of conditions and the following disclaimer in the 12163516Simp * documentation and/or other materials provided with the distribution. 13163516Simp * 14163516Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15163516Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16163516Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17163516Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18163516Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19163516Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20163516Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21163516Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22163516Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23163516Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24170002Simp * 25170002Simp * Portions of this software may have been developed with reference to 26170002Simp * the SD Simplified Specification. The following disclaimer may apply: 27170002Simp * 28170002Simp * The following conditions apply to the release of the simplified 29170002Simp * specification ("Simplified Specification") by the SD Card Association and 30170002Simp * the SD Group. The Simplified Specification is a subset of the complete SD 31170002Simp * Specification which is owned by the SD Card Association and the SD 32170002Simp * Group. This Simplified Specification is provided on a non-confidential 33170002Simp * basis subject to the disclaimers below. Any implementation of the 34170002Simp * Simplified Specification may require a license from the SD Card 35170002Simp * Association, SD Group, SD-3C LLC or other third parties. 36170002Simp * 37170002Simp * Disclaimers: 38170002Simp * 39170002Simp * The information contained in the Simplified Specification is presented only 40170002Simp * as a standard specification for SD Cards and SD Host/Ancillary products and 41170002Simp * is provided "AS-IS" without any representations or warranties of any 42170002Simp * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD 43170002Simp * Card Association for any damages, any infringements of patents or other 44170002Simp * right of the SD Group, SD-3C LLC, the SD Card Association or any third 45170002Simp * parties, which may result from its use. No license is granted by 46170002Simp * implication, estoppel or otherwise under any patent or other rights of the 47170002Simp * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing 48170002Simp * herein shall be construed as an obligation by the SD Group, the SD-3C LLC 49170002Simp * or the SD Card Association to disclose or distribute any technical 50170002Simp * information, know-how or other confidential information to any third party. 51163516Simp */ 52163516Simp 53163516Simp#include <sys/cdefs.h> 54163516Simp__FBSDID("$FreeBSD: head/sys/dev/mmc/mmcsd.c 184034 2008-10-18 22:22:25Z mav $"); 55163516Simp 56163516Simp#include <sys/param.h> 57163516Simp#include <sys/systm.h> 58163516Simp#include <sys/bio.h> 59163516Simp#include <sys/bus.h> 60163516Simp#include <sys/conf.h> 61163516Simp#include <sys/kernel.h> 62163516Simp#include <sys/kthread.h> 63163516Simp#include <sys/lock.h> 64163516Simp#include <sys/malloc.h> 65163516Simp#include <sys/module.h> 66163516Simp#include <sys/mutex.h> 67163516Simp#include <geom/geom_disk.h> 68163516Simp 69163516Simp#include <dev/mmc/mmcvar.h> 70163516Simp#include <dev/mmc/mmcreg.h> 71163516Simp 72163516Simp#include "mmcbus_if.h" 73163516Simp 74163516Simpstruct mmcsd_softc { 75163516Simp device_t dev; 76163516Simp struct mtx sc_mtx; 77163516Simp struct disk *disk; 78163516Simp struct proc *p; 79163516Simp struct bio_queue_head bio_queue; 80184034Smav daddr_t eblock, eend; /* Range remaining after the last erase. */ 81169567Simp int running; 82163516Simp}; 83163516Simp 84183480Simp#define MULTI_BLOCK_BROKEN 85163516Simp 86163516Simp/* bus entry points */ 87163516Simpstatic int mmcsd_probe(device_t dev); 88163516Simpstatic int mmcsd_attach(device_t dev); 89163516Simpstatic int mmcsd_detach(device_t dev); 90163516Simp 91163516Simp/* disk routines */ 92163516Simpstatic int mmcsd_open(struct disk *dp); 93163516Simpstatic int mmcsd_close(struct disk *dp); 94163516Simpstatic void mmcsd_strategy(struct bio *bp); 95163516Simpstatic void mmcsd_task(void *arg); 96163516Simp 97183774Simpstatic const char *mmcsd_card_name(device_t dev); 98183774Simpstatic int mmcsd_bus_bit_width(device_t dev); 99183774Simp 100163516Simp#define MMCSD_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 101163516Simp#define MMCSD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 102163516Simp#define MMCSD_LOCK_INIT(_sc) \ 103163516Simp mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ 104163516Simp "mmcsd", MTX_DEF) 105163516Simp#define MMCSD_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 106163516Simp#define MMCSD_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 107163516Simp#define MMCSD_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 108163516Simp 109163516Simpstatic int 110163516Simpmmcsd_probe(device_t dev) 111163516Simp{ 112163516Simp 113183704Smav device_quiet(dev); 114183480Simp device_set_desc(dev, "MMC/SD Memory Card"); 115163516Simp return (0); 116163516Simp} 117163516Simp 118163516Simpstatic int 119163516Simpmmcsd_attach(device_t dev) 120163516Simp{ 121163516Simp struct mmcsd_softc *sc; 122183774Simp struct disk *d; 123183774Simp intmax_t mb; 124183774Simp char unit; 125163516Simp 126163516Simp sc = device_get_softc(dev); 127163516Simp sc->dev = dev; 128163516Simp MMCSD_LOCK_INIT(sc); 129163516Simp 130183774Simp d = sc->disk = disk_alloc(); 131183774Simp d->d_open = mmcsd_open; 132183774Simp d->d_close = mmcsd_close; 133183774Simp d->d_strategy = mmcsd_strategy; 134183774Simp // d->d_dump = mmcsd_dump; Need polling mmc layer 135183774Simp d->d_name = "mmcsd"; 136183774Simp d->d_drv1 = sc; 137184033Smav d->d_maxsize = 4*1024*1024; /* Maximum defined SD card AU size. */ 138183774Simp d->d_sectorsize = mmc_get_sector_size(dev); 139183774Simp d->d_mediasize = mmc_get_media_size(dev) * d->d_sectorsize; 140183774Simp d->d_unit = device_get_unit(dev); 141184033Smav d->d_flags = DISKFLAG_CANDELETE; 142183774Simp /* 143183774Simp * Display in most natural units. There's no cards < 1MB. 144183774Simp * The SD standard goes to 2GiB, but the data format supports 145183774Simp * up to 4GiB and some card makers push it up to this limit. 146183774Simp * The SDHC standard only goes to 32GiB (the data format in 147183774Simp * SDHC is good to 2TiB however, which isn't too ugly at 148183774Simp * 2048GiBm, so we note it in passing here and don't add the 149183774Simp * code to print TiB). 150183774Simp */ 151183774Simp mb = d->d_mediasize >> 20; /* 1MiB == 1 << 20 */ 152183774Simp unit = 'M'; 153183805Smav if (mb >= 10240) { /* 1GiB = 1024 MiB */ 154183774Simp unit = 'G'; 155183774Simp mb /= 1024; 156183774Simp } 157183774Simp device_printf(dev, "%ju%cB <%s Memory Card>%s at %s %dMHz/%dbit\n", 158183774Simp mb, unit, mmcsd_card_name(dev), 159183774Simp mmc_get_read_only(dev) ? " (read-only)" : "", 160183774Simp device_get_nameunit(device_get_parent(dev)), 161183774Simp mmc_get_tran_speed(dev) / 1000000, mmcsd_bus_bit_width(dev)); 162183774Simp disk_create(d, DISK_VERSION); 163163516Simp bioq_init(&sc->bio_queue); 164169567Simp 165169567Simp sc->running = 1; 166184034Smav sc->eblock = sc->eend = 0; 167172836Sjulian kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card"); 168163516Simp 169163516Simp return (0); 170163516Simp} 171163516Simp 172163516Simpstatic int 173163516Simpmmcsd_detach(device_t dev) 174163516Simp{ 175169567Simp struct mmcsd_softc *sc = device_get_softc(dev); 176169567Simp 177169567Simp /* kill thread */ 178169567Simp MMCSD_LOCK(sc); 179169567Simp sc->running = 0; 180169567Simp wakeup(sc); 181169567Simp MMCSD_UNLOCK(sc); 182169567Simp 183169567Simp /* wait for thread to finish. XXX probably want timeout. -sorbo */ 184169567Simp MMCSD_LOCK(sc); 185169567Simp while (sc->running != -1) 186169567Simp msleep(sc, &sc->sc_mtx, PRIBIO, "detach", 0); 187169567Simp MMCSD_UNLOCK(sc); 188169567Simp 189169567Simp /* kill disk */ 190169567Simp disk_destroy(sc->disk); 191169567Simp /* XXX destroy anything in queue */ 192169567Simp 193169567Simp MMCSD_LOCK_DESTROY(sc); 194169567Simp 195183467Simp return (0); 196163516Simp} 197163516Simp 198163516Simpstatic int 199163516Simpmmcsd_open(struct disk *dp) 200163516Simp{ 201183467Simp return (0); 202163516Simp} 203163516Simp 204163516Simpstatic int 205163516Simpmmcsd_close(struct disk *dp) 206163516Simp{ 207183467Simp return (0); 208163516Simp} 209163516Simp 210163516Simpstatic void 211163516Simpmmcsd_strategy(struct bio *bp) 212163516Simp{ 213163516Simp struct mmcsd_softc *sc; 214163516Simp 215163516Simp sc = (struct mmcsd_softc *)bp->bio_disk->d_drv1; 216163516Simp MMCSD_LOCK(sc); 217163516Simp bioq_disksort(&sc->bio_queue, bp); 218163516Simp wakeup(sc); 219163516Simp MMCSD_UNLOCK(sc); 220163516Simp} 221163516Simp 222184033Smavstatic daddr_t 223184033Smavmmcsd_rw(struct mmcsd_softc *sc, struct bio *bp) 224184033Smav{ 225184033Smav daddr_t block, end; 226184033Smav struct mmc_command cmd; 227184033Smav struct mmc_command stop; 228184033Smav struct mmc_request req; 229184033Smav struct mmc_data data; 230184033Smav device_t dev = sc->dev; 231184033Smav int sz = sc->disk->d_sectorsize; 232184033Smav 233184033Smav block = bp->bio_pblkno; 234184033Smav end = bp->bio_pblkno + (bp->bio_bcount / sz); 235184033Smav while (block < end) { 236184033Smav char *vaddr = bp->bio_data + 237184033Smav (block - bp->bio_pblkno) * sz; 238184033Smav int numblocks; 239184033Smav#ifdef MULTI_BLOCK 240184033Smav numblocks = end - block; 241184033Smav#else 242184033Smav numblocks = 1; 243184033Smav#endif 244184033Smav memset(&req, 0, sizeof(req)); 245184033Smav memset(&cmd, 0, sizeof(cmd)); 246184033Smav memset(&stop, 0, sizeof(stop)); 247184033Smav req.cmd = &cmd; 248184033Smav cmd.data = &data; 249184033Smav if (bp->bio_cmd == BIO_READ) { 250184033Smav if (numblocks > 1) 251184033Smav cmd.opcode = MMC_READ_MULTIPLE_BLOCK; 252184033Smav else 253184033Smav cmd.opcode = MMC_READ_SINGLE_BLOCK; 254184033Smav } else { 255184033Smav if (numblocks > 1) 256184033Smav cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; 257184033Smav else 258184033Smav cmd.opcode = MMC_WRITE_BLOCK; 259184033Smav } 260184033Smav cmd.arg = block; 261184033Smav if (!mmc_get_high_cap(dev)) 262184033Smav cmd.arg <<= 9; 263184033Smav cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; 264184033Smav data.data = vaddr; 265184033Smav data.mrq = &req; 266184033Smav if (bp->bio_cmd == BIO_READ) 267184033Smav data.flags = MMC_DATA_READ; 268184033Smav else 269184033Smav data.flags = MMC_DATA_WRITE; 270184033Smav data.len = numblocks * sz; 271184033Smav if (numblocks > 1) { 272184033Smav data.flags |= MMC_DATA_MULTI; 273184033Smav stop.opcode = MMC_STOP_TRANSMISSION; 274184033Smav stop.arg = 0; 275184033Smav stop.flags = MMC_RSP_R1B | MMC_CMD_AC; 276184033Smav req.stop = &stop; 277184033Smav } 278184033Smav// printf("Len %d %lld-%lld flags %#x sz %d\n", 279184033Smav// (int)data.len, (long long)block, (long long)end, data.flags, sz); 280184033Smav MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, 281184033Smav &req); 282184033Smav if (req.cmd->error != MMC_ERR_NONE) 283184033Smav break; 284184033Smav block += numblocks; 285184033Smav } 286184033Smav return (block); 287184033Smav} 288184033Smav 289184033Smavstatic daddr_t 290184033Smavmmcsd_delete(struct mmcsd_softc *sc, struct bio *bp) 291184033Smav{ 292184033Smav daddr_t block, end, start, stop; 293184033Smav struct mmc_command cmd; 294184033Smav struct mmc_request req; 295184033Smav device_t dev = sc->dev; 296184033Smav int sz = sc->disk->d_sectorsize; 297184033Smav int erase_sector; 298184033Smav 299184033Smav block = bp->bio_pblkno; 300184033Smav end = bp->bio_pblkno + (bp->bio_bcount / sz); 301184034Smav /* Coalesce with part remaining from previous request. */ 302184034Smav if (block > sc->eblock && block <= sc->eend) 303184034Smav block = sc->eblock; 304184034Smav if (end >= sc->eblock && end < sc->eend) 305184034Smav end = sc->eend; 306184033Smav /* Safe round to the erase sector boundaries. */ 307184033Smav erase_sector = mmc_get_erase_sector(dev); 308184033Smav start = block + erase_sector - 1; /* Round up. */ 309184033Smav start -= start % erase_sector; 310184033Smav stop = end; /* Round down. */ 311184033Smav stop -= end % erase_sector; 312184034Smav /* We can't erase area smaller then sector, store it for later. */ 313184034Smav if (start >= stop) { 314184034Smav sc->eblock = block; 315184034Smav sc->eend = end; 316184033Smav return (end); 317184034Smav } 318184033Smav 319184033Smav /* Set erase start position. */ 320184033Smav memset(&req, 0, sizeof(req)); 321184033Smav memset(&cmd, 0, sizeof(cmd)); 322184033Smav req.cmd = &cmd; 323184033Smav if (mmc_get_card_type(dev) == mode_sd) 324184033Smav cmd.opcode = SD_ERASE_WR_BLK_START; 325184033Smav else 326184033Smav cmd.opcode = MMC_ERASE_GROUP_START; 327184033Smav cmd.arg = start; 328184033Smav if (!mmc_get_high_cap(dev)) 329184033Smav cmd.arg <<= 9; 330184033Smav cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 331184033Smav MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, 332184033Smav &req); 333184033Smav if (req.cmd->error != MMC_ERR_NONE) { 334184033Smav printf("erase err1: %d\n", req.cmd->error); 335184033Smav return (block); 336184033Smav } 337184033Smav /* Set erase stop position. */ 338184033Smav memset(&req, 0, sizeof(req)); 339184033Smav memset(&cmd, 0, sizeof(cmd)); 340184033Smav req.cmd = &cmd; 341184033Smav if (mmc_get_card_type(dev) == mode_sd) 342184033Smav cmd.opcode = SD_ERASE_WR_BLK_END; 343184033Smav else 344184033Smav cmd.opcode = MMC_ERASE_GROUP_END; 345184033Smav cmd.arg = stop; 346184033Smav if (!mmc_get_high_cap(dev)) 347184033Smav cmd.arg <<= 9; 348184033Smav cmd.arg--; 349184033Smav cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 350184033Smav MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, 351184033Smav &req); 352184033Smav if (req.cmd->error != MMC_ERR_NONE) { 353184033Smav printf("erase err2: %d\n", req.cmd->error); 354184033Smav return (block); 355184033Smav } 356184033Smav /* Erase range. */ 357184033Smav memset(&req, 0, sizeof(req)); 358184033Smav memset(&cmd, 0, sizeof(cmd)); 359184033Smav req.cmd = &cmd; 360184033Smav cmd.opcode = MMC_ERASE; 361184033Smav cmd.arg = 0; 362184033Smav cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; 363184033Smav MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, 364184033Smav &req); 365184033Smav if (req.cmd->error != MMC_ERR_NONE) { 366184033Smav printf("erase err3 %d\n", req.cmd->error); 367184033Smav return (block); 368184033Smav } 369184034Smav /* Store one of remaining parts for the next call. */ 370184034Smav if (bp->bio_pblkno >= sc->eblock || block == start) { 371184034Smav sc->eblock = stop; /* Predict next forward. */ 372184034Smav sc->eend = end; 373184034Smav } else { 374184034Smav sc->eblock = block; /* Predict next backward. */ 375184034Smav sc->eend = start; 376184034Smav } 377184033Smav return (end); 378184033Smav} 379184033Smav 380163516Simpstatic void 381163516Simpmmcsd_task(void *arg) 382163516Simp{ 383163516Simp struct mmcsd_softc *sc = (struct mmcsd_softc*)arg; 384163516Simp struct bio *bp; 385163516Simp int sz; 386163516Simp daddr_t block, end; 387163516Simp device_t dev; 388163516Simp 389163516Simp dev = sc->dev; 390169567Simp while (sc->running) { 391163516Simp MMCSD_LOCK(sc); 392163516Simp do { 393163516Simp bp = bioq_first(&sc->bio_queue); 394163516Simp if (bp == NULL) 395163516Simp msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0); 396169567Simp } while (bp == NULL && sc->running); 397169567Simp if (bp) 398169567Simp bioq_remove(&sc->bio_queue, bp); 399163516Simp MMCSD_UNLOCK(sc); 400169567Simp if (!sc->running) 401169567Simp break; 402183448Simp if (bp->bio_cmd != BIO_READ && mmc_get_read_only(dev)) { 403183448Simp bp->bio_error = EROFS; 404183448Simp bp->bio_resid = bp->bio_bcount; 405183448Simp bp->bio_flags |= BIO_ERROR; 406183448Simp biodone(bp); 407183448Simp continue; 408183448Simp } 409163516Simp MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev); 410163516Simp sz = sc->disk->d_sectorsize; 411184033Smav block = bp->bio_pblkno; 412163516Simp end = bp->bio_pblkno + (bp->bio_bcount / sz); 413184033Smav if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { 414184034Smav /* Access to the remaining erase block obsoletes it. */ 415184034Smav if (block < sc->eend && end > sc->eblock) 416184034Smav sc->eblock = sc->eend = 0; 417184033Smav block = mmcsd_rw(sc, bp); 418184033Smav } else if (bp->bio_cmd == BIO_DELETE) { 419184033Smav block = mmcsd_delete(sc, bp); 420163516Simp } 421163516Simp MMCBUS_RELEASE_BUS(device_get_parent(dev), dev); 422183480Simp if (block < end) { 423183480Simp bp->bio_error = EIO; 424183480Simp bp->bio_resid = (end - block) * sz; 425183480Simp bp->bio_flags |= BIO_ERROR; 426183480Simp } 427163516Simp biodone(bp); 428163516Simp } 429169567Simp 430169567Simp /* tell parent we're done */ 431169567Simp MMCSD_LOCK(sc); 432169567Simp sc->running = -1; 433169567Simp wakeup(sc); 434169567Simp MMCSD_UNLOCK(sc); 435169567Simp 436172836Sjulian kproc_exit(0); 437163516Simp} 438163516Simp 439183774Simpstatic const char * 440183774Simpmmcsd_card_name(device_t dev) 441183774Simp{ 442183774Simp if (mmc_get_card_type(dev) == mode_mmc) 443183774Simp return ("MMC"); 444183774Simp if (mmc_get_high_cap(dev)) 445183774Simp return ("SDHC"); 446183774Simp return ("SD"); 447183774Simp} 448183774Simp 449183774Simpstatic int 450183774Simpmmcsd_bus_bit_width(device_t dev) 451183774Simp{ 452183774Simp if (mmc_get_bus_width(dev) == bus_width_1) 453183774Simp return (1); 454183774Simp if (mmc_get_bus_width(dev) == bus_width_4) 455183774Simp return (4); 456183774Simp return (8); 457183774Simp} 458183774Simp 459163516Simpstatic device_method_t mmcsd_methods[] = { 460163516Simp DEVMETHOD(device_probe, mmcsd_probe), 461163516Simp DEVMETHOD(device_attach, mmcsd_attach), 462163516Simp DEVMETHOD(device_detach, mmcsd_detach), 463163516Simp {0, 0}, 464163516Simp}; 465163516Simp 466163516Simpstatic driver_t mmcsd_driver = { 467163516Simp "mmcsd", 468163516Simp mmcsd_methods, 469163516Simp sizeof(struct mmcsd_softc), 470163516Simp}; 471163516Simpstatic devclass_t mmcsd_devclass; 472163516Simp 473163516SimpDRIVER_MODULE(mmcsd, mmc, mmcsd_driver, mmcsd_devclass, 0, 0); 474