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/init.h> 13 #include <linux/platform_device.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/device.h> 17 #include <linux/err.h> 18 #include <linux/gpio/consumer.h> 19 #include <linux/reboot.h> 20 21 #include <linux/mmc/host.h> 22 23 #include "pwrseq.h" 24 25 struct mmc_pwrseq_emmc { 26 struct mmc_pwrseq pwrseq; 27 struct notifier_block reset_nb; 28 struct gpio_desc *reset_gpio; 29 }; 30 31 #define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) 32 33 static void mmc_pwrseq_emmc_reset(struct mmc_host *host) 34 { 35 struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); 36 37 gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); 38 udelay(1); 39 gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); 40 udelay(200); 41 } 42 43 static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, 44 unsigned long mode, void *cmd) 45 { 46 struct mmc_pwrseq_emmc *pwrseq = container_of(this, 47 struct mmc_pwrseq_emmc, reset_nb); 48 gpiod_set_value(pwrseq->reset_gpio, 1); 49 udelay(1); 50 gpiod_set_value(pwrseq->reset_gpio, 0); 51 udelay(200); 52 53 return NOTIFY_DONE; 54 } 55 56 static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { 57 .reset = mmc_pwrseq_emmc_reset, 58 }; 59 60 static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) 61 { 62 struct mmc_pwrseq_emmc *pwrseq; 63 struct device *dev = &pdev->dev; 64 65 pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); 66 if (!pwrseq) 67 return -ENOMEM; 68 69 pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 70 if (IS_ERR(pwrseq->reset_gpio)) 71 return PTR_ERR(pwrseq->reset_gpio); 72 73 if (!gpiod_cansleep(pwrseq->reset_gpio)) { 74 /* 75 * register reset handler to ensure emmc reset also from 76 * emergency_reboot(), priority 255 is the highest priority 77 * so it will be executed before any system reboot handler. 78 */ 79 pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; 80 pwrseq->reset_nb.priority = 255; 81 register_restart_handler(&pwrseq->reset_nb); 82 } else { 83 dev_notice(dev, "EMMC reset pin tied to a sleepy GPIO driver; reset on emergency-reboot disabled\n"); 84 } 85 86 pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; 87 pwrseq->pwrseq.dev = dev; 88 pwrseq->pwrseq.owner = THIS_MODULE; 89 platform_set_drvdata(pdev, pwrseq); 90 91 return mmc_pwrseq_register(&pwrseq->pwrseq); 92 } 93 94 static int mmc_pwrseq_emmc_remove(struct platform_device *pdev) 95 { 96 struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev); 97 98 unregister_restart_handler(&pwrseq->reset_nb); 99 mmc_pwrseq_unregister(&pwrseq->pwrseq); 100 101 return 0; 102 } 103 104 static const struct of_device_id mmc_pwrseq_emmc_of_match[] = { 105 { .compatible = "mmc-pwrseq-emmc",}, 106 {/* sentinel */}, 107 }; 108 109 MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match); 110 111 static struct platform_driver mmc_pwrseq_emmc_driver = { 112 .probe = mmc_pwrseq_emmc_probe, 113 .remove = mmc_pwrseq_emmc_remove, 114 .driver = { 115 .name = "pwrseq_emmc", 116 .of_match_table = mmc_pwrseq_emmc_of_match, 117 }, 118 }; 119 120 module_platform_driver(mmc_pwrseq_emmc_driver); 121 MODULE_LICENSE("GPL v2"); 122