From a2199afea169c1e13881ca90a02a28e4c9ffd114 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 18 Mar 2014 08:09:55 +0100 Subject: usb, dfu: extract flush code into seperate function move the flushing code into an extra function dfu_flush(), so it can be used from other code. Signed-off-by: Heiko Schocher Cc: Lukasz Majewski Cc: Kyungmin Park Cc: Marek Vasut Cc: Pantelis Antoniou --- drivers/dfu/dfu.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 07011e99a8..1aced26c4e 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -126,6 +126,28 @@ static int dfu_write_buffer_drain(struct dfu_entity *dfu) return ret; } +int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) +{ + int ret = 0; + + if (dfu->flush_medium) + ret = dfu->flush_medium(dfu); + + printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc); + + /* clear everything */ + dfu_free_buf(); + dfu->crc = 0; + dfu->offset = 0; + dfu->i_blk_seq_num = 0; + dfu->i_buf_start = dfu_buf; + dfu->i_buf_end = dfu_buf; + dfu->i_buf = dfu->i_buf_start; + dfu->inited = 0; + + return ret; +} + int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) { int ret = 0; @@ -197,24 +219,8 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) } /* end? */ - if (size == 0) { - /* Now try and flush to the medium if needed. */ - if (dfu->flush_medium) - ret = dfu->flush_medium(dfu); - printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc); - - /* clear everything */ - dfu_free_buf(); - dfu->crc = 0; - dfu->offset = 0; - dfu->i_blk_seq_num = 0; - dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf; - dfu->i_buf = dfu->i_buf_start; - - dfu->inited = 0; - - } + if (size == 0) + ret = dfu_flush(dfu, buf, size, blk_seq_num); return ret = 0 ? size : ret; } -- cgit v1.2.1 From 001a8319866062cd63b7b62e5bb4b85eacfde4b4 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 18 Mar 2014 08:09:56 +0100 Subject: usb: dfu: introduce dfuMANIFEST state on nand flash using ubi, after the download of the new image into the flash, the "rest" of the nand sectors get erased while flushing the medium. With current u-boot version dfu-util may show: Starting download: [##################################################] finished! state(7) = dfuMANIFEST, status(0) = No error condition is present unable to read DFU status as get_status is not answered while erasing sectors, if erasing needs some time. So do the following changes to prevent this: - introduce dfuManifest state According to dfu specification ( http://www.usb.org/developers/devclass_docs/usbdfu10.pdf ) section 7: "the device enters the dfuMANIFEST-SYNC state and awaits the solicitation of the status report by the host. Upon receipt of the anticipated DFU_GETSTATUS, the device enters the dfuMANIFEST state, where it completes its reprogramming operations." - when stepping into dfuManifest state, sending a PollTimeout DFU_MANIFEST_POLL_TIMEOUT in ms, to the host, so the host (dfu-util) waits the PollTimeout before sending a get_status again. Signed-off-by: Heiko Schocher Cc: Lukasz Majewski Cc: Kyungmin Park Cc: Marek Vasut Cc: Pantelis Antoniou --- drivers/dfu/dfu.c | 4 ---- drivers/usb/gadget/f_dfu.c | 48 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 1aced26c4e..f94c412aa9 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -218,10 +218,6 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) ret = tret; } - /* end? */ - if (size == 0) - ret = dfu_flush(dfu, buf, size, blk_seq_num); - return ret = 0 ? size : ret; } diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index a045864d73..de75ff1339 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -164,9 +164,14 @@ static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf, req->length, f_dfu->blk_seq_num); +} - if (req->length == 0) - puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); +static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req) +{ + struct f_dfu *f_dfu = req->context; + + dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf, + req->length, f_dfu->blk_seq_num); } static void handle_getstatus(struct usb_request *req) @@ -174,19 +179,22 @@ static void handle_getstatus(struct usb_request *req) struct dfu_status *dstat = (struct dfu_status *)req->buf; struct f_dfu *f_dfu = req->context; + dfu_set_poll_timeout(dstat, 0); + switch (f_dfu->dfu_state) { case DFU_STATE_dfuDNLOAD_SYNC: case DFU_STATE_dfuDNBUSY: f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; break; case DFU_STATE_dfuMANIFEST_SYNC: + f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; break; + case DFU_STATE_dfuMANIFEST: + dfu_set_poll_timeout(dstat, DFU_MANIFEST_POLL_TIMEOUT); default: break; } - dfu_set_poll_timeout(dstat, 0); - if (f_dfu->poll_timeout) if (!(f_dfu->blk_seq_num % (dfu_get_buf_size() / DFU_USB_BUFSIZ))) @@ -446,10 +454,11 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu, switch (ctrl->bRequest) { case USB_REQ_DFU_GETSTATUS: /* We're MainfestationTolerant */ - f_dfu->dfu_state = DFU_STATE_dfuIDLE; + f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; handle_getstatus(req); f_dfu->blk_seq_num = 0; value = RET_STAT_LEN; + req->complete = dnload_request_flush; break; case USB_REQ_DFU_GETSTATE: handle_getstate(req); @@ -463,6 +472,33 @@ static int state_dfu_manifest_sync(struct f_dfu *f_dfu, return value; } +static int state_dfu_manifest(struct f_dfu *f_dfu, + const struct usb_ctrlrequest *ctrl, + struct usb_gadget *gadget, + struct usb_request *req) +{ + int value = 0; + + switch (ctrl->bRequest) { + case USB_REQ_DFU_GETSTATUS: + /* We're MainfestationTolerant */ + f_dfu->dfu_state = DFU_STATE_dfuIDLE; + handle_getstatus(req); + f_dfu->blk_seq_num = 0; + value = RET_STAT_LEN; + puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); + break; + case USB_REQ_DFU_GETSTATE: + handle_getstate(req); + break; + default: + f_dfu->dfu_state = DFU_STATE_dfuERROR; + value = RET_STALL; + break; + } + return value; +} + static int state_dfu_upload_idle(struct f_dfu *f_dfu, const struct usb_ctrlrequest *ctrl, struct usb_gadget *gadget, @@ -539,7 +575,7 @@ static dfu_state_fn dfu_state[] = { state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */ state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */ state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */ - NULL, /* DFU_STATE_dfuMANIFEST */ + state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */ NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */ state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */ state_dfu_error /* DFU_STATE_dfuERROR */ -- cgit v1.2.1 From 7d0b605abb1f2dbccf4abb502f3b1fc9f97f2552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Majewski?= Date: Fri, 21 Feb 2014 08:23:00 +0100 Subject: dfu: mmc: Replace calls to u-boot commands with native mmc API For some time we have been using the run_command() with properly crafted string. Such approach turned to be unreliable and error prone. Switch to "native" mmc subsystem API would allow better type checking and shall improve speed. Also, it seems that this API is changing less often than u-boot commands. The approach similar to env operations on the eMMC has been reused. Signed-off-by: Lukasz Majewski --- drivers/dfu/dfu_mmc.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 0816f46bad..651cfff5b3 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -12,6 +12,7 @@ #include #include #include +#include static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE) dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE]; @@ -20,8 +21,8 @@ static long dfu_file_buf_len; static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, u64 offset, void *buf, long *len) { - char cmd_buf[DFU_CMD_BUF_SIZE]; - u32 blk_start, blk_count; + struct mmc *mmc = find_mmc_device(dfu->dev_num); + u32 blk_start, blk_count, n = 0; /* * We must ensure that we work in lba_blk_size chunks, so ALIGN @@ -38,12 +39,28 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, return -EINVAL; } - sprintf(cmd_buf, "mmc %s %p %x %x", - op == DFU_OP_READ ? "read" : "write", - buf, blk_start, blk_count); + debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__, + op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num, + blk_start, blk_count, buf); + switch (op) { + case DFU_OP_READ: + n = mmc->block_dev.block_read(dfu->dev_num, blk_start, + blk_count, buf); + break; + case DFU_OP_WRITE: + n = mmc->block_dev.block_write(dfu->dev_num, blk_start, + blk_count, buf); + break; + default: + error("Operation not supported\n"); + } - debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); - return run_command(cmd_buf, 0); + if (n != blk_count) { + error("MMC operation failed"); + return -EIO; + } + + return 0; } static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len) -- cgit v1.2.1 From ab769f227f79bedae7840f99b6c0c4d66aafc78e Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Wed, 26 Feb 2014 19:28:45 +0200 Subject: mmc: Remove ops from struct mmc and put in mmc_ops Remove the in-structure ops and put them in mmc_ops with a constant pointer to it. This makes the mmc structure smaller as well as conserving code space (in theory). All in-tree drivers are converted as well; this is done in a single patch in order to not break git bisect. Changes since V1: Fix compilation b0rked issue on omap platforms where OMAP_GPIO was not set. Signed-off-by: Pantelis Antoniou --- drivers/mmc/arm_pl180_mmci.c | 12 +++--- drivers/mmc/bfin_sdh.c | 11 +++--- drivers/mmc/davinci_mmc.c | 13 ++++--- drivers/mmc/dw_mmc.c | 10 +++-- drivers/mmc/fsl_esdhc.c | 14 ++++--- drivers/mmc/ftsdc010_mci.c | 11 ++++-- drivers/mmc/gen_atmel_mci.c | 12 +++--- drivers/mmc/mmc.c | 21 ++++++----- drivers/mmc/mmc_spi.c | 12 +++--- drivers/mmc/mxcmmc.c | 12 +++--- drivers/mmc/mxsmmc.c | 12 +++--- drivers/mmc/omap_hsmmc.c | 89 ++++++++++++++++++++++++++++---------------- drivers/mmc/pxa_mmc_gen.c | 11 ++++-- drivers/mmc/sdhci.c | 13 ++++--- drivers/mmc/sh_mmcif.c | 12 +++--- drivers/mmc/tegra_mmc.c | 19 ++++++---- 16 files changed, 171 insertions(+), 113 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 5a55fe73b7..4490e9710b 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -335,6 +335,12 @@ static void host_set_ios(struct mmc *dev) udelay(CLK_CHANGE_DELAY); } +static const struct mmc_ops arm_pl180_mmci_ops = { + .send_cmd = host_request, + .set_ios = host_set_ios, + .init = mmc_host_reset, +}; + /* * mmc_host_init - initialize the mmc controller. * Set initial clock and power for mmc slot. @@ -360,11 +366,7 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host) sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; writel(sdi_u32, &host->base->mask0); strncpy(dev->name, host->name, sizeof(dev->name)); - dev->send_cmd = host_request; - dev->set_ios = host_set_ios; - dev->init = mmc_host_reset; - dev->getcd = NULL; - dev->getwp = NULL; + dev->ops = &arm_pl180_mmci_ops; dev->host_caps = host->caps; dev->voltages = host->voltages; dev->f_min = host->clock_min; diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index bd9b641135..f0871ece38 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -274,6 +274,11 @@ static int bfin_sdh_init(struct mmc *mmc) return 0; } +static const struct mmc_ops bfin_mmc_ops = { + .send_cmd = bfin_sdh_request, + .set_ios = bfin_sdh_set_ios, + .init = bfin_sdh_init, +}; int bfin_mmc_init(bd_t *bis) { @@ -284,11 +289,7 @@ int bfin_mmc_init(bd_t *bis) if (!mmc) return -ENOMEM; sprintf(mmc->name, "Blackfin SDH"); - mmc->send_cmd = bfin_sdh_request; - mmc->set_ios = bfin_sdh_set_ios; - mmc->init = bfin_sdh_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &bfin_mmc_ops; mmc->host_caps = MMC_MODE_4BIT; mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index b380961188..29ca4a6ed1 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -363,6 +363,12 @@ static void dmmc_set_ios(struct mmc *mmc) dmmc_set_clock(mmc, mmc->clock); } +static const struct mmc_ops dmmc_ops = { + .send_cmd = dmmc_send_cmd, + .set_ios = dmmc_set_ios, + .init = dmmc_init, +}; + /* Called from board_mmc_init during startup. Can be called multiple times * depending on the number of slots available on board and controller */ @@ -375,12 +381,7 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host) sprintf(mmc->name, "davinci"); mmc->priv = host; - mmc->send_cmd = dmmc_send_cmd; - mmc->set_ios = dmmc_set_ios; - mmc->init = dmmc_init; - mmc->getcd = NULL; - mmc->getwp = NULL; - + mmc->ops = &dmmc_ops; mmc->f_min = 200000; mmc->f_max = 25000000; mmc->voltages = host->voltages; diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index d45c15cfa4..2e6576e8dd 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -343,6 +343,12 @@ static int dwmci_init(struct mmc *mmc) return 0; } +static const struct mmc_ops dwmci_ops = { + .send_cmd = dwmci_send_cmd, + .set_ios = dwmci_set_ios, + .init = dwmci_init, +}; + int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) { struct mmc *mmc; @@ -358,9 +364,7 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) host->mmc = mmc; sprintf(mmc->name, "%s", host->name); - mmc->send_cmd = dwmci_send_cmd; - mmc->set_ios = dwmci_set_ios; - mmc->init = dwmci_init; + mmc->ops = &dwmci_ops; mmc->f_min = min_clk; mmc->f_max = max_clk; diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 7b146a3604..861f536ac9 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -524,6 +524,13 @@ static void esdhc_reset(struct fsl_esdhc *regs) printf("MMC/SD: Reset never completed.\n"); } +static const struct mmc_ops esdhc_ops = { + .send_cmd = esdhc_send_cmd, + .set_ios = esdhc_set_ios, + .init = esdhc_init, + .getcd = esdhc_getcd, +}; + int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) { struct fsl_esdhc *regs; @@ -548,12 +555,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) | SYSCTL_IPGEN | SYSCTL_CKEN); mmc->priv = cfg; - mmc->send_cmd = esdhc_send_cmd; - mmc->set_ios = esdhc_set_ios; - mmc->init = esdhc_init; - mmc->getcd = esdhc_getcd; - mmc->getwp = NULL; - + mmc->ops = &esdhc_ops; voltage_caps = 0; caps = regs->hostcapblt; diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index 7600d5ce55..ce43ae1b84 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -316,6 +316,12 @@ static int ftsdc010_init(struct mmc *mmc) return 0; } +static const struct mmc_ops ftsdc010_ops = { + .send_cmd = ftsdc010_request, + .set_ios = ftsdc010_set_ios, + .init = ftsdc010_init, +}; + int ftsdc010_mmc_init(int devid) { struct mmc *mmc; @@ -347,10 +353,7 @@ int ftsdc010_mmc_init(int devid) mmc->priv = chip; sprintf(mmc->name, "ftsdc010"); - mmc->send_cmd = ftsdc010_request; - mmc->set_ios = ftsdc010_set_ios; - mmc->init = ftsdc010_init; - + mmc->ops = &ftsdc010_ops; mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { case FTSDC010_BWR_CAPS_4BIT: diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index c11dcd0f97..456f8bfdd4 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -344,6 +344,12 @@ static int mci_init(struct mmc *mmc) return 0; } +static const struct mmc_ops atmel_mci_ops = { + .send_cmd = mci_send_cmd, + .set_ios = mci_set_ios, + .init = mci_init, +}; + /* * This is the only exported function * @@ -360,11 +366,7 @@ int atmel_mci_init(void *regs) strcpy(mmc->name, "mci"); mmc->priv = regs; - mmc->send_cmd = mci_send_cmd; - mmc->set_ios = mci_set_ios; - mmc->init = mci_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &atmel_mci_ops; /* need to be able to pass these in on a board by board basis */ mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 8ab0bc948f..ac07bb9a2a 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -37,8 +37,8 @@ int mmc_getwp(struct mmc *mmc) wp = board_mmc_getwp(mmc); if (wp < 0) { - if (mmc->getwp) - wp = mmc->getwp(mmc); + if (mmc->ops->getwp) + wp = mmc->ops->getwp(mmc); else wp = 0; } @@ -63,7 +63,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) printf("CMD_SEND:%d\n", cmd->cmdidx); printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg); - ret = mmc->send_cmd(mmc, cmd, data); + ret = mmc->ops->send_cmd(mmc, cmd, data); switch (cmd->resp_type) { case MMC_RSP_NONE: printf("\t\tMMC_RSP_NONE\n"); @@ -106,7 +106,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) break; } #else - ret = mmc->send_cmd(mmc, cmd, data); + ret = mmc->ops->send_cmd(mmc, cmd, data); #endif return ret; } @@ -578,8 +578,8 @@ int mmc_getcd(struct mmc *mmc) cd = board_mmc_getcd(mmc); if (cd < 0) { - if (mmc->getcd) - cd = mmc->getcd(mmc); + if (mmc->ops->getcd) + cd = mmc->ops->getcd(mmc); else cd = 1; } @@ -751,7 +751,8 @@ static const int multipliers[] = { static void mmc_set_ios(struct mmc *mmc) { - mmc->set_ios(mmc); + if (mmc->ops->set_ios) + mmc->ops->set_ios(mmc); } void mmc_set_clock(struct mmc *mmc, uint clock) @@ -1207,7 +1208,8 @@ int mmc_start_init(struct mmc *mmc) { int err; - if (mmc_getcd(mmc) == 0) { + /* we pretend there's no card when init is NULL */ + if (mmc_getcd(mmc) == 0 || mmc->ops->init == NULL) { mmc->has_init = 0; #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("MMC: no card present\n"); @@ -1218,7 +1220,8 @@ int mmc_start_init(struct mmc *mmc) if (mmc->has_init) return 0; - err = mmc->init(mmc); + /* made sure it's not NULL earlier */ + err = mmc->ops->init(mmc); if (err) return err; diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index fe6a5a166d..0a0f894bcb 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -255,6 +255,12 @@ static int mmc_spi_init_p(struct mmc *mmc) return 0; } +static const struct mmc_ops mmc_spi_ops = { + .send_cmd = mmc_spi_request, + .set_ios = mmc_spi_set_ios, + .init = mmc_spi_init_p, +}; + struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode) { struct mmc *mmc; @@ -269,11 +275,7 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode) return NULL; } sprintf(mmc->name, "MMC_SPI"); - mmc->send_cmd = mmc_spi_request; - mmc->set_ios = mmc_spi_set_ios; - mmc->init = mmc_spi_init_p; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &mmc_spi_ops; mmc->host_caps = MMC_MODE_SPI; mmc->voltages = MMC_SPI_VOLTAGE; diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c index 4f99617b9a..f3e1eed737 100644 --- a/drivers/mmc/mxcmmc.c +++ b/drivers/mmc/mxcmmc.c @@ -485,6 +485,12 @@ static int mxcmci_init(struct mmc *mmc) return 0; } +static const struct mmc_ops mxcmci_ops = { + .send_cmd = mxcmci_request, + .set_ios = mxcmci_set_ios, + .init = mxcmci_init, +}; + static int mxcmci_initialize(bd_t *bis) { struct mmc *mmc = NULL; @@ -495,11 +501,7 @@ static int mxcmci_initialize(bd_t *bis) return -ENOMEM; sprintf(mmc->name, "MXC MCI"); - mmc->send_cmd = mxcmci_request; - mmc->set_ios = mxcmci_set_ios; - mmc->init = mxcmci_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &mxcmci_ops; mmc->host_caps = MMC_MODE_4BIT; host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE; diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 245f9d0c67..97c9ee8fb6 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -363,6 +363,12 @@ static int mxsmmc_init(struct mmc *mmc) return 0; } +static const struct mmc_ops mxsmmc_ops = { + .send_cmd = mxsmmc_send_cmd, + .set_ios = mxsmmc_set_ios, + .init = mxsmmc_init, +}; + int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) { struct mmc *mmc = NULL; @@ -400,11 +406,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) priv->regs = mxs_ssp_regs_by_bus(id); sprintf(mmc->name, "MXS MMC"); - mmc->send_cmd = mxsmmc_send_cmd; - mmc->set_ios = mxsmmc_set_ios; - mmc->init = mxsmmc_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &mxsmmc_ops; mmc->priv = priv; mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index d3a8b5303d..6bf602fea5 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -35,14 +35,24 @@ #include #include +/* simplify defines to OMAP_HSMMC_USE_GPIO */ +#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \ + (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT)) +#define OMAP_HSMMC_USE_GPIO +#else +#undef OMAP_HSMMC_USE_GPIO +#endif + /* common definitions for all OMAPs */ #define SYSCTL_SRC (1 << 25) #define SYSCTL_SRD (1 << 26) struct omap_hsmmc_data { struct hsmmc *base_addr; +#ifdef OMAP_HSMMC_USE_GPIO int cd_gpio; int wp_gpio; +#endif }; /* If we fail after 1 second wait, something is really bad */ @@ -54,8 +64,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, static struct mmc hsmmc_dev[3]; static struct omap_hsmmc_data hsmmc_dev_data[3]; -#if (defined(CONFIG_OMAP_GPIO) && !defined(CONFIG_SPL_BUILD)) || \ - (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_GPIO_SUPPORT)) +#ifdef OMAP_HSMMC_USE_GPIO static int omap_mmc_setup_gpio_in(int gpio, const char *label) { if (!gpio_is_valid(gpio)) @@ -69,26 +78,6 @@ static int omap_mmc_setup_gpio_in(int gpio, const char *label) return gpio; } - -static int omap_mmc_getcd(struct mmc *mmc) -{ - int cd_gpio = ((struct omap_hsmmc_data *)mmc->priv)->cd_gpio; - return gpio_get_value(cd_gpio); -} - -static int omap_mmc_getwp(struct mmc *mmc) -{ - int wp_gpio = ((struct omap_hsmmc_data *)mmc->priv)->wp_gpio; - return gpio_get_value(wp_gpio); -} -#else -static inline int omap_mmc_setup_gpio_in(int gpio, const char *label) -{ - return -1; -} - -#define omap_mmc_getcd NULL -#define omap_mmc_getwp NULL #endif #if defined(CONFIG_OMAP44XX) && defined(CONFIG_TWL6030_POWER) @@ -213,7 +202,7 @@ void mmc_init_stream(struct hsmmc *mmc_base) } -static int mmc_init_setup(struct mmc *mmc) +static int omap_hsmmc_init_setup(struct mmc *mmc) { struct hsmmc *mmc_base; unsigned int reg_val; @@ -322,7 +311,7 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit) } } -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, +static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct hsmmc *mmc_base; @@ -552,7 +541,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, return 0; } -static void mmc_set_ios(struct mmc *mmc) +static void omap_hsmmc_set_ios(struct mmc *mmc) { struct hsmmc *mmc_base; unsigned int dsor = 0; @@ -606,6 +595,44 @@ static void mmc_set_ios(struct mmc *mmc) writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); } +#ifdef OMAP_HSMMC_USE_GPIO +static int omap_hsmmc_getcd(struct mmc *mmc) +{ + struct omap_hsmmc_data *priv_data = mmc->priv; + int cd_gpio; + + /* if no CD return as 1 */ + cd_gpio = priv_data->cd_gpio; + if (cd_gpio < 0) + return 1; + + return gpio_get_value(cd_gpio); +} + +static int omap_hsmmc_getwp(struct mmc *mmc) +{ + struct omap_hsmmc_data *priv_data = mmc->priv; + int wp_gpio; + + /* if no WP return as 0 */ + wp_gpio = priv_data->wp_gpio; + if (wp_gpio < 0) + return 0; + + return gpio_get_value(wp_gpio); +} +#endif + +static const struct mmc_ops omap_hsmmc_ops = { + .send_cmd = omap_hsmmc_send_cmd, + .set_ios = omap_hsmmc_set_ios, + .init = omap_hsmmc_init_setup, +#ifdef OMAP_HSMMC_USE_GPIO + .getcd = omap_hsmmc_getcd, + .getwp = omap_hsmmc_getwp, +#endif +}; + int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, int wp_gpio) { @@ -615,9 +642,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, MMC_MODE_HC; sprintf(mmc->name, "OMAP SD/MMC"); - mmc->send_cmd = mmc_send_cmd; - mmc->set_ios = mmc_set_ios; - mmc->init = mmc_init_setup; + mmc->ops = &omap_hsmmc_ops; mmc->priv = priv_data; switch (dev_index) { @@ -647,13 +672,11 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE; return 1; } +#ifdef OMAP_HSMMC_USE_GPIO + /* on error gpio values are set to -1, which is what we want */ priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd"); - if (priv_data->cd_gpio != -1) - mmc->getcd = omap_mmc_getcd; - priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp"); - if (priv_data->wp_gpio != -1) - mmc->getwp = omap_mmc_getwp; +#endif mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; mmc->host_caps = host_caps_val & ~host_caps_mask; diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c index 29f3eaf30b..4694c8f42d 100644 --- a/drivers/mmc/pxa_mmc_gen.c +++ b/drivers/mmc/pxa_mmc_gen.c @@ -366,6 +366,12 @@ static int pxa_mmc_init(struct mmc *mmc) return 0; } +static const struct mmc_ops pxa_mmc_ops = { + .send_cmd = pxa_mmc_request, + .set_ios = pxa_mmc_set_ios, + .init = pxa_mmc_init, +}; + int pxa_mmc_register(int card_index) { struct mmc *mmc; @@ -397,10 +403,7 @@ int pxa_mmc_register(int card_index) mmc->priv = priv; sprintf(mmc->name, "PXA MMC"); - mmc->send_cmd = pxa_mmc_request; - mmc->set_ios = pxa_mmc_set_ios; - mmc->init = pxa_mmc_init; - mmc->getcd = NULL; + mmc->ops = &pxa_mmc_ops; mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->f_max = PXAMMC_MAX_SPEED; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 1e86b92bee..c3425a6ce5 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -430,6 +430,13 @@ int sdhci_init(struct mmc *mmc) return 0; } + +static const struct mmc_ops sdhci_ops = { + .send_cmd = sdhci_send_command, + .set_ios = sdhci_set_ios, + .init = sdhci_init, +}; + int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) { struct mmc *mmc; @@ -445,11 +452,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) host->mmc = mmc; sprintf(mmc->name, "%s", host->name); - mmc->send_cmd = sdhci_send_command; - mmc->set_ios = sdhci_set_ios; - mmc->init = sdhci_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &sdhci_ops; caps = sdhci_readl(host, SDHCI_CAPABILITIES); #ifdef CONFIG_MMC_SDMA diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 011d4f3e63..6a4860bb35 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -574,6 +574,12 @@ static int sh_mmcif_init(struct mmc *mmc) return 0; } +static const struct mmc_ops sh_mmcif_ops = { + .send_cmd = sh_mmcif_request, + .set_ios = sh_mmcif_set_ios, + .init = sh_mmcif_init, +}; + int mmcif_mmc_init(void) { int ret = 0; @@ -595,11 +601,7 @@ int mmcif_mmc_init(void) mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; memcpy(mmc->name, DRIVER_NAME, sizeof(DRIVER_NAME)); - mmc->send_cmd = sh_mmcif_request; - mmc->set_ios = sh_mmcif_set_ios; - mmc->init = sh_mmcif_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc->ops = &sh_mmcif_ops; host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR; host->clk = CONFIG_SH_MMCIF_CLK; mmc->priv = host; diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 3d1ce1263c..5f7b590b8f 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -314,7 +314,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, return 0; } -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, +static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { void *buf; @@ -396,7 +396,7 @@ out: host->clock = clock; } -static void mmc_set_ios(struct mmc *mmc) +static void tegra_mmc_set_ios(struct mmc *mmc) { struct mmc_host *host = mmc->priv; unsigned char ctrl; @@ -464,7 +464,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc) pad_init_mmc(host); } -static int mmc_core_init(struct mmc *mmc) +static int tegra_mmc_core_init(struct mmc *mmc) { struct mmc_host *host = (struct mmc_host *)mmc->priv; unsigned int mask; @@ -521,6 +521,13 @@ int tegra_mmc_getcd(struct mmc *mmc) return 1; } +static const struct mmc_ops tegra_mmc_ops = { + .send_cmd = tegra_mmc_send_cmd, + .set_ios = tegra_mmc_set_ios, + .init = tegra_mmc_core_init, + .getcd = tegra_mmc_getcd, +}; + static int do_mmc_init(int dev_index) { struct mmc_host *host; @@ -558,11 +565,7 @@ static int do_mmc_init(int dev_index) sprintf(mmc->name, "Tegra SD/MMC"); mmc->priv = host; - mmc->send_cmd = mmc_send_cmd; - mmc->set_ios = mmc_set_ios; - mmc->init = mmc_core_init; - mmc->getcd = tegra_mmc_getcd; - mmc->getwp = NULL; + mmc->ops = &tegra_mmc_ops; mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; mmc->host_caps = 0; -- cgit v1.2.1 From 22cb7d334e296288e53057467dfee26858275516 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Mon, 10 Mar 2014 20:05:51 +0200 Subject: mmc: Convert mmc struct's name array to a pointer Using an array is pointless; even more pointless (and scary) is using sprintf to fill it without a format string. Signed-off-by: Pantelis Antoniou --- drivers/mmc/arm_pl180_mmci.c | 2 +- drivers/mmc/bfin_sdh.c | 2 +- drivers/mmc/davinci_mmc.c | 2 +- drivers/mmc/dw_mmc.c | 2 +- drivers/mmc/fsl_esdhc.c | 2 +- drivers/mmc/ftsdc010_mci.c | 2 +- drivers/mmc/gen_atmel_mci.c | 2 +- drivers/mmc/mmc_spi.c | 2 +- drivers/mmc/mxcmmc.c | 2 +- drivers/mmc/mxsmmc.c | 2 +- drivers/mmc/omap_hsmmc.c | 2 +- drivers/mmc/pxa_mmc_gen.c | 2 +- drivers/mmc/sdhci.c | 2 +- drivers/mmc/sh_mmcif.c | 2 +- drivers/mmc/tegra_mmc.c | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 4490e9710b..5a30590673 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -365,7 +365,7 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host) /* Disable mmc interrupts */ sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; writel(sdi_u32, &host->base->mask0); - strncpy(dev->name, host->name, sizeof(dev->name)); + dev->name = host->name; dev->ops = &arm_pl180_mmci_ops; dev->host_caps = host->caps; dev->voltages = host->voltages; diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index f0871ece38..5f6145b0c7 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -288,7 +288,7 @@ int bfin_mmc_init(bd_t *bis) if (!mmc) return -ENOMEM; - sprintf(mmc->name, "Blackfin SDH"); + mmc->name = "Blackfin SDH"; mmc->ops = &bfin_mmc_ops; mmc->host_caps = MMC_MODE_4BIT; diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index 29ca4a6ed1..cae972a20f 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -379,7 +379,7 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host) mmc = malloc(sizeof(struct mmc)); memset(mmc, 0, sizeof(struct mmc)); - sprintf(mmc->name, "davinci"); + mmc->name = "davinci"; mmc->priv = host; mmc->ops = &dmmc_ops; mmc->f_min = 200000; diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 2e6576e8dd..011efb14a9 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -363,7 +363,7 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) mmc->priv = host; host->mmc = mmc; - sprintf(mmc->name, "%s", host->name); + mmc->name = host->name; mmc->ops = &dwmci_ops; mmc->f_min = min_clk; mmc->f_max = max_clk; diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 861f536ac9..f66513ed16 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -545,7 +545,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) return -ENOMEM; memset(mmc, 0, sizeof(struct mmc)); - sprintf(mmc->name, "FSL_SDHC"); + mmc->name = "FSL_SDHC"; regs = (struct fsl_esdhc *)cfg->esdhc_base; /* First reset the eSDHC controller */ diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index ce43ae1b84..b1673fc917 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -352,7 +352,7 @@ int ftsdc010_mmc_init(int devid) chip->regs = regs; mmc->priv = chip; - sprintf(mmc->name, "ftsdc010"); + mmc->name = "ftsdc010"; mmc->ops = &ftsdc010_ops; mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 456f8bfdd4..ce799f38ee 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -364,7 +364,7 @@ int atmel_mci_init(void *regs) if (!mmc) return -1; - strcpy(mmc->name, "mci"); + mmc->name = "mci"; mmc->priv = regs; mmc->ops = &atmel_mci_ops; diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index 0a0f894bcb..e94de37c8b 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -274,7 +274,7 @@ struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode) free(mmc); return NULL; } - sprintf(mmc->name, "MMC_SPI"); + mmc->name = "MMC_SPI"; mmc->ops = &mmc_spi_ops; mmc->host_caps = MMC_MODE_SPI; diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c index f3e1eed737..3357559981 100644 --- a/drivers/mmc/mxcmmc.c +++ b/drivers/mmc/mxcmmc.c @@ -500,7 +500,7 @@ static int mxcmci_initialize(bd_t *bis) if (!mmc) return -ENOMEM; - sprintf(mmc->name, "MXC MCI"); + mmc->name = "MXC MCI"; mmc->ops = &mxcmci_ops; mmc->host_caps = MMC_MODE_4BIT; diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 97c9ee8fb6..3512a99de9 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -405,7 +405,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) priv->id = id; priv->regs = mxs_ssp_regs_by_bus(id); - sprintf(mmc->name, "MXS MMC"); + mmc->name = "MXS MMC"; mmc->ops = &mxsmmc_ops; mmc->priv = priv; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 6bf602fea5..fecac5698b 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -641,7 +641,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; - sprintf(mmc->name, "OMAP SD/MMC"); + mmc->name = "OMAP SD/MMC"; mmc->ops = &omap_hsmmc_ops; mmc->priv = priv_data; diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c index 4694c8f42d..188e1d4c6b 100644 --- a/drivers/mmc/pxa_mmc_gen.c +++ b/drivers/mmc/pxa_mmc_gen.c @@ -402,7 +402,7 @@ int pxa_mmc_register(int card_index) mmc->priv = priv; - sprintf(mmc->name, "PXA MMC"); + mmc->name = "PXA MMC"; mmc->ops = &pxa_mmc_ops; mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index c3425a6ce5..dc6f4e4972 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -451,7 +451,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) mmc->priv = host; host->mmc = mmc; - sprintf(mmc->name, "%s", host->name); + mmc->name = host->name; mmc->ops = &sdhci_ops; caps = sdhci_readl(host, SDHCI_CAPABILITIES); diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 6a4860bb35..008617d5e6 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -600,7 +600,7 @@ int mmcif_mmc_init(void) mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; - memcpy(mmc->name, DRIVER_NAME, sizeof(DRIVER_NAME)); + mmc->name = DRIVER_NAME; mmc->ops = &sh_mmcif_ops; host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR; host->clk = CONFIG_SH_MMCIF_CLK; diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 5f7b590b8f..e8fbb63f29 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -563,7 +563,7 @@ static int do_mmc_init(int dev_index) mmc = &mmc_dev[dev_index]; - sprintf(mmc->name, "Tegra SD/MMC"); + mmc->name = "Tegra SD/MMC"; mmc->priv = host; mmc->ops = &tegra_mmc_ops; -- cgit v1.2.1 From 93bfd6167713a5cc1a78bcf60fa63f990fd3f4b3 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Tue, 11 Mar 2014 19:34:20 +0200 Subject: mmc: Split mmc struct, rework mmc initialization (v2) The way that struct mmc was implemented was a bit of a mess; configuration and internal state all jumbled up in a single structure. On top of that the way initialization is done with mmc_register leads to a lot of duplicated code in drivers. Typically the initialization got something like this in every driver. struct mmc *mmc = malloc(sizeof(struct mmc)); memset(mmc, 0, sizeof(struct mmc); /* fill in fields of mmc struct */ /* store private data pointer */ mmc_register(mmc); By using the new mmc_create call one just passes an mmc config struct and an optional private data pointer like this: struct mmc = mmc_create(&cfg, priv); All in tree drivers have been updated to the new form, and expect mmc_register to go away before long. Changes since v1: * Use calloc instead of manually calling memset. * Mark mmc_register as deprecated. Signed-off-by: Pantelis Antoniou --- drivers/mmc/arm_pl180_mmci.c | 40 +++++++++--------- drivers/mmc/arm_pl180_mmci.h | 4 ++ drivers/mmc/bfin_sdh.c | 31 +++++++------- drivers/mmc/davinci_mmc.c | 30 ++++++-------- drivers/mmc/dw_mmc.c | 50 ++++++++++------------ drivers/mmc/fsl_esdhc.c | 55 ++++++++++++------------- drivers/mmc/ftsdc010_mci.c | 54 ++++++++++-------------- drivers/mmc/gen_atmel_mci.c | 43 +++++++++++-------- drivers/mmc/mmc.c | 98 ++++++++++++++++++++++++++++---------------- drivers/mmc/mmc_spi.c | 40 +++++++++--------- drivers/mmc/mmc_write.c | 3 +- drivers/mmc/mxcmmc.c | 35 +++++++--------- drivers/mmc/mxsmmc.c | 38 ++++++++--------- drivers/mmc/omap_hsmmc.c | 55 ++++++++++++++----------- drivers/mmc/pxa_mmc_gen.c | 61 +++++++++++++-------------- drivers/mmc/sdhci.c | 73 ++++++++++++++++----------------- drivers/mmc/sh_mmcif.c | 42 +++++++++---------- drivers/mmc/tegra_mmc.c | 36 ++++++++-------- 18 files changed, 403 insertions(+), 385 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 5a30590673..5ef7ff7ff2 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -287,9 +287,9 @@ static void host_set_ios(struct mmc *dev) u32 clkdiv = 0; u32 tmp_clock; - if (dev->clock >= dev->f_max) { + if (dev->clock >= dev->cfg->f_max) { clkdiv = 0; - dev->clock = dev->f_max; + dev->clock = dev->cfg->f_max; } else { clkdiv = (host->clock_in / dev->clock) - 2; } @@ -348,16 +348,9 @@ static const struct mmc_ops arm_pl180_mmci_ops = { */ int arm_pl180_mmci_init(struct pl180_mmc_host *host) { - struct mmc *dev; + struct mmc *mmc; u32 sdi_u32; - dev = malloc(sizeof(struct mmc)); - if (!dev) - return -ENOMEM; - - memset(dev, 0, sizeof(struct mmc)); - dev->priv = host; - writel(host->pwr_init, &host->base->power); writel(host->clkdiv_init, &host->base->clock); udelay(CLK_CHANGE_DELAY); @@ -365,15 +358,24 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host) /* Disable mmc interrupts */ sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; writel(sdi_u32, &host->base->mask0); - dev->name = host->name; - dev->ops = &arm_pl180_mmci_ops; - dev->host_caps = host->caps; - dev->voltages = host->voltages; - dev->f_min = host->clock_min; - dev->f_max = host->clock_max; - dev->b_max = host->b_max; - mmc_register(dev); - debug("registered mmc interface number is:%d\n", dev->block_dev.dev); + + host->cfg.name = host->name; + host->cfg.ops = &arm_pl180_mmci_ops; + /* TODO remove the duplicates */ + host->cfg.host_caps = host->caps; + host->cfg.voltages = host->voltages; + host->cfg.f_min = host->clock_min; + host->cfg.f_max = host->clock_max; + if (host->b_max != 0) + host->cfg.b_max = host->b_max; + else + host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + mmc = mmc_create(&host->cfg, host); + if (mmc == NULL) + return -1; + + debug("registered mmc interface number is:%d\n", mmc->block_dev.dev); return 0; } diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h index 72344498d6..f23bd391ee 100644 --- a/drivers/mmc/arm_pl180_mmci.h +++ b/drivers/mmc/arm_pl180_mmci.h @@ -13,6 +13,9 @@ #ifndef __ARM_PL180_MMCI_H__ #define __ARM_PL180_MMCI_H__ +/* need definition of struct mmc_config */ +#include + #define COMMAND_REG_DELAY 300 #define DATA_REG_DELAY 1000 #define CLK_CHANGE_DELAY 2000 @@ -184,6 +187,7 @@ struct pl180_mmc_host { unsigned int clkdiv_init; unsigned int pwr_init; int version2; + struct mmc_config cfg; }; int arm_pl180_mmci_init(struct pl180_mmc_host *); diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index 5f6145b0c7..7b35d8e7d9 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -238,7 +238,7 @@ static void bfin_sdh_set_ios(struct mmc *mmc) u16 cfg = 0; u16 clk_ctl = 0; - if (mmc->bus_width == 4) { + if (mmc_bus_width(mmc) == 4) { cfg = bfin_read_SDH_CFG(); #ifndef RSI_BLKSZ cfg &= ~PD_SDDAT3; @@ -280,25 +280,24 @@ static const struct mmc_ops bfin_mmc_ops = { .init = bfin_sdh_init, }; +static struct mmc_config bfin_mmc_cfg = { + .name = "Blackfin SDH", + .ops = &bfin_mmc_ops, + .host_caps = MMC_MODE_4BIT, + .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, +}; + int bfin_mmc_init(bd_t *bis) { - struct mmc *mmc = NULL; - - mmc = malloc(sizeof(struct mmc)); - - if (!mmc) - return -ENOMEM; - mmc->name = "Blackfin SDH"; - mmc->ops = &bfin_mmc_ops; - mmc->host_caps = MMC_MODE_4BIT; - - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->f_max = get_sclk(); - mmc->f_min = mmc->f_max >> 9; + struct mmc *mmc; - mmc->b_max = 0; + bfin_mmc_cfg.f_max = get_sclk(); + bfin_mmc_cfg.f_min = bfin_mmc_cfg.f_max >> 9; - mmc_register(mmc); + mmc = mmc_create(&bfin_mmc_cfg, NULL); + if (mmc == NULL) + return -1; return 0; } diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index cae972a20f..aae00e9dab 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -30,10 +30,10 @@ static void dmmc_set_clock(struct mmc *mmc, uint clock) struct davinci_mmc_regs *regs = host->reg_base; uint clkrt, sysclk2, act_clock; - if (clock < mmc->f_min) - clock = mmc->f_min; - if (clock > mmc->f_max) - clock = mmc->f_max; + if (clock < mmc->cfg->f_min) + clock = mmc->cfg->f_min; + if (clock > mmc->cfg->f_max) + clock = mmc->cfg->f_max; set_val(®s->mmcclk, 0); sysclk2 = host->input_clk; @@ -374,22 +374,16 @@ static const struct mmc_ops dmmc_ops = { */ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host) { - struct mmc *mmc; + host->cfg.name = "davinci"; + host->cfg.ops = &dmmc_ops; + host->cfg.f_min = 200000; + host->cfg.f_max = 25000000; + host->cfg.voltages = host->voltages; + host->cfg.host_caps = host->host_caps; - mmc = malloc(sizeof(struct mmc)); - memset(mmc, 0, sizeof(struct mmc)); + host->cfg.b_max = DAVINCI_MAX_BLOCKS; - mmc->name = "davinci"; - mmc->priv = host; - mmc->ops = &dmmc_ops; - mmc->f_min = 200000; - mmc->f_max = 25000000; - mmc->voltages = host->voltages; - mmc->host_caps = host->host_caps; - - mmc->b_max = DAVINCI_MAX_BLOCKS; - - mmc_register(mmc); + mmc_create(&host->cfg, host); return 0; } diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 011efb14a9..eb4e2be514 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -107,7 +107,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host, static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - struct dwmci_host *host = (struct dwmci_host *)mmc->priv; + struct dwmci_host *host = mmc->priv; ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data ? DIV_ROUND_UP(data->blocks, 8) : 0); int flags = 0, i; @@ -284,7 +284,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) static void dwmci_set_ios(struct mmc *mmc) { - struct dwmci_host *host = (struct dwmci_host *)mmc->priv; + struct dwmci_host *host = mmc->priv; u32 ctype; debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock); @@ -310,7 +310,7 @@ static void dwmci_set_ios(struct mmc *mmc) static int dwmci_init(struct mmc *mmc) { - struct dwmci_host *host = (struct dwmci_host *)mmc->priv; + struct dwmci_host *host = mmc->priv; if (host->board_init) host->board_init(host); @@ -323,7 +323,7 @@ static int dwmci_init(struct mmc *mmc) } /* Enumerate at 400KHz */ - dwmci_setup_bus(host, mmc->f_min); + dwmci_setup_bus(host, mmc->cfg->f_min); dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF); dwmci_writel(host, DWMCI_INTMASK, 0); @@ -351,37 +351,29 @@ static const struct mmc_ops dwmci_ops = { int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) { - struct mmc *mmc; - int err = 0; + host->cfg.name = host->name; + host->cfg.ops = &dwmci_ops; + host->cfg.f_min = min_clk; + host->cfg.f_max = max_clk; - mmc = calloc(sizeof(struct mmc), 1); - if (!mmc) { - printf("mmc calloc fail!\n"); - return -1; - } - - mmc->priv = host; - host->mmc = mmc; - - mmc->name = host->name; - mmc->ops = &dwmci_ops; - mmc->f_min = min_clk; - mmc->f_max = max_clk; + host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - - mmc->host_caps = host->caps; + host->cfg.host_caps = host->caps; if (host->buswidth == 8) { - mmc->host_caps |= MMC_MODE_8BIT; - mmc->host_caps &= ~MMC_MODE_4BIT; + host->cfg.host_caps |= MMC_MODE_8BIT; + host->cfg.host_caps &= ~MMC_MODE_4BIT; } else { - mmc->host_caps |= MMC_MODE_4BIT; - mmc->host_caps &= ~MMC_MODE_8BIT; + host->cfg.host_caps |= MMC_MODE_4BIT; + host->cfg.host_caps &= ~MMC_MODE_8BIT; } - mmc->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC; + host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC; + + host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - err = mmc_register(mmc); + host->mmc = mmc_create(&host->cfg, host); + if (host->mmc == NULL) + return -1; - return err; + return 0; } diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index f66513ed16..d64962652c 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -172,7 +172,7 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data) static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) { int timeout; - struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO uint wml_value; @@ -267,7 +267,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { uint xfertyp; uint irqstat; - struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + struct fsl_esdhc_cfg *cfg = mmc->priv; volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 @@ -406,13 +406,13 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) static void set_sysctl(struct mmc *mmc, uint clock) { int div, pre_div; - struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + struct fsl_esdhc_cfg *cfg = mmc->priv; volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; int sdhc_clk = cfg->sdhc_clk; uint clk; - if (clock < mmc->f_min) - clock = mmc->f_min; + if (clock < mmc->cfg->f_min) + clock = mmc->cfg->f_min; if (sdhc_clk / 16 > clock) { for (pre_div = 2; pre_div < 256; pre_div *= 2) @@ -443,7 +443,7 @@ static void set_sysctl(struct mmc *mmc, uint clock) static void esdhc_set_ios(struct mmc *mmc) { - struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; /* Set the clock speed */ @@ -461,7 +461,7 @@ static void esdhc_set_ios(struct mmc *mmc) static int esdhc_init(struct mmc *mmc) { - struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; int timeout = 1000; @@ -496,7 +496,7 @@ static int esdhc_init(struct mmc *mmc) static int esdhc_getcd(struct mmc *mmc) { - struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; int timeout = 1000; @@ -540,12 +540,6 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) if (!cfg) return -1; - mmc = malloc(sizeof(struct mmc)); - if (!mmc) - return -ENOMEM; - - memset(mmc, 0, sizeof(struct mmc)); - mmc->name = "FSL_SDHC"; regs = (struct fsl_esdhc *)cfg->esdhc_base; /* First reset the eSDHC controller */ @@ -554,8 +548,8 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN | SYSCTL_IPGEN | SYSCTL_CKEN); - mmc->priv = cfg; - mmc->ops = &esdhc_ops; + memset(&cfg->cfg, 0, sizeof(cfg->cfg)); + voltage_caps = 0; caps = regs->hostcapblt; @@ -576,38 +570,43 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) if (caps & ESDHC_HOSTCAPBLT_VS33) voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34; + cfg->cfg.name = "FSL_SDHC"; + cfg->cfg.ops = &esdhc_ops; #ifdef CONFIG_SYS_SD_VOLTAGE - mmc->voltages = CONFIG_SYS_SD_VOLTAGE; + cfg->cfg.voltages = CONFIG_SYS_SD_VOLTAGE; #else - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + cfg->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; #endif - if ((mmc->voltages & voltage_caps) == 0) { + if ((cfg->cfg.voltages & voltage_caps) == 0) { printf("voltage not supported by controller\n"); return -1; } - mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; + cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; if (cfg->max_bus_width > 0) { if (cfg->max_bus_width < 8) - mmc->host_caps &= ~MMC_MODE_8BIT; + cfg->cfg.host_caps &= ~MMC_MODE_8BIT; if (cfg->max_bus_width < 4) - mmc->host_caps &= ~MMC_MODE_4BIT; + cfg->cfg.host_caps &= ~MMC_MODE_4BIT; } if (caps & ESDHC_HOSTCAPBLT_HSS) - mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + cfg->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK) - mmc->host_caps &= ~MMC_MODE_8BIT; + cfg->cfg.host_caps &= ~MMC_MODE_8BIT; #endif - mmc->f_min = 400000; - mmc->f_max = MIN(gd->arch.sdhc_clk, 52000000); + cfg->cfg.f_min = 400000; + cfg->cfg.f_max = MIN(gd->arch.sdhc_clk, 52000000); - mmc->b_max = 0; - mmc_register(mmc); + cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + mmc = mmc_create(&cfg->cfg, cfg); + if (mmc == NULL) + return -1; return 0; } diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index b1673fc917..a620678e5f 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -27,6 +27,7 @@ struct ftsdc010_chip { uint32_t sclk; /* FTSDC010 source clock in Hz */ uint32_t fifo; /* fifo depth in bytes */ uint32_t acmd; + struct mmc_config cfg; /* mmc configuration */ }; static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) @@ -123,14 +124,6 @@ static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate) } } -static inline int ftsdc010_is_ro(struct mmc *mmc) -{ - struct ftsdc010_chip *chip = mmc->priv; - const uint8_t *csd = (const uint8_t *)mmc->csd; - - return chip->wprot || (csd[1] & 0x30); -} - static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask) { int ret = TIMEOUT; @@ -337,47 +330,44 @@ int ftsdc010_mmc_init(int devid) regs = (void __iomem *)(CONFIG_FTSDC010_BASE + (devid << 20)); #endif - mmc = malloc(sizeof(struct mmc)); - if (!mmc) - return -ENOMEM; - memset(mmc, 0, sizeof(struct mmc)); - chip = malloc(sizeof(struct ftsdc010_chip)); - if (!chip) { - free(mmc); + if (!chip) return -ENOMEM; - } memset(chip, 0, sizeof(struct ftsdc010_chip)); chip->regs = regs; - mmc->priv = chip; +#ifdef CONFIG_SYS_CLK_FREQ + chip->sclk = CONFIG_SYS_CLK_FREQ; +#else + chip->sclk = clk_get_rate("SDC"); +#endif - mmc->name = "ftsdc010"; - mmc->ops = &ftsdc010_ops; - mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; + chip->cfg.name = "ftsdc010"; + chip->cfg.ops = &ftsdc010_ops; + chip->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; switch (readl(®s->bwr) & FTSDC010_BWR_CAPS_MASK) { case FTSDC010_BWR_CAPS_4BIT: - mmc->host_caps |= MMC_MODE_4BIT; + chip->cfg.host_caps |= MMC_MODE_4BIT; break; case FTSDC010_BWR_CAPS_8BIT: - mmc->host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; + chip->cfg.host_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; break; default: break; } -#ifdef CONFIG_SYS_CLK_FREQ - chip->sclk = CONFIG_SYS_CLK_FREQ; -#else - chip->sclk = clk_get_rate("SDC"); -#endif + chip->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + chip->cfg.f_max = chip->sclk / 2; + chip->cfg.f_min = chip->sclk / 0x100; - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->f_max = chip->sclk / 2; - mmc->f_min = chip->sclk / 0x100; - mmc->block_dev.part_type = PART_TYPE_DOS; + chip->cfg.part_type = PART_TYPE_DOS; + chip->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - mmc_register(mmc); + mmc = mmc_create(&chip->cfg, chip); + if (mmc == NULL) { + free(chip); + return -ENOMEM; + } return 0; } diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index ce799f38ee..acca0269e5 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -55,7 +55,7 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) /* Setup for MCI Clock and Block Size */ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) { - atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + atmel_mci_t *mci = mmc->priv; u32 bus_hz = get_mci_clk_rate(); u32 clkdiv = 255; @@ -165,7 +165,7 @@ io_fail: static int mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + atmel_mci_t *mci = mmc->priv; u32 cmdr; u32 error_flags = 0; u32 status; @@ -289,7 +289,7 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Entered into mmc structure during driver init */ static void mci_set_ios(struct mmc *mmc) { - atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + atmel_mci_t *mci = mmc->priv; int bus_width = mmc->bus_width; unsigned int version = atmel_mci_get_version(mci); int busw; @@ -325,7 +325,7 @@ static void mci_set_ios(struct mmc *mmc) /* Entered into mmc structure during driver init */ static int mci_init(struct mmc *mmc) { - atmel_mci_t *mci = (atmel_mci_t *)mmc->priv; + atmel_mci_t *mci = mmc->priv; /* Initialize controller */ writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */ @@ -357,36 +357,45 @@ static const struct mmc_ops atmel_mci_ops = { */ int atmel_mci_init(void *regs) { - struct mmc *mmc = malloc(sizeof(struct mmc)); + struct mmc *mmc; + struct mmc_config *cfg; struct atmel_mci *mci; unsigned int version; - if (!mmc) + cfg = malloc(sizeof(*cfg)); + if (cfg == NULL) return -1; + memset(cfg, 0, sizeof(*cfg)); - mmc->name = "mci"; - mmc->priv = regs; - mmc->ops = &atmel_mci_ops; + mci = (struct atmel_mci *)regs; + + cfg->name = "mci"; + cfg->ops = &atmel_mci_ops; /* need to be able to pass these in on a board by board basis */ - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - mci = (struct atmel_mci *)mmc->priv; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; version = atmel_mci_get_version(mci); if ((version & 0xf00) >= 0x300) - mmc->host_caps = MMC_MODE_8BIT; + cfg->host_caps = MMC_MODE_8BIT; - mmc->host_caps |= MMC_MODE_4BIT; + cfg->host_caps |= MMC_MODE_4BIT; /* * min and max frequencies determined by * max and min of clock divider */ - mmc->f_min = get_mci_clk_rate() / (2*256); - mmc->f_max = get_mci_clk_rate() / (2*1); + cfg->f_min = get_mci_clk_rate() / (2*256); + cfg->f_max = get_mci_clk_rate() / (2*1); + + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - mmc->b_max = 0; + mmc = mmc_create(cfg, regs); - mmc_register(mmc); + if (mmc == NULL) { + free(cfg); + return -1; + } + /* NOTE: possibly leaking the cfg structure */ return 0; } diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ac07bb9a2a..eccdbc4b61 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -17,11 +17,6 @@ #include #include "mmc_private.h" -/* Set block count limit because of 16 bit register limit on some hardware*/ -#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT -#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535 -#endif - static struct list_head mmc_devices; static int cur_dev_num = -1; @@ -37,8 +32,8 @@ int mmc_getwp(struct mmc *mmc) wp = board_mmc_getwp(mmc); if (wp < 0) { - if (mmc->ops->getwp) - wp = mmc->ops->getwp(mmc); + if (mmc->cfg->ops->getwp) + wp = mmc->cfg->ops->getwp(mmc); else wp = 0; } @@ -63,7 +58,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) printf("CMD_SEND:%d\n", cmd->cmdidx); printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg); - ret = mmc->ops->send_cmd(mmc, cmd, data); + ret = mmc->cfg->ops->send_cmd(mmc, cmd, data); switch (cmd->resp_type) { case MMC_RSP_NONE: printf("\t\tMMC_RSP_NONE\n"); @@ -106,7 +101,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) break; } #else - ret = mmc->ops->send_cmd(mmc, cmd, data); + ret = mmc->cfg->ops->send_cmd(mmc, cmd, data); #endif return ret; } @@ -253,7 +248,8 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst) return 0; do { - cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; + cur = (blocks_todo > mmc->cfg->b_max) ? + mmc->cfg->b_max : blocks_todo; if(mmc_read_blocks(mmc, dst, start, cur) != cur) return 0; blocks_todo -= cur; @@ -312,7 +308,7 @@ static int sd_send_op_cond(struct mmc *mmc) * specified. */ cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 : - (mmc->voltages & 0xff8000); + (mmc->cfg->voltages & 0xff8000); if (mmc->version == SD_VERSION_2) cmd.cmdarg |= OCR_HCS; @@ -361,11 +357,11 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd, cmd->cmdarg = 0; if (use_arg && !mmc_host_is_spi(mmc)) { cmd->cmdarg = - (mmc->voltages & + (mmc->cfg->voltages & (mmc->op_cond_response & OCR_VOLTAGE_MASK)) | (mmc->op_cond_response & OCR_ACCESS_MODE); - if (mmc->host_caps & MMC_MODE_HC) + if (mmc->cfg->host_caps & MMC_MODE_HC) cmd->cmdarg |= OCR_HCS; } err = mmc_send_cmd(mmc, cmd, NULL); @@ -578,8 +574,8 @@ int mmc_getcd(struct mmc *mmc) cd = board_mmc_getcd(mmc); if (cd < 0) { - if (mmc->ops->getcd) - cd = mmc->ops->getcd(mmc); + if (mmc->cfg->ops->getcd) + cd = mmc->cfg->ops->getcd(mmc); else cd = 1; } @@ -703,8 +699,8 @@ retry_scr: * This can avoid furthur problem when the card runs in different * mode between the host. */ - if (!((mmc->host_caps & MMC_MODE_HS_52MHz) && - (mmc->host_caps & MMC_MODE_HS))) + if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) && + (mmc->cfg->host_caps & MMC_MODE_HS))) return 0; err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status); @@ -751,17 +747,17 @@ static const int multipliers[] = { static void mmc_set_ios(struct mmc *mmc) { - if (mmc->ops->set_ios) - mmc->ops->set_ios(mmc); + if (mmc->cfg->ops->set_ios) + mmc->cfg->ops->set_ios(mmc); } void mmc_set_clock(struct mmc *mmc, uint clock) { - if (clock > mmc->f_max) - clock = mmc->f_max; + if (clock > mmc->cfg->f_max) + clock = mmc->cfg->f_max; - if (clock < mmc->f_min) - clock = mmc->f_min; + if (clock < mmc->cfg->f_min) + clock = mmc->cfg->f_min; mmc->clock = clock; @@ -1027,7 +1023,7 @@ static int mmc_startup(struct mmc *mmc) return err; /* Restrict card's capabilities by what the host can do */ - mmc->card_caps &= mmc->host_caps; + mmc->card_caps &= mmc->cfg->host_caps; if (IS_SD(mmc)) { if (mmc->card_caps & MMC_MODE_4BIT) { @@ -1082,7 +1078,7 @@ static int mmc_startup(struct mmc *mmc) * this bus width, if it's more than 1 */ if (extw != EXT_CSD_BUS_WIDTH_1 && - !(mmc->host_caps & ext_to_hostcaps[extw])) + !(mmc->cfg->host_caps & ext_to_hostcaps[extw])) continue; err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, @@ -1155,7 +1151,7 @@ static int mmc_send_if_cond(struct mmc *mmc) cmd.cmdidx = SD_CMD_SEND_IF_COND; /* We set the bit if the host supports voltages between 2.7 and 3.6 V */ - cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa; + cmd.cmdarg = ((mmc->cfg->voltages & 0xff8000) != 0) << 8 | 0xaa; cmd.resp_type = MMC_RSP_R7; err = mmc_send_cmd(mmc, &cmd, NULL); @@ -1171,8 +1167,33 @@ static int mmc_send_if_cond(struct mmc *mmc) return 0; } -int mmc_register(struct mmc *mmc) +/* not used any more */ +int __deprecated mmc_register(struct mmc *mmc) +{ +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) + printf("%s is deprecated! use mmc_create() instead.\n", __func__); +#endif + return -1; +} + +struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) { + struct mmc *mmc; + + /* quick validation */ + if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL || + cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0) + return NULL; + + mmc = calloc(1, sizeof(*mmc)); + if (mmc == NULL) + return NULL; + + mmc->cfg = cfg; + mmc->priv = priv; + + /* the following chunk was mmc_register() */ + /* Setup dsr related values */ mmc->dsr_imp = 0; mmc->dsr = 0xffffffff; @@ -1183,14 +1204,21 @@ int mmc_register(struct mmc *mmc) mmc->block_dev.block_read = mmc_bread; mmc->block_dev.block_write = mmc_bwrite; mmc->block_dev.block_erase = mmc_berase; - if (!mmc->b_max) - mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - INIT_LIST_HEAD (&mmc->link); + /* setup initial part type */ + mmc->block_dev.part_type = mmc->cfg->part_type; - list_add_tail (&mmc->link, &mmc_devices); + INIT_LIST_HEAD(&mmc->link); - return 0; + list_add_tail(&mmc->link, &mmc_devices); + + return mmc; +} + +void mmc_destroy(struct mmc *mmc) +{ + /* only freeing memory for now */ + free(mmc); } #ifdef CONFIG_PARTITIONS @@ -1209,7 +1237,7 @@ int mmc_start_init(struct mmc *mmc) int err; /* we pretend there's no card when init is NULL */ - if (mmc_getcd(mmc) == 0 || mmc->ops->init == NULL) { + if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) { mmc->has_init = 0; #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("MMC: no card present\n"); @@ -1221,7 +1249,7 @@ int mmc_start_init(struct mmc *mmc) return 0; /* made sure it's not NULL earlier */ - err = mmc->ops->init(mmc); + err = mmc->cfg->ops->init(mmc); if (err) return err; @@ -1323,7 +1351,7 @@ void print_mmc_devices(char separator) list_for_each(entry, &mmc_devices) { m = list_entry(entry, struct mmc, link); - printf("%s: %d", m->name, m->block_dev.dev); + printf("%s: %d", m->cfg->name, m->block_dev.dev); if (entry->next != &mmc_devices) printf("%c ", separator); diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index e94de37c8b..5b5b33a4b2 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -92,7 +92,7 @@ static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf, spi_xfer(spi, 2 * 8, NULL, &crc, 0); #ifdef CONFIG_MMC_SPI_CRC_ON if (swab16(cyg_crc16(buf, bsize)) != crc) { - debug("%s: CRC error\n", mmc->name); + debug("%s: CRC error\n", mmc->cfg->name); r1 = R1_SPI_COM_CRC; break; } @@ -238,6 +238,7 @@ done: static void mmc_spi_set_ios(struct mmc *mmc) { struct spi_slave *spi = mmc->priv; + debug("%s: clock %u\n", __func__, mmc->clock); if (mmc->clock) spi_set_speed(spi, mmc->clock); @@ -246,7 +247,6 @@ static void mmc_spi_set_ios(struct mmc *mmc) static int mmc_spi_init_p(struct mmc *mmc) { struct spi_slave *spi = mmc->priv; - mmc->clock = 0; spi_set_speed(spi, MMC_SPI_MIN_CLOCK); spi_claim_bus(spi); /* cs deactivated for 100+ clock */ @@ -261,29 +261,31 @@ static const struct mmc_ops mmc_spi_ops = { .init = mmc_spi_init_p, }; +static struct mmc_config mmc_spi_cfg = { + .name = "MMC_SPI", + .ops = &mmc_spi_ops, + .host_caps = MMC_MODE_SPI, + .voltages = MMC_SPI_VOLTAGE, + .f_min = MMC_SPI_MIN_CLOCK, + .part_type = PART_TYPE_DOS, + .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, +}; + struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode) { struct mmc *mmc; + struct spi_slave *spi; - mmc = malloc(sizeof(*mmc)); - if (!mmc) - return NULL; - memset(mmc, 0, sizeof(*mmc)); - mmc->priv = spi_setup_slave(bus, cs, speed, mode); - if (!mmc->priv) { - free(mmc); + spi = spi_setup_slave(bus, cs, speed, mode); + if (spi == NULL) return NULL; - } - mmc->name = "MMC_SPI"; - mmc->ops = &mmc_spi_ops; - mmc->host_caps = MMC_MODE_SPI; - - mmc->voltages = MMC_SPI_VOLTAGE; - mmc->f_max = speed; - mmc->f_min = MMC_SPI_MIN_CLOCK; - mmc->block_dev.part_type = PART_TYPE_DOS; - mmc_register(mmc); + mmc_spi_cfg.f_max = speed; + mmc = mmc_create(&mmc_spi_cfg, spi); + if (mmc == NULL) { + spi_free_slave(spi); + return NULL; + } return mmc; } diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index aa2fdefa75..3db9669c82 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -167,7 +167,8 @@ ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src) return 0; do { - cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo; + cur = (blocks_todo > mmc->cfg->b_max) ? + mmc->cfg->b_max : blocks_todo; if (mmc_write_blocks(mmc, start, cur, src) != cur) return 0; blocks_todo -= cur; diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c index 3357559981..561b204598 100644 --- a/drivers/mmc/mxcmmc.c +++ b/drivers/mmc/mxcmmc.c @@ -122,6 +122,8 @@ struct mxcmci_host { }; static struct mxcmci_host mxcmci_host; + +/* maintainer note: do we really want to have a global host pointer? */ static struct mxcmci_host *host = &mxcmci_host; static inline int mxcmci_use_dma(struct mxcmci_host *host) @@ -491,31 +493,24 @@ static const struct mmc_ops mxcmci_ops = { .init = mxcmci_init, }; +static struct mmc_config mxcmci_cfg = { + .name = "MXC MCI", + .ops = &mxcmci_ops, + .host_caps = MMC_MODE_4BIT, + .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, +}; + static int mxcmci_initialize(bd_t *bis) { - struct mmc *mmc = NULL; - - mmc = malloc(sizeof(struct mmc)); - - if (!mmc) - return -ENOMEM; - - mmc->name = "MXC MCI"; - mmc->ops = &mxcmci_ops; - mmc->host_caps = MMC_MODE_4BIT; - host->base = (struct mxcmci_regs *)CONFIG_MXC_MCI_REGS_BASE; - mmc->priv = host; - host->mmc = mmc; - - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - - mmc->f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7; - mmc->f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1; - mmc->b_max = 0; + mxcmci_cfg.f_min = mxc_get_clock(MXC_ESDHC_CLK) >> 7; + mxcmci_cfg.f_max = mxc_get_clock(MXC_ESDHC_CLK) >> 1; - mmc_register(mmc); + host->mmc = mmc_create(&mxcmci_cfg, host); + if (host->mmc == NULL) + return -1; return 0; } diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 3512a99de9..2fa4eeef44 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -35,6 +35,7 @@ struct mxsmmc_priv { int (*mmc_is_wp)(int); int (*mmc_cd)(int); struct mxs_dma_desc *desc; + struct mmc_config cfg; /* mmc configuration */ }; #define MXSMMC_MAX_TIMEOUT 10000 @@ -134,7 +135,7 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) static int mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv; + struct mxsmmc_priv *priv = mmc->priv; struct mxs_ssp_regs *ssp_regs = priv->regs; uint32_t reg; int timeout; @@ -305,7 +306,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) static void mxsmmc_set_ios(struct mmc *mmc) { - struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv; + struct mxsmmc_priv *priv = mmc->priv; struct mxs_ssp_regs *ssp_regs = priv->regs; /* Set the clock speed */ @@ -334,7 +335,7 @@ static void mxsmmc_set_ios(struct mmc *mmc) static int mxsmmc_init(struct mmc *mmc) { - struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv; + struct mxsmmc_priv *priv = mmc->priv; struct mxs_ssp_regs *ssp_regs = priv->regs; /* Reset SSP */ @@ -379,20 +380,13 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) if (!mxs_ssp_bus_id_valid(id)) return -ENODEV; - mmc = malloc(sizeof(struct mmc)); - if (!mmc) - return -ENOMEM; - priv = malloc(sizeof(struct mxsmmc_priv)); - if (!priv) { - free(mmc); + if (!priv) return -ENOMEM; - } priv->desc = mxs_dma_desc_alloc(); if (!priv->desc) { free(priv); - free(mmc); return -ENOMEM; } @@ -405,13 +399,12 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) priv->id = id; priv->regs = mxs_ssp_regs_by_bus(id); - mmc->name = "MXS MMC"; - mmc->ops = &mxsmmc_ops; - mmc->priv = priv; + priv->cfg.name = "MXS MMC"; + priv->cfg.ops = &mxsmmc_ops; - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | + priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; @@ -421,10 +414,15 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) * CLOCK_DIVIDE has to be an even value from 2 to 254, and * CLOCK_RATE could be any integer from 0 to 255. */ - mmc->f_min = 400000; - mmc->f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2; - mmc->b_max = 0x20; + priv->cfg.f_min = 400000; + priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2; + priv->cfg.b_max = 0x20; - mmc_register(mmc); + mmc = mmc_create(&priv->cfg, priv); + if (mmc == NULL) { + mxs_dma_desc_free(priv->desc); + free(priv); + return -ENOMEM; + } return 0; } diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index fecac5698b..17cbb0983d 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -49,6 +50,7 @@ struct omap_hsmmc_data { struct hsmmc *base_addr; + struct mmc_config cfg; #ifdef OMAP_HSMMC_USE_GPIO int cd_gpio; int wp_gpio; @@ -61,8 +63,6 @@ struct omap_hsmmc_data { static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size); static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, unsigned int siz); -static struct mmc hsmmc_dev[3]; -static struct omap_hsmmc_data hsmmc_dev_data[3]; #ifdef OMAP_HSMMC_USE_GPIO static int omap_mmc_setup_gpio_in(int gpio, const char *label) @@ -147,7 +147,7 @@ unsigned char mmc_board_init(struct mmc *mmc) &t2_base->devconf1); /* Change from default of 52MHz to 26MHz if necessary */ - if (!(mmc->host_caps & MMC_MODE_HS_52MHz)) + if (!(mmc->cfg->host_caps & MMC_MODE_HS_52MHz)) writel(readl(&t2_base->ctl_prog_io1) & ~CTLPROGIO1SPEEDCTRL, &t2_base->ctl_prog_io1); @@ -636,14 +636,17 @@ static const struct mmc_ops omap_hsmmc_ops = { int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, int wp_gpio) { - struct mmc *mmc = &hsmmc_dev[dev_index]; - struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index]; - uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | - MMC_MODE_HC; + struct mmc *mmc; + struct omap_hsmmc_data *priv_data; + struct mmc_config *cfg; + uint host_caps_val; + + priv_data = malloc(sizeof(*priv_data)); + if (priv_data == NULL) + return -1; - mmc->name = "OMAP SD/MMC"; - mmc->ops = &omap_hsmmc_ops; - mmc->priv = priv_data; + host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | + MMC_MODE_HC; switch (dev_index) { case 0: @@ -678,34 +681,40 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp"); #endif - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - mmc->host_caps = host_caps_val & ~host_caps_mask; + cfg = &priv_data->cfg; - mmc->f_min = 400000; + cfg->name = "OMAP SD/MMC"; + cfg->ops = &omap_hsmmc_ops; + + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + cfg->host_caps = host_caps_val & ~host_caps_mask; + + cfg->f_min = 400000; if (f_max != 0) - mmc->f_max = f_max; + cfg->f_max = f_max; else { - if (mmc->host_caps & MMC_MODE_HS) { - if (mmc->host_caps & MMC_MODE_HS_52MHz) - mmc->f_max = 52000000; + if (cfg->host_caps & MMC_MODE_HS) { + if (cfg->host_caps & MMC_MODE_HS_52MHz) + cfg->f_max = 52000000; else - mmc->f_max = 26000000; + cfg->f_max = 26000000; } else - mmc->f_max = 20000000; + cfg->f_max = 20000000; } - mmc->b_max = 0; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; #if defined(CONFIG_OMAP34XX) /* * Silicon revs 2.1 and older do not support multiblock transfers. */ if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21)) - mmc->b_max = 1; + cfg->b_max = 1; #endif - - mmc_register(mmc); + mmc = mmc_create(cfg, priv_data); + if (mmc == NULL) + return -1; return 0; } diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c index 188e1d4c6b..1f297571e5 100644 --- a/drivers/mmc/pxa_mmc_gen.c +++ b/drivers/mmc/pxa_mmc_gen.c @@ -52,7 +52,7 @@ struct pxa_mmc_priv { /* Wait for bit to be set */ static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; unsigned int timeout = PXA_MMC_TIMEOUT; @@ -71,7 +71,7 @@ static int pxa_mmc_wait(struct mmc *mmc, uint32_t mask) static int pxa_mmc_stop_clock(struct mmc *mmc) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; unsigned int timeout = PXA_MMC_TIMEOUT; @@ -100,7 +100,7 @@ static int pxa_mmc_stop_clock(struct mmc *mmc) static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd, uint32_t cmdat) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; int ret; @@ -143,7 +143,7 @@ static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd, static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; uint32_t a, b, c; int i; @@ -185,7 +185,7 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd) static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; uint32_t len; uint32_t *buf = (uint32_t *)data->dest; @@ -221,7 +221,7 @@ static int pxa_mmc_do_read_xfer(struct mmc *mmc, struct mmc_data *data) static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; uint32_t len; uint32_t *buf = (uint32_t *)data->src; @@ -264,7 +264,7 @@ static int pxa_mmc_do_write_xfer(struct mmc *mmc, struct mmc_data *data) static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; uint32_t cmdat = 0; int ret; @@ -317,7 +317,7 @@ static int pxa_mmc_request(struct mmc *mmc, struct mmc_cmd *cmd, static void pxa_mmc_set_ios(struct mmc *mmc) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; uint32_t tmp; uint32_t pxa_mmc_clock; @@ -335,7 +335,7 @@ static void pxa_mmc_set_ios(struct mmc *mmc) /* Set clock to the card the usual way. */ pxa_mmc_clock = 0; - tmp = mmc->f_max / mmc->clock; + tmp = mmc->cfg->f_max / mmc->clock; tmp += tmp % 2; while (tmp > 1) { @@ -348,7 +348,7 @@ static void pxa_mmc_set_ios(struct mmc *mmc) static int pxa_mmc_init(struct mmc *mmc) { - struct pxa_mmc_priv *priv = (struct pxa_mmc_priv *)mmc->priv; + struct pxa_mmc_priv *priv = mmc->priv; struct pxa_mmc_regs *regs = priv->regs; /* Make sure the clock are stopped */ @@ -372,6 +372,16 @@ static const struct mmc_ops pxa_mmc_ops = { .init = pxa_mmc_init, }; +static struct mmc_config pxa_mmc_cfg = { + .name = "PXA MMC", + .ops = &pxa_mmc_ops, + .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + .f_max = PXAMMC_MAX_SPEED, + .f_min = PXAMMC_MIN_SPEED, + .host_caps = PXAMMC_HOST_CAPS, + .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, +}; + int pxa_mmc_register(int card_index) { struct mmc *mmc; @@ -379,13 +389,11 @@ int pxa_mmc_register(int card_index) uint32_t reg; int ret = -ENOMEM; - mmc = malloc(sizeof(struct mmc)); - if (!mmc) - goto err0; - priv = malloc(sizeof(struct pxa_mmc_priv)); if (!priv) - goto err1; + goto err0; + + memset(priv, 0, sizeof(*priv)); switch (card_index) { case 0: @@ -395,23 +403,12 @@ int pxa_mmc_register(int card_index) priv->regs = (struct pxa_mmc_regs *)MMC1_BASE; break; default: + ret = -EINVAL; printf("PXA MMC: Invalid MMC controller ID (card_index = %d)\n", card_index); - goto err2; + goto err1; } - mmc->priv = priv; - - mmc->name = "PXA MMC"; - mmc->ops = &pxa_mmc_ops; - - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->f_max = PXAMMC_MAX_SPEED; - mmc->f_min = PXAMMC_MIN_SPEED; - mmc->host_caps = PXAMMC_HOST_CAPS; - - mmc->b_max = 0; - #ifndef CONFIG_CPU_MONAHANS /* PXA2xx */ reg = readl(CKEN); reg |= CKEN12_MMC; @@ -422,14 +419,14 @@ int pxa_mmc_register(int card_index) writel(reg, CKENA); #endif - mmc_register(mmc); + mmc = mmc_create(&pxa_mmc_cfg, priv); + if (mmc == NULL) + goto err1; return 0; -err2: - free(priv); err1: - free(mmc); + free(priv); err0: return ret; } diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index dc6f4e4972..3125d13ba3 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -127,7 +127,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - struct sdhci_host *host = (struct sdhci_host *)mmc->priv; + struct sdhci_host *host = mmc->priv; unsigned int stat = 0; int ret = 0; int trans_bytes = 0, is_aligned = 1; @@ -268,7 +268,7 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) { - struct sdhci_host *host = (struct sdhci_host *)mmc->priv; + struct sdhci_host *host = mmc->priv; unsigned int div, clk, timeout; sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); @@ -278,18 +278,18 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { /* Version 3.00 divisors must be a multiple of 2. */ - if (mmc->f_max <= clock) + if (mmc->cfg->f_max <= clock) div = 1; else { for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { - if ((mmc->f_max / div) <= clock) + if ((mmc->cfg->f_max / div) <= clock) break; } } } else { /* Version 2.00 divisors must be a power of 2. */ for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { - if ((mmc->f_max / div) <= clock) + if ((mmc->cfg->f_max / div) <= clock) break; } } @@ -358,7 +358,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) void sdhci_set_ios(struct mmc *mmc) { u32 ctrl; - struct sdhci_host *host = (struct sdhci_host *)mmc->priv; + struct sdhci_host *host = mmc->priv; if (host->set_control_reg) host->set_control_reg(host); @@ -395,7 +395,7 @@ void sdhci_set_ios(struct mmc *mmc) int sdhci_init(struct mmc *mmc) { - struct sdhci_host *host = (struct sdhci_host *)mmc->priv; + struct sdhci_host *host = mmc->priv; if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) { aligned_buffer = memalign(8, 512*1024); @@ -406,7 +406,7 @@ int sdhci_init(struct mmc *mmc) } } - sdhci_set_power(host, fls(mmc->voltages) - 1); + sdhci_set_power(host, fls(mmc->cfg->voltages) - 1); if (host->quirks & SDHCI_QUIRK_NO_CD) { unsigned int status; @@ -439,20 +439,10 @@ static const struct mmc_ops sdhci_ops = { int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) { - struct mmc *mmc; unsigned int caps; - mmc = malloc(sizeof(struct mmc)); - if (!mmc) { - printf("%s: mmc malloc fail!\n", __func__); - return -1; - } - - mmc->priv = host; - host->mmc = mmc; - - mmc->name = host->name; - mmc->ops = &sdhci_ops; + host->cfg.name = host->name; + host->cfg.ops = &sdhci_ops; caps = sdhci_readl(host, SDHCI_CAPABILITIES); #ifdef CONFIG_MMC_SDMA @@ -464,51 +454,60 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) #endif if (max_clk) - mmc->f_max = max_clk; + host->cfg.f_max = max_clk; else { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) - mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) + host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; else - mmc->f_max = (caps & SDHCI_CLOCK_BASE_MASK) + host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; - mmc->f_max *= 1000000; + host->cfg.f_max *= 1000000; } - if (mmc->f_max == 0) { + if (host->cfg.f_max == 0) { printf("%s: Hardware doesn't specify base clock frequency\n", __func__); return -1; } if (min_clk) - mmc->f_min = min_clk; + host->cfg.f_min = min_clk; else { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) - mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300; + host->cfg.f_min = host->cfg.f_max / + SDHCI_MAX_DIV_SPEC_300; else - mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200; + host->cfg.f_min = host->cfg.f_max / + SDHCI_MAX_DIV_SPEC_200; } - mmc->voltages = 0; + host->cfg.voltages = 0; if (caps & SDHCI_CAN_VDD_330) - mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; if (caps & SDHCI_CAN_VDD_300) - mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; + host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; if (caps & SDHCI_CAN_VDD_180) - mmc->voltages |= MMC_VDD_165_195; + host->cfg.voltages |= MMC_VDD_165_195; if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE) - mmc->voltages |= host->voltages; + host->cfg.voltages |= host->voltages; - mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT; + host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT; if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { if (caps & SDHCI_CAN_DO_8BIT) - mmc->host_caps |= MMC_MODE_8BIT; + host->cfg.host_caps |= MMC_MODE_8BIT; } if (host->host_caps) - mmc->host_caps |= host->host_caps; + host->cfg.host_caps |= host->host_caps; + + host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; sdhci_reset(host, SDHCI_RESET_ALL); - mmc_register(mmc); + + host->mmc = mmc_create(&host->cfg, host); + if (host->mmc == NULL) { + printf("%s: mmc create fail!\n", __func__); + return -1; + } return 0; } diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 008617d5e6..64b5b47261 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -20,11 +20,6 @@ #define DRIVER_NAME "sh_mmcif" -static void *mmc_priv(struct mmc *mmc) -{ - return (void *)mmc->priv; -} - static int sh_mmcif_intr(void *dev_id) { struct sh_mmcif_host *host = dev_id; @@ -522,7 +517,7 @@ static int sh_mmcif_start_cmd(struct sh_mmcif_host *host, static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - struct sh_mmcif_host *host = mmc_priv(mmc); + struct sh_mmcif_host *host = mmc->priv; int ret; WATCHDOG_RESET(); @@ -550,7 +545,7 @@ static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd, static void sh_mmcif_set_ios(struct mmc *mmc) { - struct sh_mmcif_host *host = mmc_priv(mmc); + struct sh_mmcif_host *host = mmc->priv; if (mmc->clock) sh_mmcif_clock_control(host, mmc->clock); @@ -567,7 +562,7 @@ static void sh_mmcif_set_ios(struct mmc *mmc) static int sh_mmcif_init(struct mmc *mmc) { - struct sh_mmcif_host *host = mmc_priv(mmc); + struct sh_mmcif_host *host = mmc->priv; sh_mmcif_sync_reset(host); sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask); @@ -580,33 +575,36 @@ static const struct mmc_ops sh_mmcif_ops = { .init = sh_mmcif_init, }; +static struct mmc_config sh_mmcif_cfg = { + .name = DRIVER_NAME, + .ops = &sh_mmcif_ops, + .host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | + MMC_MODE_8BIT | MMC_MODE_HC, + .voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + .f_min = CLKDEV_MMC_INIT, + .f_max = CLKDEV_EMMC_DATA, + .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, +}; + int mmcif_mmc_init(void) { int ret = 0; struct mmc *mmc; struct sh_mmcif_host *host = NULL; - mmc = malloc(sizeof(struct mmc)); - if (!mmc) - ret = -ENOMEM; - memset(mmc, 0, sizeof(*mmc)); host = malloc(sizeof(struct sh_mmcif_host)); if (!host) ret = -ENOMEM; memset(host, 0, sizeof(*host)); - mmc->f_min = CLKDEV_MMC_INIT; - mmc->f_max = CLKDEV_EMMC_DATA; - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | - MMC_MODE_8BIT | MMC_MODE_HC; - mmc->name = DRIVER_NAME; - mmc->ops = &sh_mmcif_ops; host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR; host->clk = CONFIG_SH_MMCIF_CLK; - mmc->priv = host; - mmc_register(mmc); + mmc = mmc_create(&sh_mmcif_cfg, host); + if (mmc == NULL) { + free(host); + return -ENOMEM; + } - return ret; + return 0; } diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index e8fbb63f29..ed67eec252 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -18,7 +18,6 @@ DECLARE_GLOBAL_DATA_PTR; -struct mmc mmc_dev[MAX_HOSTS]; struct mmc_host mmc_host[MAX_HOSTS]; #ifndef CONFIG_OF_CONTROL @@ -145,7 +144,7 @@ static int mmc_wait_inhibit(struct mmc_host *host, static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data, struct bounce_buffer *bbstate) { - struct mmc_host *host = (struct mmc_host *)mmc->priv; + struct mmc_host *host = mmc->priv; int flags, i; int result; unsigned int mask = 0; @@ -456,7 +455,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc) } /* Set SD bus voltage & enable bus power */ - mmc_set_power(host, fls(mmc->voltages) - 1); + mmc_set_power(host, fls(mmc->cfg->voltages) - 1); debug("%s: power control = %02X, host control = %02X\n", __func__, readb(&host->reg->pwrcon), readb(&host->reg->hostctl)); @@ -466,7 +465,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc) static int tegra_mmc_core_init(struct mmc *mmc) { - struct mmc_host *host = (struct mmc_host *)mmc->priv; + struct mmc_host *host = mmc->priv; unsigned int mask; debug(" mmc_core_init called\n"); @@ -511,7 +510,7 @@ static int tegra_mmc_core_init(struct mmc *mmc) int tegra_mmc_getcd(struct mmc *mmc) { - struct mmc_host *host = (struct mmc_host *)mmc->priv; + struct mmc_host *host = mmc->priv; debug("tegra_mmc_getcd called\n"); @@ -561,19 +560,18 @@ static int do_mmc_init(int dev_index) debug(" CD GPIO name = %s\n", host->cd_gpio.name); } - mmc = &mmc_dev[dev_index]; + memset(&host->cfg, 0, sizeof(host->cfg)); - mmc->name = "Tegra SD/MMC"; - mmc->priv = host; - mmc->ops = &tegra_mmc_ops; + host->cfg.name = "Tegra SD/MMC"; + host->cfg.ops = &tegra_mmc_ops; - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - mmc->host_caps = 0; + host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + host->cfg.host_caps = 0; if (host->width == 8) - mmc->host_caps |= MMC_MODE_8BIT; + host->cfg.host_caps |= MMC_MODE_8BIT; if (host->width >= 4) - mmc->host_caps |= MMC_MODE_4BIT; - mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; + host->cfg.host_caps |= MMC_MODE_4BIT; + host->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; /* * min freq is for card identification, and is the highest @@ -581,10 +579,14 @@ static int do_mmc_init(int dev_index) * max freq is highest HS eMMC clock as per the SD/MMC spec * (actually 52MHz) */ - mmc->f_min = 375000; - mmc->f_max = 48000000; + host->cfg.f_min = 375000; + host->cfg.f_max = 48000000; - mmc_register(mmc); + host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + mmc = mmc_create(&host->cfg, host); + if (mmc == NULL) + return -1; return 0; } -- cgit v1.2.1 From eea4e6fe82fef9975e0153644935b89882890450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Majewski?= Date: Fri, 21 Feb 2014 08:23:00 +0100 Subject: dfu: mmc: Replace calls to u-boot commands with native mmc API For some time we have been using the run_command() with properly crafted string. Such approach turned to be unreliable and error prone. Switch to "native" mmc subsystem API would allow better type checking and shall improve speed. Also, it seems that this API is changing less often than u-boot commands. The approach similar to env operations on the eMMC has been reused. Signed-off-by: Lukasz Majewski --- drivers/dfu/dfu_mmc.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 0816f46bad..651cfff5b3 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -12,6 +12,7 @@ #include #include #include +#include static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE) dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE]; @@ -20,8 +21,8 @@ static long dfu_file_buf_len; static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, u64 offset, void *buf, long *len) { - char cmd_buf[DFU_CMD_BUF_SIZE]; - u32 blk_start, blk_count; + struct mmc *mmc = find_mmc_device(dfu->dev_num); + u32 blk_start, blk_count, n = 0; /* * We must ensure that we work in lba_blk_size chunks, so ALIGN @@ -38,12 +39,28 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, return -EINVAL; } - sprintf(cmd_buf, "mmc %s %p %x %x", - op == DFU_OP_READ ? "read" : "write", - buf, blk_start, blk_count); + debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__, + op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num, + blk_start, blk_count, buf); + switch (op) { + case DFU_OP_READ: + n = mmc->block_dev.block_read(dfu->dev_num, blk_start, + blk_count, buf); + break; + case DFU_OP_WRITE: + n = mmc->block_dev.block_write(dfu->dev_num, blk_start, + blk_count, buf); + break; + default: + error("Operation not supported\n"); + } - debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); - return run_command(cmd_buf, 0); + if (n != blk_count) { + error("MMC operation failed"); + return -EIO; + } + + return 0; } static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len) -- cgit v1.2.1 From a7b26dbb49139535992c6d4c282bcf258b3f7fa3 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Fri, 21 Mar 2014 16:16:57 +0400 Subject: net/designware: align DMA buffer descriptors to D$ line It's important to have ability to flush/invalidate each DMA buffer descriptor individually to prevent incoherency of adjacent BDs. Signed-off-by: Alexey Brodkin Cc: Vineet Gupta Cc: Joe Hershberger Cc: Vipin Kumar Cc: Stefan Roese Cc: Shiraz Hashim Cc: Albert ARIBAUD Cc: Amit Virdi Cc: Sonic Zhang --- drivers/net/designware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/designware.h b/drivers/net/designware.h index afeaccec19..382b0c7f0a 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -110,7 +110,7 @@ struct dmamacdescr { u32 dmamac_cntl; void *dmamac_addr; struct dmamacdescr *dmamac_next; -} __aligned(16); +} __aligned(ARCH_DMA_MINALIGN); /* * txrx_status definitions -- cgit v1.2.1 From 0bd937248a7a69f531e19eac28d164fce0c60855 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 25 Mar 2014 10:58:21 +0100 Subject: drivers: crypto: ace_sha: add implementation of hardware based lib rand This patch adds implementation of rand library based on hardware random number generator of security subsystem in Exynos SOC. This library includes: - srand() - used for seed hardware block - rand() - returns random number - rand_r() - the same as above with given seed which depends on CONFIG_EXYNOS_ACE_SHA and CONFIG_LIB_HW_RAND. Signed-off-by: Przemyslaw Marczak cc: Akshay Saraswat cc: ARUN MANKUZHI cc: Minkyu Kang Cc: Michael Walle Cc: Tom Rini Cc: Masahiro Yamada --- drivers/crypto/ace_sha.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++- drivers/crypto/ace_sha.h | 8 ++++-- 2 files changed, 77 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/ace_sha.c b/drivers/crypto/ace_sha.c index acbafde97c..ed4f541823 100644 --- a/drivers/crypto/ace_sha.c +++ b/drivers/crypto/ace_sha.c @@ -5,10 +5,12 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include +#include "ace_sha.h" + +#ifdef CONFIG_SHA_HW_ACCEL #include #include #include -#include "ace_sha.h" /* SHA1 value for the message of zero length */ static const unsigned char sha1_digest_emptymsg[SHA1_SUM_LEN] = { @@ -111,3 +113,72 @@ void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA1)) debug("ACE was not setup properly or it is faulty\n"); } +#endif /* CONFIG_SHA_HW_ACCEL */ + +#ifdef CONFIG_LIB_HW_RAND +static unsigned int seed_done; + +void srand(unsigned int seed) +{ + struct exynos_ace_sfr *reg = + (struct exynos_ace_sfr *)samsung_get_base_ace_sfr(); + int i, status; + + /* Seed data */ + for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++) + writel(seed << i, ®->hash_seed[i]); + + /* Wait for seed setup done */ + while (1) { + status = readl(®->hash_status); + if ((status & ACE_HASH_SEEDSETTING_MASK) || + (status & ACE_HASH_PRNGERROR_MASK)) + break; + } + + seed_done = 1; +} + +unsigned int rand(void) +{ + struct exynos_ace_sfr *reg = + (struct exynos_ace_sfr *)samsung_get_base_ace_sfr(); + int i, status; + unsigned int seed = (unsigned int)&status; + unsigned int ret = 0; + + if (!seed_done) + srand(seed); + + /* Start PRNG */ + writel(ACE_HASH_ENGSEL_PRNG | ACE_HASH_STARTBIT_ON, ®->hash_control); + + /* Wait for PRNG done */ + while (1) { + status = readl(®->hash_status); + if (status & ACE_HASH_PRNGDONE_MASK) + break; + if (status & ACE_HASH_PRNGERROR_MASK) { + seed_done = 0; + return 0; + } + } + + /* Clear Done IRQ */ + writel(ACE_HASH_PRNGDONE_MASK, ®->hash_status); + + /* Read a PRNG result */ + for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++) + ret += readl(®->hash_prng[i]); + + seed_done = 0; + return ret; +} + +unsigned int rand_r(unsigned int *seedp) +{ + srand(*seedp); + + return rand(); +} +#endif /* CONFIG_LIB_HW_RAND */ diff --git a/drivers/crypto/ace_sha.h b/drivers/crypto/ace_sha.h index a426d52372..f1097f72dc 100644 --- a/drivers/crypto/ace_sha.h +++ b/drivers/crypto/ace_sha.h @@ -72,9 +72,10 @@ struct exynos_ace_sfr { unsigned char res12[0x30]; unsigned int hash_result[8]; unsigned char res13[0x20]; - unsigned int hash_seed[8]; - unsigned int hash_prng[8]; - unsigned char res14[0x180]; + unsigned int hash_seed[5]; + unsigned char res14[12]; + unsigned int hash_prng[5]; + unsigned char res15[0x18c]; unsigned int pka_sfr[5]; /* base + 0x700 */ }; @@ -291,6 +292,7 @@ struct exynos_ace_sfr { #define ACE_HASH_PRNGERROR_MASK (1 << 7) #define ACE_HASH_PRNGERROR_OFF (0 << 7) #define ACE_HASH_PRNGERROR_ON (1 << 7) +#define ACE_HASH_PRNG_REG_NUM 5 #define ACE_SHA_TYPE_SHA1 1 #define ACE_SHA_TYPE_SHA256 2 -- cgit v1.2.1 From 0b2da7e209f4110b7c81d578336a10330e4a4404 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 28 Mar 2014 16:55:29 -0400 Subject: blackfin: mmc: Correct mmc_host_is_spi and bfin_sdh.c In the recent mmc cleanup, the mmc_host_is_spi macro was broken and bfin_sdh.c had mmc->bus_width turned into mmc_bus_width(mmc), both of which were incorrect. Signed-off-by: Tom Rini --- drivers/mmc/bfin_sdh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index 7b35d8e7d9..bcd6a3e52f 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -238,7 +238,7 @@ static void bfin_sdh_set_ios(struct mmc *mmc) u16 cfg = 0; u16 clk_ctl = 0; - if (mmc_bus_width(mmc) == 4) { + if (mmc->bus_width == 4) { cfg = bfin_read_SDH_CFG(); #ifndef RSI_BLKSZ cfg &= ~PD_SDDAT3; -- cgit v1.2.1 From 462d1883f78353c5ed9d09de45a9b5b2422793a3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 31 Mar 2014 13:03:30 +0900 Subject: drivers: i2c: delete an unused source file Signed-off-by: Masahiro Yamada Cc: Heiko Schocher --- drivers/i2c/adi_i2c.c | 387 -------------------------------------------------- 1 file changed, 387 deletions(-) delete mode 100644 drivers/i2c/adi_i2c.c (limited to 'drivers') diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c deleted file mode 100644 index 675f4171ce..0000000000 --- a/drivers/i2c/adi_i2c.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * i2c.c - driver for ADI TWI/I2C - * - * Copyright (c) 2006-2013 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include - -#include -#include -#include - -/* Every register is 32bit aligned, but only 16bits in size */ -#define ureg(name) u16 name; u16 __pad_##name; -struct twi_regs { - ureg(clkdiv); - ureg(control); - ureg(slave_ctl); - ureg(slave_stat); - ureg(slave_addr); - ureg(master_ctl); - ureg(master_stat); - ureg(master_addr); - ureg(int_stat); - ureg(int_mask); - ureg(fifo_ctl); - ureg(fifo_stat); - char __pad[0x50]; - ureg(xmt_data8); - ureg(xmt_data16); - ureg(rcv_data8); - ureg(rcv_data16); -}; -#undef ureg - -/* U-Boot I2C framework allows only one active device at a time. */ -#ifdef TWI_CLKDIV -#define TWI0_CLKDIV TWI_CLKDIV -#endif -static struct twi_regs *twi = (void *)TWI0_CLKDIV; - -#ifdef DEBUG -# define dmemset(s, c, n) memset(s, c, n) -#else -# define dmemset(s, c, n) -#endif -#define debugi(fmt, args...) \ - debug( \ - "MSTAT:0x%03x FSTAT:0x%x ISTAT:0x%02x\t%-20s:%-3i: " fmt "\n", \ - twi->master_stat, twi->fifo_stat, twi->int_stat, \ - __func__, __LINE__, ## args) - -#ifdef CONFIG_TWICLK_KHZ -# error do not define CONFIG_TWICLK_KHZ ... use CONFIG_SYS_I2C_SPEED -#endif - -/* - * The way speed is changed into duty often results in integer truncation - * with 50% duty, so we'll force rounding up to the next duty by adding 1 - * to the max. In practice this will get us a speed of something like - * 385 KHz. The other limit is easy to handle as it is only 8 bits. - */ -#define I2C_SPEED_MAX 400000 -#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed)) -#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1) -#define I2C_DUTY_MIN 0xff /* 8 bit limited */ -#define SYS_I2C_DUTY I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED) -/* Note: duty is inverse of speed, so the comparisons below are correct */ -#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN -# error "The Blackfin I2C hardware can only operate 20KHz - 400KHz" -#endif - -/* All transfers are described by this data structure */ -struct i2c_msg { - u8 flags; -#define I2C_M_COMBO 0x4 -#define I2C_M_STOP 0x2 -#define I2C_M_READ 0x1 - int len; /* msg length */ - u8 *buf; /* pointer to msg data */ - int alen; /* addr length */ - u8 *abuf; /* addr buffer */ -}; - -/* Allow msec timeout per ~byte transfer */ -#define I2C_TIMEOUT 10 - -/** - * wait_for_completion - manage the actual i2c transfer - * @msg: the i2c msg - */ -static int wait_for_completion(struct i2c_msg *msg) -{ - u16 int_stat, ctl; - ulong timebase = get_timer(0); - - do { - int_stat = readw(&twi->int_stat); - - if (int_stat & XMTSERV) { - debugi("processing XMTSERV"); - writew(XMTSERV, &twi->int_stat); - if (msg->alen) { - writew(*(msg->abuf++), &twi->xmt_data8); - --msg->alen; - } else if (!(msg->flags & I2C_M_COMBO) && msg->len) { - writew(*(msg->buf++), &twi->xmt_data8); - --msg->len; - } else { - ctl = readw(&twi->master_ctl); - if (msg->flags & I2C_M_COMBO) - writew(ctl | RSTART | MDIR, - &twi->master_ctl); - else - writew(ctl | STOP, &twi->master_ctl); - } - } - if (int_stat & RCVSERV) { - debugi("processing RCVSERV"); - writew(RCVSERV, &twi->int_stat); - if (msg->len) { - *(msg->buf++) = readw(&twi->rcv_data8); - --msg->len; - } else if (msg->flags & I2C_M_STOP) { - ctl = readw(&twi->master_ctl); - writew(ctl | STOP, &twi->master_ctl); - } - } - if (int_stat & MERR) { - debugi("processing MERR"); - writew(MERR, &twi->int_stat); - return msg->len; - } - if (int_stat & MCOMP) { - debugi("processing MCOMP"); - writew(MCOMP, &twi->int_stat); - if (msg->flags & I2C_M_COMBO && msg->len) { - ctl = readw(&twi->master_ctl); - ctl = (ctl & ~RSTART) | - (min(msg->len, 0xff) << 6) | MEN | MDIR; - writew(ctl, &twi->master_ctl); - } else - break; - } - - /* If we were able to do something, reset timeout */ - if (int_stat) - timebase = get_timer(0); - - } while (get_timer(timebase) < I2C_TIMEOUT); - - return msg->len; -} - -/** - * i2c_transfer - setup an i2c transfer - * @return: 0 if things worked, non-0 if things failed - * - * Here we just get the i2c stuff all prepped and ready, and then tail off - * into wait_for_completion() for all the bits to go. - */ -static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, - int len, u8 flags) -{ - int ret; - u16 ctl; - uchar addr_buffer[] = { - (addr >> 0), - (addr >> 8), - (addr >> 16), - }; - struct i2c_msg msg = { - .flags = flags | (len >= 0xff ? I2C_M_STOP : 0), - .buf = buffer, - .len = len, - .abuf = addr_buffer, - .alen = alen, - }; - - dmemset(buffer, 0xff, len); - debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i ", - chip, addr, alen, buffer[0], len); - debugi("flags=0x%02x[%s] ", flags, - (flags & I2C_M_READ ? "rd" : "wr")); - - /* wait for things to settle */ - while (readw(&twi->master_stat) & BUSBUSY) - if (ctrlc()) - return 1; - - /* Set Transmit device address */ - writew(chip, &twi->master_addr); - - /* Clear the FIFO before starting things */ - writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl); - writew(0, &twi->fifo_ctl); - - /* prime the pump */ - if (msg.alen) { - len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len; - debugi("first byte=0x%02x", *msg.abuf); - writew(*(msg.abuf++), &twi->xmt_data8); - --msg.alen; - } else if (!(msg.flags & I2C_M_READ) && msg.len) { - debugi("first byte=0x%02x", *msg.buf); - writew(*(msg.buf++), &twi->xmt_data8); - --msg.len; - } - - /* clear int stat */ - writew(-1, &twi->master_stat); - writew(-1, &twi->int_stat); - writew(0, &twi->int_mask); - - /* Master enable */ - ctl = readw(&twi->master_ctl); - ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN | - ((msg.flags & I2C_M_READ) ? MDIR : 0); - writew(ctl, &twi->master_ctl); - - /* process the rest */ - ret = wait_for_completion(&msg); - debugi("ret=%d", ret); - - if (ret) { - ctl = readw(&twi->master_ctl) & ~MEN; - writew(ctl, &twi->master_ctl); - ctl = readw(&twi->control) & ~TWI_ENA; - writew(ctl, &twi->control); - ctl = readw(&twi->control) | TWI_ENA; - writew(ctl, &twi->control); - } - - return ret; -} - -/** - * i2c_set_bus_speed - set i2c bus speed - * @speed: bus speed (in HZ) - */ -int i2c_set_bus_speed(unsigned int speed) -{ - u16 clkdiv = I2C_SPEED_TO_DUTY(speed); - - /* Set TWI interface clock */ - if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN) - return -1; - clkdiv = (clkdiv << 8) | (clkdiv & 0xff); - writew(clkdiv, &twi->clkdiv); - - /* Don't turn it on */ - writew(speed > 100000 ? FAST : 0, &twi->master_ctl); - - return 0; -} - -/** - * i2c_get_bus_speed - get i2c bus speed - * @speed: bus speed (in HZ) - */ -unsigned int i2c_get_bus_speed(void) -{ - u16 clkdiv = readw(&twi->clkdiv) & 0xff; - /* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */ - return 5000000 / clkdiv; -} - -/** - * i2c_init - initialize the i2c bus - * @speed: bus speed (in HZ) - * @slaveaddr: address of device in slave mode (0 - not slave) - * - * Slave mode isn't actually implemented. It'll stay that way until - * we get a real request for it. - */ -void i2c_init(int speed, int slaveaddr) -{ - u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F; - - /* Set TWI internal clock as 10MHz */ - writew(prescale, &twi->control); - - /* Set TWI interface clock as specified */ - i2c_set_bus_speed(speed); - - /* Enable it */ - writew(TWI_ENA | prescale, &twi->control); - - debugi("CONTROL:0x%04x CLKDIV:0x%04x", readw(&twi->control), - readw(&twi->clkdiv)); - -#if CONFIG_SYS_I2C_SLAVE -# error I2C slave support not tested/supported -#endif -} - -/** - * i2c_probe - test if a chip exists at a given i2c address - * @chip: i2c chip addr to search for - * @return: 0 if found, non-0 if not found - */ -int i2c_probe(uchar chip) -{ - u8 byte; - return i2c_read(chip, 0, 0, &byte, 1); -} - -/** - * i2c_read - read data from an i2c device - * @chip: i2c chip addr - * @addr: memory (register) address in the chip - * @alen: byte size of address - * @buffer: buffer to store data read from chip - * @len: how many bytes to read - * @return: 0 on success, non-0 on failure - */ -int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) -{ - return i2c_transfer(chip, addr, alen, buffer, - len, (alen ? I2C_M_COMBO : I2C_M_READ)); -} - -/** - * i2c_write - write data to an i2c device - * @chip: i2c chip addr - * @addr: memory (register) address in the chip - * @alen: byte size of address - * @buffer: buffer holding data to write to chip - * @len: how many bytes to write - * @return: 0 on success, non-0 on failure - */ -int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) -{ - return i2c_transfer(chip, addr, alen, buffer, len, 0); -} - -/** - * i2c_set_bus_num - change active I2C bus - * @bus: bus index, zero based - * @returns: 0 on success, non-0 on failure - */ -int i2c_set_bus_num(unsigned int bus) -{ - switch (bus) { -#if CONFIG_SYS_MAX_I2C_BUS > 0 - case 0: - twi = (void *)TWI0_CLKDIV; - return 0; -#endif -#if CONFIG_SYS_MAX_I2C_BUS > 1 - case 1: - twi = (void *)TWI1_CLKDIV; - return 0; -#endif -#if CONFIG_SYS_MAX_I2C_BUS > 2 - case 2: - twi = (void *)TWI2_CLKDIV; - return 0; -#endif - default: return -1; - } -} - -/** - * i2c_get_bus_num - returns index of active I2C bus - */ -unsigned int i2c_get_bus_num(void) -{ - switch ((unsigned long)twi) { -#if CONFIG_SYS_MAX_I2C_BUS > 0 - case TWI0_CLKDIV: - return 0; -#endif -#if CONFIG_SYS_MAX_I2C_BUS > 1 - case TWI1_CLKDIV: - return 1; -#endif -#if CONFIG_SYS_MAX_I2C_BUS > 2 - case TWI2_CLKDIV: - return 2; -#endif - default: return -1; - } -} -- cgit v1.2.1 From cd2bf4846c36a225bfffdedda50e5e80c8b2857f Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 31 Mar 2014 14:54:28 +0900 Subject: mmc: sh_mmcif: Fix compile error BY commit "mmc: Split mmc struct, rework mmc initialization (v2)", sh_mmcif has compile error. This fixes compile error. Signed-off-by: Nobuhiro Iwamatsu CC: Pantelis Antoniou Reported-by: Masahiro Yamada Acked-by: Pantelis Antoniou --- drivers/mmc/sh_mmcif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 64b5b47261..ad5b23ce7e 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -580,7 +580,7 @@ static struct mmc_config sh_mmcif_cfg = { .ops = &sh_mmcif_ops, .host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC, - .voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, .f_min = CLKDEV_MMC_INIT, .f_max = CLKDEV_EMMC_DATA, .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, -- cgit v1.2.1 From 74c32ef58dbcc204af03f5d7188b5cea3959974c Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 31 Mar 2014 14:54:29 +0900 Subject: mmc: sh_mmcif: Fix warning by unused variable Signed-off-by: Nobuhiro Iwamatsu Reported-by: Masahiro Yamada Acked-by: Pantelis Antoniou --- drivers/mmc/sh_mmcif.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index ad5b23ce7e..ed83a14c2d 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -588,13 +588,12 @@ static struct mmc_config sh_mmcif_cfg = { int mmcif_mmc_init(void) { - int ret = 0; struct mmc *mmc; struct sh_mmcif_host *host = NULL; host = malloc(sizeof(struct sh_mmcif_host)); if (!host) - ret = -ENOMEM; + return -ENOMEM; memset(host, 0, sizeof(*host)); host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR; -- cgit v1.2.1 From 33ace362fdf80e2e2ea4cdf2829a5179c52de3f4 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 7 Feb 2014 14:15:20 -0500 Subject: mmc: Add 'mmc rst-function' sub-command Some eMMC chips may need the RST_n_FUNCTION bit set to a non-zero value in order for warm reset of the system to work. Details on this being required will be part of the eMMC datasheet. Also add using this command to the dra7xx README. * Whitespace fix by panto Signed-off-by: Tom Rini Acked-by: Pantelis Antoniou --- drivers/mmc/mmc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index eccdbc4b61..16051e52ff 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1513,4 +1513,16 @@ int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access) return err; return 0; } + +/* + * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value + * for enable. Note that this is a write-once field for non-zero values. + * + * Returns 0 on success. + */ +int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) +{ + return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION, + enable); +} #endif -- cgit v1.2.1 From fb823981c550f873270666ce0f6117dbb956c214 Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Mon, 24 Mar 2014 02:40:41 -0500 Subject: mmc: fsl_esdhc: fix calculation of timeout for data transactions Calculation of the timeout value should be based on actual clock value, written to controller registers. Since mmc->tran_speed is either the maximum allowed speed, or the preliminary value, that is be not yet set to registers, the actual timeout, taken by the controller, based on its clock settings, may be much longer than expected, based on mmc->tran_speed value. In particular it happens at early initialization stage, when typical value of mmc->tran_speed is 20MHz or 26MHz, while actual clock setting, configured in the controller, is 400kHz. It's more correct to use mmc->clock value for timeout calculation instead. Signed-off-by: Andrew Gabbasov Acked-by: Pantelis Antoniou --- drivers/mmc/fsl_esdhc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index d64962652c..58637742a4 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -221,16 +221,16 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) * 2)Timeout period should be minimum 0.250sec as per SD Card spec * So, Number of SD Clock cycles for 0.25sec should be minimum * (SD Clock/sec * 0.25 sec) SD Clock cycles - * = (mmc->tran_speed * 1/4) SD Clock cycles + * = (mmc->clock * 1/4) SD Clock cycles * As 1) >= 2) - * => (2^(timeout+13)) >= mmc->tran_speed * 1/4 + * => (2^(timeout+13)) >= mmc->clock * 1/4 * Taking log2 both the sides - * => timeout + 13 >= log2(mmc->tran_speed/4) + * => timeout + 13 >= log2(mmc->clock/4) * Rounding up to next power of 2 - * => timeout + 13 = log2(mmc->tran_speed/4) + 1 - * => timeout + 13 = fls(mmc->tran_speed/4) + * => timeout + 13 = log2(mmc->clock/4) + 1 + * => timeout + 13 = fls(mmc->clock/4) */ - timeout = fls(mmc->tran_speed/4); + timeout = fls(mmc->clock/4); timeout -= 13; if (timeout > 14) -- cgit v1.2.1 From 8a573022c38da9ecc749acbc60556a8e8bd41996 Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Mon, 24 Mar 2014 02:41:06 -0500 Subject: mmc: fsl_esdhc: add controller reset in case of data related errors too The controller reset is performed now if command error occurs. This commit adds the reset for the case of data related errors too. Signed-off-by: Andrew Gabbasov Acked-by: Pantelis Antoniou --- drivers/mmc/fsl_esdhc.c | 63 ++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 58637742a4..00a454f850 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -265,6 +265,7 @@ static void check_and_invalidate_dcache_range static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { + int err = 0; uint xfertyp; uint irqstat; struct fsl_esdhc_cfg *cfg = mmc->priv; @@ -296,8 +297,6 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Set up for a data transfer if we have one */ if (data) { - int err; - err = esdhc_setup_data(mmc, data); if(err) return err; @@ -325,27 +324,15 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) irqstat = esdhc_read32(®s->irqstat); - /* Reset CMD and DATA portions on error */ - if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) { - esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | - SYSCTL_RSTC); - while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) - ; - - if (data) { - esdhc_write32(®s->sysctl, - esdhc_read32(®s->sysctl) | - SYSCTL_RSTD); - while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) - ; - } + if (irqstat & CMD_ERR) { + err = COMM_ERR; + goto out; } - if (irqstat & CMD_ERR) - return COMM_ERR; - - if (irqstat & IRQSTAT_CTOE) - return TIMEOUT; + if (irqstat & IRQSTAT_CTOE) { + err = TIMEOUT; + goto out; + } /* Workaround for ESDHC errata ENGcm03648 */ if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { @@ -360,7 +347,8 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) if (timeout <= 0) { printf("Timeout waiting for DAT0 to go high!\n"); - return TIMEOUT; + err = TIMEOUT; + goto out; } } @@ -387,20 +375,41 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) do { irqstat = esdhc_read32(®s->irqstat); - if (irqstat & IRQSTAT_DTOE) - return TIMEOUT; + if (irqstat & IRQSTAT_DTOE) { + err = TIMEOUT; + goto out; + } - if (irqstat & DATA_ERR) - return COMM_ERR; + if (irqstat & DATA_ERR) { + err = COMM_ERR; + goto out; + } } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE); #endif if (data->flags & MMC_DATA_READ) check_and_invalidate_dcache_range(cmd, data); } +out: + /* Reset CMD and DATA portions on error */ + if (err) { + esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | + SYSCTL_RSTC); + while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) + ; + + if (data) { + esdhc_write32(®s->sysctl, + esdhc_read32(®s->sysctl) | + SYSCTL_RSTD); + while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) + ; + } + } + esdhc_write32(®s->irqstat, -1); - return 0; + return err; } static void set_sysctl(struct mmc *mmc, uint clock) -- cgit v1.2.1 From 1336e2d343f088b71ec71907855caccd1053d166 Mon Sep 17 00:00:00 2001 From: "Haijun.Zhang" Date: Tue, 18 Mar 2014 17:04:23 +0800 Subject: mmc:eSDHC: Workaround for data timeout issue on Txxx SoC 1. The Data timeout counter value in eSDHC_SYSCTL register is not working as it should be, so add quirks to enable this workaround to fix it to the max value 0xE. 2. Add CONFIG_SYS_FSL_ERRATUM_ESDHC111 to enable its workaround. * Update of patch for change mmc interface by Pantelis Antoniou Signed-off-by: Haijun Zhang Acked-by: Pantelis Antoniou --- drivers/mmc/fsl_esdhc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 00a454f850..4c3b93d413 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -244,6 +244,9 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) timeout++; #endif +#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE + timeout = 0xE; +#endif esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); return 0; -- cgit v1.2.1 From 3f62971162370213271dc1e7a396b6b3a6d5b6c6 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 1 Apr 2014 17:26:40 +0300 Subject: ahci: Fix data abort on multiple scsi resets. Commit 2faf5fb82ed6 introduced a regression that causes a data abort when running scsi init followed by scsi reset. There are 2 problems with the original commit 1) ALLOC_CACHE_ALIGN_BUFFER() allocates memory on the stack but is assigned to ataid[port] and used by other functions. 2) The function ata_scsiop_inquiry() tries to free memory which was never allocated on the heap. Fix these problems by using tmpid as a temporary cache aligned buffer. Allocate memory separately for ataid[port] and re-use it if required. Fixes: 2faf5fb82ed6 (ahci: Fix cache align error messages) Reported-by: Eli Nidam Signed-off-by: Roger Quadros --- drivers/block/ahci.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index a409f63770..c8f65739e9 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -623,6 +623,7 @@ static int ata_scsiop_inquiry(ccb *pccb) 95 - 4, }; u8 fis[20]; + u16 *idbuf; ALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS); u8 port; @@ -649,17 +650,25 @@ static int ata_scsiop_inquiry(ccb *pccb) return -EIO; } - if (ataid[port]) - free(ataid[port]); - ataid[port] = tmpid; - ata_swap_buf_le16(tmpid, ATA_ID_WORDS); + if (!ataid[port]) { + ataid[port] = malloc(ATA_ID_WORDS * 2); + if (!ataid[port]) { + printf("%s: No memory for ataid[port]\n", __func__); + return -ENOMEM; + } + } + + idbuf = ataid[port]; + + memcpy(idbuf, tmpid, ATA_ID_WORDS * 2); + ata_swap_buf_le16(idbuf, ATA_ID_WORDS); memcpy(&pccb->pdata[8], "ATA ", 8); - ata_id_strcpy((u16 *) &pccb->pdata[16], &tmpid[ATA_ID_PROD], 16); - ata_id_strcpy((u16 *) &pccb->pdata[32], &tmpid[ATA_ID_FW_REV], 4); + ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], 16); + ata_id_strcpy((u16 *)&pccb->pdata[32], &idbuf[ATA_ID_FW_REV], 4); #ifdef DEBUG - ata_dump_id(tmpid); + ata_dump_id(idbuf); #endif return 0; } -- cgit v1.2.1