2 * Copyright (C) 2015, Samsung Electronics Co., Ltd.
4 * Author: Marek Szyprowski <m.szyprowski@samsung.com>
6 * License terms: GNU General Public License (GPL) version 2
8 * Simple eMMC hardware reset provider
10 #include <linux/delay.h>
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/device.h>
14 #include <linux/err.h>
15 #include <linux/gpio/consumer.h>
16 #include <linux/reboot.h>
18 #include <linux/mmc/host.h>
22 struct mmc_pwrseq_emmc
{
23 struct mmc_pwrseq pwrseq
;
24 struct notifier_block reset_nb
;
25 struct gpio_desc
*reset_gpio
;
28 static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc
*pwrseq
)
30 gpiod_set_value(pwrseq
->reset_gpio
, 1);
32 gpiod_set_value(pwrseq
->reset_gpio
, 0);
36 static void mmc_pwrseq_emmc_reset(struct mmc_host
*host
)
38 struct mmc_pwrseq_emmc
*pwrseq
= container_of(host
->pwrseq
,
39 struct mmc_pwrseq_emmc
, pwrseq
);
41 __mmc_pwrseq_emmc_reset(pwrseq
);
44 static void mmc_pwrseq_emmc_free(struct mmc_host
*host
)
46 struct mmc_pwrseq_emmc
*pwrseq
= container_of(host
->pwrseq
,
47 struct mmc_pwrseq_emmc
, pwrseq
);
49 unregister_restart_handler(&pwrseq
->reset_nb
);
50 gpiod_put(pwrseq
->reset_gpio
);
54 static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops
= {
55 .post_power_on
= mmc_pwrseq_emmc_reset
,
56 .free
= mmc_pwrseq_emmc_free
,
59 static int mmc_pwrseq_emmc_reset_nb(struct notifier_block
*this,
60 unsigned long mode
, void *cmd
)
62 struct mmc_pwrseq_emmc
*pwrseq
= container_of(this,
63 struct mmc_pwrseq_emmc
, reset_nb
);
65 __mmc_pwrseq_emmc_reset(pwrseq
);
69 struct mmc_pwrseq
*mmc_pwrseq_emmc_alloc(struct mmc_host
*host
,
72 struct mmc_pwrseq_emmc
*pwrseq
;
75 pwrseq
= kzalloc(sizeof(struct mmc_pwrseq_emmc
), GFP_KERNEL
);
77 return ERR_PTR(-ENOMEM
);
79 pwrseq
->reset_gpio
= gpiod_get(dev
, "reset", GPIOD_OUT_LOW
);
80 if (IS_ERR(pwrseq
->reset_gpio
)) {
81 ret
= PTR_ERR(pwrseq
->reset_gpio
);
86 * register reset handler to ensure emmc reset also from
87 * emergency_reboot(), priority 255 is the highest priority
88 * so it will be executed before any system reboot handler.
90 pwrseq
->reset_nb
.notifier_call
= mmc_pwrseq_emmc_reset_nb
;
91 pwrseq
->reset_nb
.priority
= 255;
92 register_restart_handler(&pwrseq
->reset_nb
);
94 pwrseq
->pwrseq
.ops
= &mmc_pwrseq_emmc_ops
;
96 return &pwrseq
->pwrseq
;