1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014 Linaro Ltd 4 * 5 * Author: Ulf Hansson <[email protected]> 6 * 7 * Simple MMC power sequence management 8 */ 9 #include <linux/clk.h> 10 #include <linux/init.h> 11 #include <linux/kernel.h> 12 #include <linux/platform_device.h> 13 #include <linux/module.h> 14 #include <linux/slab.h> 15 #include <linux/device.h> 16 #include <linux/err.h> 17 #include <linux/gpio/consumer.h> 18 #include <linux/delay.h> 19 #include <linux/property.h> 20 #include <linux/of.h> 21 #include <linux/reset.h> 22 23 #include <linux/mmc/host.h> 24 25 #include "pwrseq.h" 26 27 struct mmc_pwrseq_simple { 28 struct mmc_pwrseq pwrseq; 29 bool clk_enabled; 30 u32 post_power_on_delay_ms; 31 u32 power_off_delay_us; 32 struct clk *ext_clk; 33 struct gpio_descs *reset_gpios; 34 struct reset_control *reset_ctrl; 35 bool use_reset; 36 }; 37 38 #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) 39 40 static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, 41 int value) 42 { 43 struct gpio_descs *reset_gpios = pwrseq->reset_gpios; 44 45 if (!IS_ERR(reset_gpios)) { 46 unsigned long *values; 47 int nvalues = reset_gpios->ndescs; 48 49 values = bitmap_alloc(nvalues, GFP_KERNEL); 50 if (!values) 51 return; 52 53 if (value) 54 bitmap_fill(values, nvalues); 55 else 56 bitmap_zero(values, nvalues); 57 58 gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc, 59 reset_gpios->info, values); 60 61 bitmap_free(values); 62 } 63 } 64 65 static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) 66 { 67 struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); 68 69 if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) { 70 clk_prepare_enable(pwrseq->ext_clk); 71 pwrseq->clk_enabled = true; 72 } 73 74 if (pwrseq->use_reset) { 75 reset_control_deassert(pwrseq->reset_ctrl); 76 reset_control_assert(pwrseq->reset_ctrl); 77 } else 78 mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); 79 } 80 81 static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) 82 { 83 struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); 84 85 if (pwrseq->use_reset) 86 reset_control_deassert(pwrseq->reset_ctrl); 87 else 88 mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); 89 90 if (pwrseq->post_power_on_delay_ms) 91 msleep(pwrseq->post_power_on_delay_ms); 92 } 93 94 static void mmc_pwrseq_simple_power_off(struct mmc_host *host) 95 { 96 struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); 97 98 if (pwrseq->use_reset) 99 reset_control_assert(pwrseq->reset_ctrl); 100 else 101 mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); 102 103 if (pwrseq->power_off_delay_us) 104 usleep_range(pwrseq->power_off_delay_us, 105 2 * pwrseq->power_off_delay_us); 106 107 if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) { 108 clk_disable_unprepare(pwrseq->ext_clk); 109 pwrseq->clk_enabled = false; 110 } 111 } 112 113 static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { 114 .pre_power_on = mmc_pwrseq_simple_pre_power_on, 115 .post_power_on = mmc_pwrseq_simple_post_power_on, 116 .power_off = mmc_pwrseq_simple_power_off, 117 }; 118 119 static const struct of_device_id mmc_pwrseq_simple_of_match[] = { 120 { .compatible = "mmc-pwrseq-simple",}, 121 {/* sentinel */}, 122 }; 123 MODULE_DEVICE_TABLE(of, mmc_pwrseq_simple_of_match); 124 125 static int mmc_pwrseq_simple_probe(struct platform_device *pdev) 126 { 127 struct mmc_pwrseq_simple *pwrseq; 128 struct device *dev = &pdev->dev; 129 int ngpio; 130 131 pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); 132 if (!pwrseq) 133 return -ENOMEM; 134 135 pwrseq->ext_clk = devm_clk_get(dev, "ext_clock"); 136 if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) 137 return dev_err_probe(dev, PTR_ERR(pwrseq->ext_clk), "external clock not ready\n"); 138 139 ngpio = of_count_phandle_with_args(dev->of_node, "reset-gpios", "#gpio-cells"); 140 if (ngpio == 1) 141 pwrseq->use_reset = true; 142 143 if (pwrseq->use_reset) { 144 pwrseq->reset_ctrl = devm_reset_control_get_optional_shared(dev, NULL); 145 if (IS_ERR(pwrseq->reset_ctrl)) 146 return dev_err_probe(dev, PTR_ERR(pwrseq->reset_ctrl), 147 "reset control not ready\n"); 148 } else { 149 pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); 150 if (IS_ERR(pwrseq->reset_gpios) && 151 PTR_ERR(pwrseq->reset_gpios) != -ENOENT && 152 PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { 153 return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios), 154 "reset GPIOs not ready\n"); 155 } 156 } 157 158 device_property_read_u32(dev, "post-power-on-delay-ms", 159 &pwrseq->post_power_on_delay_ms); 160 device_property_read_u32(dev, "power-off-delay-us", 161 &pwrseq->power_off_delay_us); 162 163 pwrseq->pwrseq.dev = dev; 164 pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; 165 pwrseq->pwrseq.owner = THIS_MODULE; 166 platform_set_drvdata(pdev, pwrseq); 167 168 return mmc_pwrseq_register(&pwrseq->pwrseq); 169 } 170 171 static void mmc_pwrseq_simple_remove(struct platform_device *pdev) 172 { 173 struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); 174 175 mmc_pwrseq_unregister(&pwrseq->pwrseq); 176 } 177 178 static struct platform_driver mmc_pwrseq_simple_driver = { 179 .probe = mmc_pwrseq_simple_probe, 180 .remove = mmc_pwrseq_simple_remove, 181 .driver = { 182 .name = "pwrseq_simple", 183 .of_match_table = mmc_pwrseq_simple_of_match, 184 }, 185 }; 186 187 module_platform_driver(mmc_pwrseq_simple_driver); 188 MODULE_DESCRIPTION("Simple power sequence management for MMC"); 189 MODULE_LICENSE("GPL v2"); 190