1 /* 2 * Copyright (C) 2015, Samsung Electronics Co., Ltd. 3 * 4 * Author: Marek Szyprowski <m.szyprowski@samsung.com> 5 * 6 * License terms: GNU General Public License (GPL) version 2 7 * 8 * Simple eMMC hardware reset provider 9 */ 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> 17 18 #include <linux/mmc/host.h> 19 20 #include "pwrseq.h" 21 22 struct mmc_pwrseq_emmc { 23 struct mmc_pwrseq pwrseq; 24 struct notifier_block reset_nb; 25 struct gpio_desc *reset_gpio; 26 }; 27 28 static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) 29 { 30 gpiod_set_value(pwrseq->reset_gpio, 1); 31 udelay(1); 32 gpiod_set_value(pwrseq->reset_gpio, 0); 33 udelay(200); 34 } 35 36 static void mmc_pwrseq_emmc_reset(struct mmc_host *host) 37 { 38 struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, 39 struct mmc_pwrseq_emmc, pwrseq); 40 41 __mmc_pwrseq_emmc_reset(pwrseq); 42 } 43 44 static void mmc_pwrseq_emmc_free(struct mmc_host *host) 45 { 46 struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, 47 struct mmc_pwrseq_emmc, pwrseq); 48 49 unregister_restart_handler(&pwrseq->reset_nb); 50 gpiod_put(pwrseq->reset_gpio); 51 kfree(pwrseq); 52 } 53 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, 57 }; 58 59 static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, 60 unsigned long mode, void *cmd) 61 { 62 struct mmc_pwrseq_emmc *pwrseq = container_of(this, 63 struct mmc_pwrseq_emmc, reset_nb); 64 65 __mmc_pwrseq_emmc_reset(pwrseq); 66 return NOTIFY_DONE; 67 } 68 69 struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, 70 struct device *dev) 71 { 72 struct mmc_pwrseq_emmc *pwrseq; 73 int ret = 0; 74 75 pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL); 76 if (!pwrseq) 77 return ERR_PTR(-ENOMEM); 78 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); 82 goto free; 83 } 84 85 /* 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. 89 */ 90 pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; 91 pwrseq->reset_nb.priority = 255; 92 register_restart_handler(&pwrseq->reset_nb); 93 94 pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; 95 96 return &pwrseq->pwrseq; 97 free: 98 kfree(pwrseq); 99 return ERR_PTR(ret); 100 } 101