Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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/slab.h>
 18#include <linux/device.h>
 19#include <linux/err.h>
 20#include <linux/gpio/consumer.h>
 21
 22#include <linux/mmc/host.h>
 23
 24#include "pwrseq.h"
 25
 26struct mmc_pwrseq_sd8787 {
 27	struct mmc_pwrseq pwrseq;
 28	struct gpio_desc *reset_gpio;
 29	struct gpio_desc *pwrdn_gpio;
 30};
 31
 32#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq)
 33
 34static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
 35{
 36	struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
 37
 38	gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
 39
 40	msleep(300);
 41	gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
 42}
 43
 44static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
 45{
 46	struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
 47
 48	gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
 49	gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
 50}
 51
 52static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
 53	.pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
 54	.power_off = mmc_pwrseq_sd8787_power_off,
 55};
 56
 57static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
 58	{ .compatible = "mmc-pwrseq-sd8787",},
 59	{/* sentinel */},
 60};
 61MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
 62
 63static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
 64{
 65	struct mmc_pwrseq_sd8787 *pwrseq;
 66	struct device *dev = &pdev->dev;
 67
 68	pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
 69	if (!pwrseq)
 70		return -ENOMEM;
 71
 72	pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW);
 73	if (IS_ERR(pwrseq->pwrdn_gpio))
 74		return PTR_ERR(pwrseq->pwrdn_gpio);
 75
 76	pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
 77	if (IS_ERR(pwrseq->reset_gpio))
 78		return PTR_ERR(pwrseq->reset_gpio);
 79
 80	pwrseq->pwrseq.dev = dev;
 81	pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
 82	pwrseq->pwrseq.owner = THIS_MODULE;
 83	platform_set_drvdata(pdev, pwrseq);
 84
 85	return mmc_pwrseq_register(&pwrseq->pwrseq);
 86}
 87
 88static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
 89{
 90	struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
 91
 92	mmc_pwrseq_unregister(&pwrseq->pwrseq);
 93
 94	return 0;
 95}
 96
 97static struct platform_driver mmc_pwrseq_sd8787_driver = {
 98	.probe = mmc_pwrseq_sd8787_probe,
 99	.remove = mmc_pwrseq_sd8787_remove,
100	.driver = {
101		.name = "pwrseq_sd8787",
102		.of_match_table = mmc_pwrseq_sd8787_of_match,
103	},
104};
105
106module_platform_driver(mmc_pwrseq_sd8787_driver);
107MODULE_LICENSE("GPL v2");