From 642628a116c7df8a16c78aa17feb4e4d5b3e6d3a Mon Sep 17 00:00:00 2001 From: Newbyte Date: Sat, 18 Sep 2021 14:51:36 +0200 Subject: [PATCH] main/linux-postmarketos-exynos4: upgrade to 5.14.5 (MR 2532) Also add patches that should fix backlight control, add reboot modes, and work around a nasty eMMC corruption issue. [ci:skip-build]: already built successfully in CI --- ...backlight-control-support-for-s6e8aa.patch | 182 ++++++++++ main/linux-postmarketos-exynos4/APKBUILD | 14 +- .../add-reboot-modes-to-midas.patch | 61 ++++ .../config-postmarketos-exynos4.armv7 | 3 +- .../workaround-metadata-corruption-bug.patch | 342 ++++++++++++++++++ 5 files changed, 597 insertions(+), 5 deletions(-) create mode 100644 main/linux-postmarketos-exynos4/0001-drivers-drm-Add-backlight-control-support-for-s6e8aa.patch create mode 100644 main/linux-postmarketos-exynos4/add-reboot-modes-to-midas.patch create mode 100644 main/linux-postmarketos-exynos4/workaround-metadata-corruption-bug.patch diff --git a/main/linux-postmarketos-exynos4/0001-drivers-drm-Add-backlight-control-support-for-s6e8aa.patch b/main/linux-postmarketos-exynos4/0001-drivers-drm-Add-backlight-control-support-for-s6e8aa.patch new file mode 100644 index 000000000..3fef7d1c1 --- /dev/null +++ b/main/linux-postmarketos-exynos4/0001-drivers-drm-Add-backlight-control-support-for-s6e8aa.patch @@ -0,0 +1,182 @@ +From 26b78def11ca95209c1b3ee5519c594438d88f21 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Joonas=20Kylm=C3=A4l=C3=A4?= +Date: Tue, 3 Sep 2019 10:45:08 -0400 +Subject: [PATCH] drivers: drm: Add backlight control support for s6e8aa0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Joonas Kylmälä +--- + drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c | 83 ++++++++++++++----- + 1 file changed, 61 insertions(+), 22 deletions(-) + +diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +index 527371120266..a20369fa6b60 100644 +--- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c ++++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +@@ -3,6 +3,8 @@ + * MIPI-DSI based s6e8aa0 AMOLED LCD 5.3 inch panel driver. + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd ++ * Copyright (C) 2019 Paweł Chmiel ++ * Derived from drivers/gpu/drm/panel/panel-samsung-s6e63m0.c + * + * Inki Dae, + * Donghwa Lee, +@@ -12,6 +14,7 @@ + * Andrzej Hajda + */ + ++#include + #include + #include + #include +@@ -25,6 +28,7 @@ + #include + #include + #include ++#include + + #define LDI_MTP_LENGTH 24 + #define GAMMA_LEVEL_NUM 25 +@@ -84,6 +88,8 @@ + #define AID_2 (0x6) + #define AID_3 (0x7) + ++#define MAX_BRIGHTNESS (GAMMA_LEVEL_NUM - 1) ++ + typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN]; + + struct s6e8aa0_variant { +@@ -94,6 +100,7 @@ struct s6e8aa0_variant { + struct s6e8aa0 { + struct device *dev; + struct drm_panel panel; ++ struct backlight_device *bl_dev; + + struct regulator_bulk_data supplies[2]; + struct gpio_desc *reset_gpio; +@@ -109,7 +116,6 @@ struct s6e8aa0 { + u8 version; + u8 id; + const struct s6e8aa0_variant *variant; +- int brightness; + + /* This field is tested by functions directly accessing DSI bus before + * transfer, transfer is skipped if it is set. In case of transfer +@@ -320,9 +326,10 @@ static void s6e8aa0_etc_elvss_control(struct s6e8aa0 *ctx) + + static void s6e8aa0_elvss_nvm_set_v142(struct s6e8aa0 *ctx) + { ++ struct backlight_device *bd = ctx->bl_dev; + u8 br; + +- switch (ctx->brightness) { ++ switch (bd->props.brightness) { + case 0 ... 6: /* 30cd ~ 100cd */ + br = 0xdf; + break; +@@ -761,24 +768,6 @@ static const struct s6e8aa0_variant s6e8aa0_variants[] = { + } + }; + +-static void s6e8aa0_brightness_set(struct s6e8aa0 *ctx) +-{ +- const u8 *gamma; +- +- if (ctx->error) +- return; +- +- gamma = ctx->variant->gamma_tables[ctx->brightness]; +- +- if (ctx->version >= 142) +- s6e8aa0_elvss_nvm_set(ctx); +- +- s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN); +- +- /* update gamma table. */ +- s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03); +-} +- + static void s6e8aa0_panel_init(struct s6e8aa0 *ctx) + { + s6e8aa0_apply_level_1_key(ctx); +@@ -790,7 +779,7 @@ static void s6e8aa0_panel_init(struct s6e8aa0 *ctx) + + s6e8aa0_panel_cond_set(ctx); + s6e8aa0_display_condition_set(ctx); +- s6e8aa0_brightness_set(ctx); ++ backlight_enable(ctx->bl_dev); + s6e8aa0_etc_source_control(ctx); + s6e8aa0_etc_pentile_control(ctx); + s6e8aa0_elvss_nvm_set(ctx); +@@ -973,6 +962,54 @@ static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx) + return 0; + } + ++static int s6e8aa0_set_brightness(struct backlight_device *bd) ++{ ++ struct s6e8aa0 *ctx = bl_get_data(bd); ++ int brightness = bd->props.brightness; ++ const u8 *gamma; ++ ++ if (ctx->error) ++ return ctx->error; ++ ++ gamma = ctx->variant->gamma_tables[brightness]; ++ ++ if (ctx->version >= 142) ++ s6e8aa0_elvss_nvm_set(ctx); ++ ++ s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN); ++ ++ /* update gamma table. */ ++ s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03); ++ ++ return s6e8aa0_clear_error(ctx); ++} ++ ++static const struct backlight_ops s6e8aa0_backlight_ops = { ++ .update_status = s6e8aa0_set_brightness, ++}; ++ ++static int s6e8aa0_backlight_register(struct s6e8aa0 *ctx) ++{ ++ struct backlight_properties props = { ++ .type = BACKLIGHT_RAW, ++ .brightness = MAX_BRIGHTNESS, ++ .max_brightness = MAX_BRIGHTNESS ++ }; ++ struct device *dev = ctx->dev; ++ int ret = 0; ++ ++ ctx->bl_dev = devm_backlight_device_register(dev, "panel", dev, ctx, ++ &s6e8aa0_backlight_ops, ++ &props); ++ if (IS_ERR(ctx->bl_dev)) { ++ ret = PTR_ERR(ctx->bl_dev); ++ DRM_DEV_ERROR(dev, "error registering backlight device (%d)\n", ++ ret); ++ } ++ ++ return ret; ++} ++ + static int s6e8aa0_probe(struct mipi_dsi_device *dsi) + { + struct device *dev = &dsi->dev; +@@ -1014,7 +1051,9 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi) + return PTR_ERR(ctx->reset_gpio); + } + +- ctx->brightness = GAMMA_LEVEL_NUM - 1; ++ ret = s6e8aa0_backlight_register(ctx); ++ if (ret < 0) ++ return ret; + + drm_panel_init(&ctx->panel, dev, &s6e8aa0_drm_funcs, + DRM_MODE_CONNECTOR_DSI); +-- +2.31.1 + diff --git a/main/linux-postmarketos-exynos4/APKBUILD b/main/linux-postmarketos-exynos4/APKBUILD index 531c4141b..bfd0843f9 100644 --- a/main/linux-postmarketos-exynos4/APKBUILD +++ b/main/linux-postmarketos-exynos4/APKBUILD @@ -3,8 +3,8 @@ # Kernel config based on: arch/arm/configs/exynos_defconfig pkgname=linux-postmarketos-exynos4 -pkgver=5.14 -pkgrel=1 +pkgver=5.14.5 +pkgrel=0 pkgdesc="Mainline kernel fork for Samsung Exynos4 devices" arch="armv7" _carch="arm" @@ -28,8 +28,11 @@ source=" https://cdn.kernel.org/pub/linux/kernel/v${_kernver%%.*}.x/linux-$_kernver.tar.xz $_config 0001-ARM-decompressor-Flush-tlb-before-swiching-domain-0-.patch + 0001-drivers-drm-Add-backlight-control-support-for-s6e8aa.patch 0001-power-supply-max17042_battery-use-VF-SOC-register-fo.patch 0001-power_supply-max77693-change-the-supply-type-to-POWE.patch + add-reboot-modes-to-midas.patch + workaround-metadata-corruption-bug.patch initramfs.list init " @@ -69,11 +72,14 @@ package() { } sha512sums=" -8e4f3ec3d36f774280f75dc7b004a43e09417af58f12e9c9f8348976659d4cfda7ad905f306f43fed66a27922e5c45db22e46bbfa7a0b9f365012380de3b6f64 linux-5.14.tar.xz -15fbc2cdc569b35e46a9c30ee49a6642f32284a606bb4e94177d0fd25036c799a345de4c9da5fadaef3c402c36748225f63f1a157fccff05c684d7dee667ff7e config-postmarketos-exynos4.armv7 +8213a77210a1dc58adf60bc6afe7d6a5e2931fd838f30683bb6503286b3d291ee01ae1f60adc426a36a03d857c18a5fb4d156041aed4e1542d3456e9e459bd1f linux-5.14.5.tar.xz +445f6a42d598ab8388f1176aa0825d632007886eea9084ee7f79405b29742936b6ecd8b07b3fa6505e691d36b09ccb12e7381bb6b1dbca3fe7c55416b32d2f2a config-postmarketos-exynos4.armv7 4bb111db4396a1981ad0883737c6594ca93701699846298b940d2ea202c666be0158a0f9ddc5b95b9147fa4cfe62639512ae78e9315f8d975b379ccc4e15da36 0001-ARM-decompressor-Flush-tlb-before-swiching-domain-0-.patch +4d949df3906b4c7e13ae38345f8a25ec438e18b429d96d42486bb95d0cdc65d1fb68a8cd366e4040ff398633015bbd4db72e2327ad936c3a0069361392923fe1 0001-drivers-drm-Add-backlight-control-support-for-s6e8aa.patch 166fe4dff1cdc451a9a32a5240adb93b534b8c576c5ac8d995401ebbf676385a6d8b5a6a21f556df588dee41cc4e5b8ede9eff3dd4c7835c0ca374882784d42e 0001-power-supply-max17042_battery-use-VF-SOC-register-fo.patch e581eb55eb4cdfdac2cbe713a5044077a9b2f15881f0bed03cc89ecb1e38d19a1c9cfbaf53ee184c4a64b10bfe071e289f4fb2230e2420e4f0042f1f301a325c 0001-power_supply-max77693-change-the-supply-type-to-POWE.patch +4b1e0db3cb1ea369eb6b28356deaf660e3c6e73a043069dbfbe17b5b5237e854f4e400b484b4ca77a2810ecc0edaec80205c28c6793fcdc031d366b25c1b59f6 add-reboot-modes-to-midas.patch +237f0931adfdafa57f3f194281fd28ed47b3e42636feeb7ffe4d860f2468070d399bf2d8fba075d8eec3047252573009671b45cfafc9b9de273391090f39f3e4 workaround-metadata-corruption-bug.patch aaff0332b90e1f9f62de1128cace934717336e54ab09de46477369fa808302482d97334e43a85ee8597c1bcab64d3484750103559fea2ce8cd51776156bf7591 initramfs.list 09f1f214a24300696809727a7b04378887c06ca6f40803ca51a12bf2176a360b2eb8632139d6a0722094e05cb2038bdb04018a1e3d33fc2697674552ade03bee init " diff --git a/main/linux-postmarketos-exynos4/add-reboot-modes-to-midas.patch b/main/linux-postmarketos-exynos4/add-reboot-modes-to-midas.patch new file mode 100644 index 000000000..789e8abcc --- /dev/null +++ b/main/linux-postmarketos-exynos4/add-reboot-modes-to-midas.patch @@ -0,0 +1,61 @@ +From 4b0c208b9506faafbcb06629b35b4cd8cf2636ff Mon Sep 17 00:00:00 2001 +From: Denis 'GNUtoo' Carikli +Date: Wed, 4 Nov 2020 00:06:26 +0100 +Subject: [WIP] ARM: dts: exynos: Add reboot modes to midas + +The values have been taken from the sec-reboot.c driver in +the 3.0.101 smdk4412 kernel used in LineageOS which is based +on Samsung source code releases for various devices. + +Only the strict minimum modes have been added: the S-Boot 4.0 +bootloader is nonfree, so exporting less well known modes could +potentially have unwanted consequences. + +TODO: +- After reboot to download, heimdall doesn't work while it works + with the SMDK4412 kernel. +- Fix reboot without arguments (Test: Try "Reboot system now" + in a recovery after rebooting to the recovery) + +Signed-off-by: Denis 'GNUtoo' Carikli +--- + arch/arm/boot/dts/exynos4412-midas.dtsi | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4412-midas.dtsi b/arch/arm/boot/dts/exynos4412-midas.dtsi +index 0645006..fb949f9 100644 +--- a/arch/arm/boot/dts/exynos4412-midas.dtsi ++++ b/arch/arm/boot/dts/exynos4412-midas.dtsi +@@ -983,6 +983,29 @@ + &pmu_system_controller { + assigned-clocks = <&pmu_system_controller 0>; + assigned-clock-parents = <&clock CLK_XUSBXTI>; ++ ++ /* S-Boot 4.0 */ ++ #define S5P_INFORM2 0xF008 ++ #define S5P_INFORM3 0x080C ++ #define BOOT_MODE_PREFIX 0x12345670 ++ #define BOOT_NORMAL (BOOT_MODE_PREFIX | 0) ++ #define BOOT_DOWNLOAD (BOOT_MODE_PREFIX | 1) ++ #define BOOT_RECOVERY (BOOT_MODE_PREFIX | 4) ++ ++ no-lpm-mode { ++ compatible = "syscon-reboot"; ++ offset = ; ++ value = <0x12345678>; ++ }; ++ ++ reboot-mode { ++ compatible = "syscon-reboot-mode"; ++ offset = ; ++ mode-normal = ; ++ mode-recovery = ; ++ mode-bootloader = ; ++ mode-download = ; ++ }; + }; + + &pinctrl_0 { +-- +cgit v1.1 + diff --git a/main/linux-postmarketos-exynos4/config-postmarketos-exynos4.armv7 b/main/linux-postmarketos-exynos4/config-postmarketos-exynos4.armv7 index dcdf7deaa..c241c1e8f 100644 --- a/main/linux-postmarketos-exynos4/config-postmarketos-exynos4.armv7 +++ b/main/linux-postmarketos-exynos4/config-postmarketos-exynos4.armv7 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 5.14.0 Kernel Configuration +# Linux/arm 5.14.5 Kernel Configuration # CONFIG_CC_VERSION_TEXT="armv7-alpine-linux-musleabihf-gcc (Alpine 10.3.1_git20210625) 10.3.1 20210625" CONFIG_CC_IS_GCC=y @@ -4409,6 +4409,7 @@ CONFIG_ASHMEM=y # CONFIG_LTE_GDM724X is not set # CONFIG_GS_FPGABOOT is not set # CONFIG_UNISYSSPAR is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set # CONFIG_FB_TFT is not set # CONFIG_KS7010 is not set # CONFIG_PI433 is not set diff --git a/main/linux-postmarketos-exynos4/workaround-metadata-corruption-bug.patch b/main/linux-postmarketos-exynos4/workaround-metadata-corruption-bug.patch new file mode 100644 index 000000000..1211bec0b --- /dev/null +++ b/main/linux-postmarketos-exynos4/workaround-metadata-corruption-bug.patch @@ -0,0 +1,342 @@ +From 310f85dddffcb1070bf291ca8a97ce17e849828f Mon Sep 17 00:00:00 2001 +From: belgin +Date: Tue, 29 Jun 2021 20:31:12 +0300 +Subject: mmc: core: Workaround VTU00M 0xf1 FTL metadata corruption bug + +Some versions of the 0xf1 revision of the firmware of the +VTU00M eMMC from Samsung have a bug that triggers an FTL +metadata corruption. + +These eMMC are used at least in the Samsung Galaxy SIII +(GT-I9300) and Galaxy Note II (GT-N7100). + +The corrupted FTL metadata can make the eMMC CPU crash. + +In practice as the eMMC has several hardware partitions, in +some cases the bootloader hadware partition (which is used +to store the phone bootloader in the Galaxy SIII and Note II) +still works, while the main hardware partition (that contains +the phone operating system) doesn't. + +In other cases the eMMC crashes during the very begining of +its boot procedure. In that case the phones botloaders can't +be loaded anymore, which results in a black screen and no +visible signs that the phone has been powered on. + +This patch has been ported from the Samsung patch made to +address this issue. + +It uses MMC vendor specific commands to patch the eMMC +firmware in RAM. The patch hangs the eMMC CPU right before +the corruption is about to happen. + +So while it's not ideal, it still better to have devices +hanging, even repetedly, than breaking devices completely. + +Since VTU00M eMMC firmwares are not free software nor +redistributable, we cannot simply dump newer firmwares, +and redistribute them. In addition the only tested way +to do a firmware update destroys all the data on the +eMMC (including the FTL metadata as well) in the process. + +A proper fix would be to write a compatible free software +eMMC firmware and to investigate the firmware update command +that doesn't erase the FTL metadata and/or the data, however +this could be quite time consuming. + +References: +- https://media.ccc.de/v/34c3-8784-emmc_hacking_or_how_i_fixed_long-dead_galaxy_s3_phones + +TODO: +- Adapt this patch to use the SD/eMMC hook system for eMMC cards. +- upstream it + +Signed-off-by: belgin +GNUtoo: Rewrite the commit message +Signed-off-by: Denis 'GNUtoo' Carikli +--- + drivers/mmc/core/mmc.c | 17 ++++ + drivers/mmc/core/mmc_ops.c | 206 +++++++++++++++++++++++++++++++++++++++++++++ + include/linux/mmc/card.h | 1 + + include/linux/mmc/core.h | 3 + + 4 files changed, 227 insertions(+) + +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index 7494d59..8f570fb 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1895,6 +1895,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + if (!oldcard) + host->card = card; + ++ err = mmc_start_movi_operation(host->card); ++ if (err) { ++ pr_warn("%s: movi operation failed\n", mmc_hostname(host)); ++ goto free_card; ++ } ++ + return 0; + + free_card: +@@ -2274,6 +2280,17 @@ int mmc_attach_mmc(struct mmc_host *host) + if (err) + goto remove_card; + ++ if (!strncmp(host->card->cid.prod_name, "VTU00M", 6) && ++ (host->card->cid.prv == 0xf1) && ++ (mmc_start_movi_smart(host->card) == 0x2)) ++ host->card->movi_ops = 0x2; ++ ++ err = mmc_start_movi_operation(host->card); ++ if (err) { ++ pr_warn("%s: movi operation failed\n", mmc_hostname(host)); ++ goto remove_card; ++ } ++ + mmc_claim_host(host); + return 0; + +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index ebad70e..0f80dd4 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -829,6 +829,212 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width) + return mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); + } + ++static int mmc_send_cmd(struct mmc_host *host, ++ u32 opcode, u32 arg, unsigned int flags, u32 *resp) ++{ ++ int err; ++ struct mmc_command cmd; ++ ++ memset(&cmd, 0, sizeof(struct mmc_command)); ++ ++ cmd.opcode = opcode; ++ cmd.arg = arg; ++ cmd.flags = flags; ++ *resp = 0; ++ ++ err = mmc_wait_for_cmd(host, &cmd, 0); ++ ++ if (!err) ++ *resp = cmd.resp[0]; ++ else ++ printk(KERN_ERR "[CMD%d] FAILED!!\n", cmd.opcode); ++ ++ return err; ++} ++ ++static int mmc_movi_cmd(struct mmc_host *host, u32 arg) ++{ ++ int err; ++ u32 resp; ++ ++ err = mmc_send_cmd(host, 62, arg, ++ MMC_RSP_R1B | MMC_CMD_AC, &resp); ++ mdelay(10); ++ ++ if (!err) ++ do { ++ err = mmc_send_cmd(host, MMC_SEND_STATUS, ++ host->card->rca << 16, ++ MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC, ++ &resp); ++ if (err) { ++ printk(KERN_ERR "CMD13(VC) failed\n"); ++ break; ++ } ++ /*wait until READY_FOR_DATA*/ ++ } while (!(resp & 1<<8)); ++ ++ return err; ++} ++ ++static int mmc_movi_erase_cmd(struct mmc_host *host, u32 arg1, u32 arg2) ++{ ++ int err; ++ u32 resp; ++ ++ err = mmc_send_cmd(host, MMC_ERASE_GROUP_START, arg1, ++ MMC_RSP_R1 | MMC_CMD_AC, &resp); ++ if (err) ++ return err; ++ ++ err = mmc_send_cmd(host, MMC_ERASE_GROUP_END, arg2, ++ MMC_RSP_R1 | MMC_CMD_AC, &resp); ++ if (err) ++ return err; ++ ++ err = mmc_send_cmd(host, MMC_ERASE, 0, ++ MMC_RSP_R1B | MMC_CMD_AC, &resp); ++ if (!err) ++ do { ++ err = mmc_send_cmd(host, MMC_SEND_STATUS, ++ host->card->rca << 16, ++ MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC, ++ &resp); ++ if (err) { ++ printk(KERN_ERR "CMD13(VC) failed\n"); ++ break; ++ } ++ /*wait until READY_FOR_DATA*/ ++ } while (!(resp & 1<<8)); ++ ++ return err; ++} ++ ++ ++static int mmc_movi_read_req(struct mmc_card *card, ++ void *data_buf, u32 arg, u32 blocks) ++{ ++ struct mmc_request mrq = {0}; ++ struct mmc_command cmd = {0}; ++ struct mmc_data data = {0}; ++ struct scatterlist sg; ++ ++ /*send request*/ ++ mrq.cmd = &cmd; ++ mrq.data = &data; ++ ++ if (blocks > 1) ++ cmd.opcode = MMC_READ_MULTIPLE_BLOCK; ++ else ++ cmd.opcode = MMC_READ_SINGLE_BLOCK; ++ cmd.arg = arg; ++ ++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; ++ ++ data.blksz = 512; ++ data.blocks = blocks; ++ data.flags = MMC_DATA_READ; ++ data.sg = &sg; ++ data.sg_len = 1; ++ ++ sg_init_one(&sg, data_buf, data.blksz * data.blocks); ++ ++ mmc_set_data_timeout(&data, card); ++ ++ mmc_wait_for_req(card->host, &mrq); ++ ++ if (cmd.error) ++ return cmd.error; ++ ++ if (data.error) ++ return data.error; ++ ++ return 0; ++} ++ ++int mmc_start_movi_smart(struct mmc_card *card) ++{ ++ int err; ++ u8 data_buf[512]; ++ u32 date = 0; ++ ++ err = mmc_movi_cmd(card->host, 0xEFAC62EC); ++ if (err) ++ return err; ++ ++ err = mmc_movi_cmd(card->host, 0x0000CCEE); ++ if (err) ++ return err; ++ ++ err = mmc_movi_read_req(card, (void *)data_buf, 0x1000, 1); ++ if (err) ++ return err; ++ ++ err = mmc_movi_cmd(card->host, 0xEFAC62EC); ++ if (err) ++ return err; ++ ++ err = mmc_movi_cmd(card->host, 0x00DECCEE); ++ if (err) ++ return err; ++ ++ date = ((data_buf[327] << 24) | (data_buf[326] << 16) | ++ (data_buf[325] << 8) | data_buf[324]); ++ ++ if (date != 0x20120413) { ++ err = -1; ++ return err; ++ } ++ ++ return 0x2; ++} ++EXPORT_SYMBOL_GPL(mmc_start_movi_smart); ++ ++int mmc_start_movi_operation(struct mmc_card *card) ++{ ++ int err = 0; ++ ++ if (card->movi_ops != 0x2) ++ return 0; ++ ++ err = mmc_movi_cmd(card->host, 0xEFAC62EC); ++ if (err) ++ return err; ++ err = mmc_movi_cmd(card->host, 0x10210000); ++ if (err) ++ return err; ++ ++ err = mmc_movi_erase_cmd(card->host, 0x00040300, 0x4A03B510); ++ if (err) ++ return err; ++ err = mmc_movi_erase_cmd(card->host, 0x00040304, 0x28004790); ++ if (err) ++ return err; ++ err = mmc_movi_erase_cmd(card->host, 0x00040308, 0xE7FED100); ++ if (err) ++ return err; ++ err = mmc_movi_erase_cmd(card->host, 0x0004030C, 0x0000BD10); ++ if (err) ++ return err; ++ err = mmc_movi_erase_cmd(card->host, 0x00040310, 0x00059D73); ++ if (err) ++ return err; ++ err = mmc_movi_erase_cmd(card->host, 0x0005C7EA, 0xFD89F7E3); ++ if (err) ++ return err; ++ ++ err = mmc_movi_cmd(card->host, 0xEFAC62EC); ++ if (err) ++ return err; ++ err = mmc_movi_cmd(card->host, 0x00DECCEE); ++ if (err) ++ return err; ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(mmc_start_movi_operation); ++ ++ + static int mmc_send_hpi_cmd(struct mmc_card *card) + { + unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time; +diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h +index 42df06c..4dc435d 100644 +--- a/include/linux/mmc/card.h ++++ b/include/linux/mmc/card.h +@@ -313,6 +313,7 @@ struct mmc_card { + + unsigned int bouncesz; /* Bounce buffer size */ + struct workqueue_struct *complete_wq; /* Private workqueue */ ++ unsigned int movi_ops; + }; + + static inline bool mmc_large_sector(struct mmc_card *card) +diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h +index 29aa507..80cbc1a 100644 +--- a/include/linux/mmc/core.h ++++ b/include/linux/mmc/core.h +@@ -174,4 +174,7 @@ int mmc_hw_reset(struct mmc_host *host); + int mmc_sw_reset(struct mmc_host *host); + void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card); + ++int mmc_start_movi_smart(struct mmc_card *card); ++int mmc_start_movi_operation(struct mmc_card *card); ++ + #endif /* LINUX_MMC_CORE_H */ +-- +cgit v1.1 +