123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- From 302cd9b8a9f1f8a7735fabea3b9a7645dc40f9cc Mon Sep 17 00:00:00 2001
- From: Myy Miouyouyou <myy@miouyouyou.fr>
- Date: Sun, 7 Jan 2018 01:52:44 +0100
- Subject: [PATCH] drivers: mmc: dw-mci-rockchip: Handle ASUS Tinkerboard reboot
- On ASUS Tinkerboard systems, if the SDMMC hardware is shutdown before
- rebooting, the system will be dead, as the SDMMC is the only way to
- boot anything, and the hardware doesn't power up the SDMMC hardware
- automatically when rebooting.
- So, when using an ASUS Tinkerboard system, a new reboot handler is
- installed. This reboot handler takes care of powering the SDMMC
- hardware again before restarting the system, resolving the issue.
- The code was inspired by the pwrseq_emmc.c, which seems to overcome
- similar effects with eMMC hardware.
- Signed-off-by: Myy Miouyouyou <myy@miouyouyou.fr>
- ---
- drivers/mmc/host/dw_mmc-rockchip.c | 66 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 66 insertions(+)
- diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
- index a3f1c2b30..7eac1f221 100644
- --- a/drivers/mmc/host/dw_mmc-rockchip.c
- +++ b/drivers/mmc/host/dw_mmc-rockchip.c
- @@ -16,6 +16,11 @@
- #include <linux/pm_runtime.h>
- #include <linux/slab.h>
-
- +#include <linux/regulator/consumer.h>
- +#include <linux/reboot.h>
- +#include <linux/delay.h>
- +#include "../core/core.h"
- +
- #include "dw_mmc.h"
- #include "dw_mmc-pltfm.h"
-
- @@ -334,6 +339,66 @@ static const struct of_device_id dw_mci_rockchip_match[] = {
- };
- MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match);
-
- +struct dw_mci_rockchip_broken_boards_data {
- + struct notifier_block reset_nb;
- + struct platform_device *pdev;
- +};
- +
- +/* This reboot handler handles cases where disabling the SDMMC on
- + * reboot will cause the hardware to be unable to start correctly
- + * after rebooting.
- + *
- + * This happens with Tinkerboard systems...
- + */
- +static int dw_mci_rockchip_broken_boards_reset_nb(
- + struct notifier_block *this,
- + unsigned long mode, void *cmd)
- +{
- + struct dw_mci_rockchip_broken_boards_data const *data =
- + container_of(this,
- + struct dw_mci_rockchip_broken_boards_data,
- + reset_nb);
- + struct dw_mci *host = platform_get_drvdata(data->pdev);
- + struct mmc_host *mmc = host->slot->mmc;
- +
- + printk(KERN_ERR "Meow.\n");
- +
- + mmc_power_off(mmc);
- +
- + mdelay(20);
- +
- + if (!IS_ERR(mmc->supply.vmmc))
- + regulator_enable(mmc->supply.vmmc);
- +
- + if (!IS_ERR(mmc->supply.vqmmc))
- + regulator_set_voltage(mmc->supply.vqmmc, 3000000, 3300000);
- +
- + printk(KERN_ERR "woeM.\n");
- +
- + return NOTIFY_DONE;
- +}
- +
- +static void dw_mci_rockchip_register_broken_boards_reboot_handler(
- + struct platform_device *pdev)
- +{
- + struct dw_mci_rockchip_broken_boards_data *data;
- +
- + if (!of_machine_is_compatible("asus,rk3288-tinker"))
- + return;
- +
- + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- +
- + if (!data)
- + return;
- +
- + data->reset_nb.notifier_call =
- + dw_mci_rockchip_broken_boards_reset_nb;
- + data->reset_nb.priority = 255;
- + register_restart_handler(&data->reset_nb);
- +
- + data->pdev = pdev;
- +}
- +
- static int dw_mci_rockchip_probe(struct platform_device *pdev)
- {
- const struct dw_mci_drv_data *drv_data;
- @@ -361,6 +426,7 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
- }
-
- pm_runtime_put_autosuspend(&pdev->dev);
- + dw_mci_rockchip_register_broken_boards_reboot_handler(pdev);
-
- return 0;
- }
- --
- 2.14.1
|