linux/drivers/mmc/core/pwrseq_sd8787.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi chip
   4 *
   5 * Copyright (C) 2016 Matt Ranostay <matt@ranostay.consulting>
   6 *
   7 * Based on the original work pwrseq_simple.c
   8 *  Copyright (C) 2014 Linaro Ltd
   9 *  Author: Ulf Hansson <ulf.hansson@linaro.org>
  10 */
  11
  12#include <linux/delay.h>
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/platform_device.h>
  16#include <linux/module.h>
  17#include <linux/of.h>
  18#include <linux/slab.h>
  19#include <linux/device.h>
  20#include <linux/err.h>
  21#include <linux/gpio/consumer.h>
  22
  23#include <linux/mmc/host.h>
  24
  25#include "pwrseq.h"
  26
  27struct mmc_pwrseq_sd8787 {
  28        struct mmc_pwrseq pwrseq;
  29        struct gpio_desc *reset_gpio;
  30        struct gpio_desc *pwrdn_gpio;
  31        u32 reset_pwrdwn_delay_ms;
  32};
  33
  34#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq)
  35
  36static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
  37{
  38        struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
  39
  40        gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
  41
  42        msleep(pwrseq->reset_pwrdwn_delay_ms);
  43        gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
  44}
  45
  46static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
  47{
  48        struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
  49
  50        gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
  51        gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
  52}
  53
  54static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
  55        .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
  56        .power_off = mmc_pwrseq_sd8787_power_off,
  57};
  58
  59static const u32 sd8787_delay_ms = 300;
  60static const u32 wilc1000_delay_ms = 5;
  61
  62static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
  63        { .compatible = "mmc-pwrseq-sd8787", .data = &sd8787_delay_ms },
  64        { .compatible = "mmc-pwrseq-wilc1000", .data = &wilc1000_delay_ms },
  65        {/* sentinel */},
  66};
  67MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
  68
  69static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
  70{
  71        struct mmc_pwrseq_sd8787 *pwrseq;
  72        struct device *dev = &pdev->dev;
  73        const struct of_device_id *match;
  74
  75        pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
  76        if (!pwrseq)
  77                return -ENOMEM;
  78
  79        match = of_match_node(mmc_pwrseq_sd8787_of_match, pdev->dev.of_node);
  80        pwrseq->reset_pwrdwn_delay_ms = *(u32 *)match->data;
  81
  82        pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW);
  83        if (IS_ERR(pwrseq->pwrdn_gpio))
  84                return PTR_ERR(pwrseq->pwrdn_gpio);
  85
  86        pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
  87        if (IS_ERR(pwrseq->reset_gpio))
  88                return PTR_ERR(pwrseq->reset_gpio);
  89
  90        pwrseq->pwrseq.dev = dev;
  91        pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
  92        pwrseq->pwrseq.owner = THIS_MODULE;
  93        platform_set_drvdata(pdev, pwrseq);
  94
  95        return mmc_pwrseq_register(&pwrseq->pwrseq);
  96}
  97
  98static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
  99{
 100        struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
 101
 102        mmc_pwrseq_unregister(&pwrseq->pwrseq);
 103
 104        return 0;
 105}
 106
 107static struct platform_driver mmc_pwrseq_sd8787_driver = {
 108        .probe = mmc_pwrseq_sd8787_probe,
 109        .remove = mmc_pwrseq_sd8787_remove,
 110        .driver = {
 111                .name = "pwrseq_sd8787",
 112                .of_match_table = mmc_pwrseq_sd8787_of_match,
 113        },
 114};
 115
 116module_platform_driver(mmc_pwrseq_sd8787_driver);
 117MODULE_LICENSE("GPL v2");
 118