Blame view
drivers/mmc/mmc_write.c
4.91 KB
da61fa5f4 mmc: don't suppor... |
1 2 3 4 5 6 7 8 9 10 11 |
/* * Copyright 2008, Freescale Semiconductor, Inc * Andy Fleming * * Based vaguely on the Linux code * * SPDX-License-Identifier: GPL-2.0+ */ #include <config.h> #include <common.h> |
33fb211dd dm: mmc: Add supp... |
12 |
#include <dm.h> |
da61fa5f4 mmc: don't suppor... |
13 |
#include <part.h> |
180f87fcc mmc_write.c: Make... |
14 15 |
#include <div64.h> #include <linux/math64.h> |
da61fa5f4 mmc: don't suppor... |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#include "mmc_private.h" static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt) { struct mmc_cmd cmd; ulong end; int err, start_cmd, end_cmd; if (mmc->high_capacity) { end = start + blkcnt - 1; } else { end = (start + blkcnt - 1) * mmc->write_bl_len; start *= mmc->write_bl_len; } if (IS_SD(mmc)) { start_cmd = SD_CMD_ERASE_WR_BLK_START; end_cmd = SD_CMD_ERASE_WR_BLK_END; } else { start_cmd = MMC_CMD_ERASE_GROUP_START; end_cmd = MMC_CMD_ERASE_GROUP_END; } cmd.cmdidx = start_cmd; cmd.cmdarg = start; cmd.resp_type = MMC_RSP_R1; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) goto err_out; cmd.cmdidx = end_cmd; cmd.cmdarg = end; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) goto err_out; cmd.cmdidx = MMC_CMD_ERASE; |
1aa2d074a mmc: update MMC_E... |
55 |
cmd.cmdarg = MMC_ERASE_ARG; |
da61fa5f4 mmc: don't suppor... |
56 57 58 59 60 61 62 63 64 65 66 67 68 |
cmd.resp_type = MMC_RSP_R1b; err = mmc_send_cmd(mmc, &cmd, NULL); if (err) goto err_out; return 0; err_out: puts("mmc erase failed "); return err; } |
561e624c3 dm: mmc: Support ... |
69 70 71 72 73 |
#ifdef CONFIG_BLK ulong mmc_berase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt) #else ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt) #endif |
da61fa5f4 mmc: don't suppor... |
74 |
{ |
561e624c3 dm: mmc: Support ... |
75 76 77 |
#ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); #endif |
bcce53d04 dm: block: Rename... |
78 |
int dev_num = block_dev->devnum; |
da61fa5f4 mmc: don't suppor... |
79 |
int err = 0; |
180f87fcc mmc_write.c: Make... |
80 |
u32 start_rem, blkcnt_rem; |
da61fa5f4 mmc: don't suppor... |
81 82 83 84 85 86 |
struct mmc *mmc = find_mmc_device(dev_num); lbaint_t blk = 0, blk_r = 0; int timeout = 1000; if (!mmc) return -1; |
69f45cd53 dm: mmc: Use the ... |
87 88 |
err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num, block_dev->hwpart); |
873cc1d77 mmc: store hwpart... |
89 90 |
if (err < 0) return -1; |
180f87fcc mmc_write.c: Make... |
91 92 93 94 95 96 97 98 |
/* * We want to see if the requested start or total block count are * unaligned. We discard the whole numbers and only care about the * remainder. */ err = div_u64_rem(start, mmc->erase_grp_size, &start_rem); err = div_u64_rem(blkcnt, mmc->erase_grp_size, &blkcnt_rem); if (start_rem || blkcnt_rem) |
da61fa5f4 mmc: don't suppor... |
99 100 101 102 103 104 105 106 107 108 109 110 111 |
printf(" Caution! Your devices Erase group is 0x%x " "The erase range would be change to " "0x" LBAF "~0x" LBAF " ", mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1), ((start + blkcnt + mmc->erase_grp_size) & ~(mmc->erase_grp_size - 1)) - 1); while (blk < blkcnt) { |
e492dbb41 mmc: sd: optimize... |
112 113 114 115 116 117 118 |
if (IS_SD(mmc) && mmc->ssr.au) { blk_r = ((blkcnt - blk) > mmc->ssr.au) ? mmc->ssr.au : (blkcnt - blk); } else { blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ? mmc->erase_grp_size : (blkcnt - blk); } |
da61fa5f4 mmc: don't suppor... |
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
err = mmc_erase_t(mmc, start + blk, blk_r); if (err) break; blk += blk_r; /* Waiting for the ready status */ if (mmc_send_status(mmc, timeout)) return 0; } return blk; } static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void *src) { struct mmc_cmd cmd; struct mmc_data data; int timeout = 1000; |
c40fdca6b dm: mmc: Move the... |
139 |
if ((start + blkcnt) > mmc_get_blk_desc(mmc)->lba) { |
da61fa5f4 mmc: don't suppor... |
140 141 |
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ") ", |
c40fdca6b dm: mmc: Move the... |
142 |
start + blkcnt, mmc_get_blk_desc(mmc)->lba); |
da61fa5f4 mmc: don't suppor... |
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
return 0; } if (blkcnt == 0) return 0; else if (blkcnt == 1) cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK; else cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK; if (mmc->high_capacity) cmd.cmdarg = start; else cmd.cmdarg = start * mmc->write_bl_len; cmd.resp_type = MMC_RSP_R1; data.src = src; data.blocks = blkcnt; data.blocksize = mmc->write_bl_len; data.flags = MMC_DATA_WRITE; if (mmc_send_cmd(mmc, &cmd, &data)) { printf("mmc write failed "); return 0; } /* SPI multiblock writes terminate using a special * token, not a STOP_TRANSMISSION request. */ if (!mmc_host_is_spi(mmc) && blkcnt > 1) { cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_R1b; if (mmc_send_cmd(mmc, &cmd, NULL)) { printf("mmc fail to send stop cmd "); return 0; } } /* Waiting for the ready status */ if (mmc_send_status(mmc, timeout)) return 0; return blkcnt; } |
33fb211dd dm: mmc: Add supp... |
191 192 193 194 |
#ifdef CONFIG_BLK ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, const void *src) #else |
4101f6879 dm: Drop the bloc... |
195 |
ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, |
7c4213f6a block: pass block... |
196 |
const void *src) |
33fb211dd dm: mmc: Add supp... |
197 |
#endif |
da61fa5f4 mmc: don't suppor... |
198 |
{ |
33fb211dd dm: mmc: Add supp... |
199 200 201 |
#ifdef CONFIG_BLK struct blk_desc *block_dev = dev_get_uclass_platdata(dev); #endif |
bcce53d04 dm: block: Rename... |
202 |
int dev_num = block_dev->devnum; |
da61fa5f4 mmc: don't suppor... |
203 |
lbaint_t cur, blocks_todo = blkcnt; |
873cc1d77 mmc: store hwpart... |
204 |
int err; |
da61fa5f4 mmc: don't suppor... |
205 206 207 208 |
struct mmc *mmc = find_mmc_device(dev_num); if (!mmc) return 0; |
69f45cd53 dm: mmc: Use the ... |
209 |
err = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_num, block_dev->hwpart); |
873cc1d77 mmc: store hwpart... |
210 211 |
if (err < 0) return 0; |
da61fa5f4 mmc: don't suppor... |
212 213 214 215 |
if (mmc_set_blocklen(mmc, mmc->write_bl_len)) return 0; do { |
93bfd6167 mmc: Split mmc st... |
216 217 |
cur = (blocks_todo > mmc->cfg->b_max) ? mmc->cfg->b_max : blocks_todo; |
da61fa5f4 mmc: don't suppor... |
218 219 220 221 222 223 224 225 226 |
if (mmc_write_blocks(mmc, start, cur, src) != cur) return 0; blocks_todo -= cur; start += cur; src += cur * mmc->write_bl_len; } while (blocks_todo > 0); return blkcnt; } |