diff options
| author | Jaehoon Chung <jh80.chung@samsung.com> | 2012-09-17 04:42:02 -0400 |
|---|---|---|
| committer | Chris Ball <cjb@laptop.org> | 2012-10-03 10:05:12 -0400 |
| commit | 950d56acce5d401f477b91d0177605b543d63d07 (patch) | |
| tree | 205505f3976d02c6ef2fa9d6c911407f0e0f6c80 /include/linux/mmc | |
| parent | bec9d4e5939987053169a9bb48fc58b6a2d3e237 (diff) | |
mmc: support BKOPS feature for eMMC
Enable eMMC background operations (BKOPS) feature.
If URGENT_BKOPS is set after a response, note that BKOPS are required.
Immediately run BKOPS if required. Read/write operations should be
requested during BKOPS(LEVEL-1), then issue HPI to interrupt the
ongoing BKOPS and service the foreground operation.
(This patch only controls the LEVEL2/3.)
When repeating the writing 1GB data, at a certain time, performance is
decreased. At that time, card triggers the Level-3 or Level-2. After
running bkops, performance is recovered.
Future considerations:
* Check BKOPS_LEVEL=1 and start BKOPS in a preventive manner.
* Interrupt ongoing BKOPS before powering off the card.
* How do we get BKOPS_STATUS value (periodically send ext_csd command)?
* If using periodic bkops, also consider runtime_pm control.
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Konstantin Dorfman <kdorfman@codeaurora.org>
Reviewed-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'include/linux/mmc')
| -rw-r--r-- | include/linux/mmc/card.h | 8 | ||||
| -rw-r--r-- | include/linux/mmc/core.h | 4 | ||||
| -rw-r--r-- | include/linux/mmc/mmc.h | 19 |
3 files changed, 31 insertions, 0 deletions
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4b27f9f503e4..78cc3be85391 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
| @@ -76,10 +76,13 @@ struct mmc_ext_csd { | |||
| 76 | bool hpi_en; /* HPI enablebit */ | 76 | bool hpi_en; /* HPI enablebit */ |
| 77 | bool hpi; /* HPI support bit */ | 77 | bool hpi; /* HPI support bit */ |
| 78 | unsigned int hpi_cmd; /* cmd used as HPI */ | 78 | unsigned int hpi_cmd; /* cmd used as HPI */ |
| 79 | bool bkops; /* background support bit */ | ||
| 80 | bool bkops_en; /* background enable bit */ | ||
| 79 | unsigned int data_sector_size; /* 512 bytes or 4KB */ | 81 | unsigned int data_sector_size; /* 512 bytes or 4KB */ |
| 80 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ | 82 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ |
| 81 | unsigned int boot_ro_lock; /* ro lock support */ | 83 | unsigned int boot_ro_lock; /* ro lock support */ |
| 82 | bool boot_ro_lockable; | 84 | bool boot_ro_lockable; |
| 85 | u8 raw_exception_status; /* 53 */ | ||
| 83 | u8 raw_partition_support; /* 160 */ | 86 | u8 raw_partition_support; /* 160 */ |
| 84 | u8 raw_erased_mem_count; /* 181 */ | 87 | u8 raw_erased_mem_count; /* 181 */ |
| 85 | u8 raw_ext_csd_structure; /* 194 */ | 88 | u8 raw_ext_csd_structure; /* 194 */ |
| @@ -93,6 +96,7 @@ struct mmc_ext_csd { | |||
| 93 | u8 raw_sec_erase_mult; /* 230 */ | 96 | u8 raw_sec_erase_mult; /* 230 */ |
| 94 | u8 raw_sec_feature_support;/* 231 */ | 97 | u8 raw_sec_feature_support;/* 231 */ |
| 95 | u8 raw_trim_mult; /* 232 */ | 98 | u8 raw_trim_mult; /* 232 */ |
| 99 | u8 raw_bkops_status; /* 246 */ | ||
| 96 | u8 raw_sectors[4]; /* 212 - 4 bytes */ | 100 | u8 raw_sectors[4]; /* 212 - 4 bytes */ |
| 97 | 101 | ||
| 98 | unsigned int feature_support; | 102 | unsigned int feature_support; |
| @@ -226,6 +230,7 @@ struct mmc_card { | |||
| 226 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ | 230 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ |
| 227 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ | 231 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ |
| 228 | #define MMC_STATE_SLEEP (1<<9) /* card is in sleep state */ | 232 | #define MMC_STATE_SLEEP (1<<9) /* card is in sleep state */ |
| 233 | #define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */ | ||
| 229 | unsigned int quirks; /* card quirks */ | 234 | unsigned int quirks; /* card quirks */ |
| 230 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ | 235 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ |
| 231 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ | 236 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ |
| @@ -393,6 +398,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
| 393 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) | 398 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) |
| 394 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) | 399 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) |
| 395 | #define mmc_card_is_sleep(c) ((c)->state & MMC_STATE_SLEEP) | 400 | #define mmc_card_is_sleep(c) ((c)->state & MMC_STATE_SLEEP) |
| 401 | #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) | ||
| 396 | 402 | ||
| 397 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 403 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
| 398 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | 404 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) |
| @@ -405,7 +411,9 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
| 405 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) | 411 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) |
| 406 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) | 412 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) |
| 407 | #define mmc_card_set_sleep(c) ((c)->state |= MMC_STATE_SLEEP) | 413 | #define mmc_card_set_sleep(c) ((c)->state |= MMC_STATE_SLEEP) |
| 414 | #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) | ||
| 408 | 415 | ||
| 416 | #define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) | ||
| 409 | #define mmc_card_clr_sleep(c) ((c)->state &= ~MMC_STATE_SLEEP) | 417 | #define mmc_card_clr_sleep(c) ((c)->state &= ~MMC_STATE_SLEEP) |
| 410 | /* | 418 | /* |
| 411 | * Quirk add/remove for MMC products. | 419 | * Quirk add/remove for MMC products. |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 1b431c728b9a..9b9cdafc7737 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
| @@ -134,6 +134,8 @@ struct mmc_host; | |||
| 134 | struct mmc_card; | 134 | struct mmc_card; |
| 135 | struct mmc_async_req; | 135 | struct mmc_async_req; |
| 136 | 136 | ||
| 137 | extern int mmc_stop_bkops(struct mmc_card *); | ||
| 138 | extern int mmc_read_bkops_status(struct mmc_card *); | ||
| 137 | extern struct mmc_async_req *mmc_start_req(struct mmc_host *, | 139 | extern struct mmc_async_req *mmc_start_req(struct mmc_host *, |
| 138 | struct mmc_async_req *, int *); | 140 | struct mmc_async_req *, int *); |
| 139 | extern int mmc_interrupt_hpi(struct mmc_card *); | 141 | extern int mmc_interrupt_hpi(struct mmc_card *); |
| @@ -142,6 +144,8 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); | |||
| 142 | extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *); | 144 | extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *); |
| 143 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, | 145 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, |
| 144 | struct mmc_command *, int); | 146 | struct mmc_command *, int); |
| 147 | extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); | ||
| 148 | extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool); | ||
| 145 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); | 149 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); |
| 146 | 150 | ||
| 147 | #define MMC_ERASE_ARG 0x00000000 | 151 | #define MMC_ERASE_ARG 0x00000000 |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index d425cab144d9..01e4b394029b 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
| @@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode) | |||
| 139 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ | 139 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ |
| 140 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ | 140 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ |
| 141 | #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ | 141 | #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ |
| 142 | #define R1_EXCEPTION_EVENT (1 << 6) /* sx, a */ | ||
| 142 | #define R1_APP_CMD (1 << 5) /* sr, c */ | 143 | #define R1_APP_CMD (1 << 5) /* sr, c */ |
| 143 | 144 | ||
| 144 | #define R1_STATE_IDLE 0 | 145 | #define R1_STATE_IDLE 0 |
| @@ -274,12 +275,15 @@ struct _mmc_csd { | |||
| 274 | #define EXT_CSD_FLUSH_CACHE 32 /* W */ | 275 | #define EXT_CSD_FLUSH_CACHE 32 /* W */ |
| 275 | #define EXT_CSD_CACHE_CTRL 33 /* R/W */ | 276 | #define EXT_CSD_CACHE_CTRL 33 /* R/W */ |
| 276 | #define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ | 277 | #define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ |
| 278 | #define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO */ | ||
| 277 | #define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ | 279 | #define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ |
| 278 | #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ | 280 | #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ |
| 279 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ | 281 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ |
| 280 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ | 282 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ |
| 281 | #define EXT_CSD_HPI_MGMT 161 /* R/W */ | 283 | #define EXT_CSD_HPI_MGMT 161 /* R/W */ |
| 282 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ | 284 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ |
| 285 | #define EXT_CSD_BKOPS_EN 163 /* R/W */ | ||
| 286 | #define EXT_CSD_BKOPS_START 164 /* W */ | ||
| 283 | #define EXT_CSD_SANITIZE_START 165 /* W */ | 287 | #define EXT_CSD_SANITIZE_START 165 /* W */ |
| 284 | #define EXT_CSD_WR_REL_PARAM 166 /* RO */ | 288 | #define EXT_CSD_WR_REL_PARAM 166 /* RO */ |
| 285 | #define EXT_CSD_BOOT_WP 173 /* R/W */ | 289 | #define EXT_CSD_BOOT_WP 173 /* R/W */ |
| @@ -313,11 +317,13 @@ struct _mmc_csd { | |||
| 313 | #define EXT_CSD_PWR_CL_200_360 237 /* RO */ | 317 | #define EXT_CSD_PWR_CL_200_360 237 /* RO */ |
| 314 | #define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ | 318 | #define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ |
| 315 | #define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ | 319 | #define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ |
| 320 | #define EXT_CSD_BKOPS_STATUS 246 /* RO */ | ||
| 316 | #define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ | 321 | #define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ |
| 317 | #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ | 322 | #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ |
| 318 | #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ | 323 | #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ |
| 319 | #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ | 324 | #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ |
| 320 | #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ | 325 | #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ |
| 326 | #define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ | ||
| 321 | #define EXT_CSD_HPI_FEATURES 503 /* RO */ | 327 | #define EXT_CSD_HPI_FEATURES 503 /* RO */ |
| 322 | 328 | ||
| 323 | /* | 329 | /* |
| @@ -378,6 +384,19 @@ struct _mmc_csd { | |||
| 378 | #define EXT_CSD_PWR_CL_8BIT_SHIFT 4 | 384 | #define EXT_CSD_PWR_CL_8BIT_SHIFT 4 |
| 379 | #define EXT_CSD_PWR_CL_4BIT_SHIFT 0 | 385 | #define EXT_CSD_PWR_CL_4BIT_SHIFT 0 |
| 380 | /* | 386 | /* |
| 387 | * EXCEPTION_EVENT_STATUS field | ||
| 388 | */ | ||
| 389 | #define EXT_CSD_URGENT_BKOPS BIT(0) | ||
| 390 | #define EXT_CSD_DYNCAP_NEEDED BIT(1) | ||
| 391 | #define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2) | ||
| 392 | #define EXT_CSD_PACKED_FAILURE BIT(3) | ||
| 393 | |||
| 394 | /* | ||
| 395 | * BKOPS status level | ||
| 396 | */ | ||
| 397 | #define EXT_CSD_BKOPS_LEVEL_2 0x2 | ||
| 398 | |||
| 399 | /* | ||
| 381 | * MMC_SWITCH access modes | 400 | * MMC_SWITCH access modes |
| 382 | */ | 401 | */ |
| 383 | 402 | ||
