mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 20:23:57 +08:00
5716fb9bd9
Switch the SPI MMC driver to use GPIO descriptors internally and just look those up using the standard slot GPIO functions mmc_gpiod_request_cd() and mmc_gpiod_request_ro(). Make sure to request index 0 and 1 in accordance with the SPI MMC DT binding, and add the same GPIOs in machine descriptor tables on all boards that use SPI MMC in board files. The lines are flagged as GPIO_ACTIVE_[LOW|HIGH] as that is what they are, and since we can now rely on the descriptors to have the right polarity, we set the "override_active_level" to false in mmc_gpiod_request_cd() and mmc_gpiod_request_ro(). Cc: Hartley Sweeten <hsweeten@visionengravers.com> # Vision EP9307 Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
124 lines
3.0 KiB
C
124 lines
3.0 KiB
C
/*
|
|
* OpenFirmware bindings for the MMC-over-SPI driver
|
|
*
|
|
* Copyright (c) MontaVista Software, Inc. 2008.
|
|
*
|
|
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/device.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/spi/mmc_spi.h>
|
|
#include <linux/mmc/core.h>
|
|
#include <linux/mmc/host.h>
|
|
|
|
/* For archs that don't support NO_IRQ (such as mips), provide a dummy value */
|
|
#ifndef NO_IRQ
|
|
#define NO_IRQ 0
|
|
#endif
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
struct of_mmc_spi {
|
|
int detect_irq;
|
|
struct mmc_spi_platform_data pdata;
|
|
};
|
|
|
|
static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
|
|
{
|
|
return container_of(dev->platform_data, struct of_mmc_spi, pdata);
|
|
}
|
|
|
|
static int of_mmc_spi_init(struct device *dev,
|
|
irqreturn_t (*irqhandler)(int, void *), void *mmc)
|
|
{
|
|
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
|
|
|
|
return request_threaded_irq(oms->detect_irq, NULL, irqhandler,
|
|
IRQF_ONESHOT, dev_name(dev), mmc);
|
|
}
|
|
|
|
static void of_mmc_spi_exit(struct device *dev, void *mmc)
|
|
{
|
|
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
|
|
|
|
free_irq(oms->detect_irq, mmc);
|
|
}
|
|
|
|
struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
|
|
{
|
|
struct device *dev = &spi->dev;
|
|
struct device_node *np = dev->of_node;
|
|
struct of_mmc_spi *oms;
|
|
const __be32 *voltage_ranges;
|
|
int num_ranges;
|
|
int i;
|
|
|
|
if (dev->platform_data || !np)
|
|
return dev->platform_data;
|
|
|
|
oms = kzalloc(sizeof(*oms), GFP_KERNEL);
|
|
if (!oms)
|
|
return NULL;
|
|
|
|
voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
|
|
num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
|
|
if (!voltage_ranges || !num_ranges) {
|
|
dev_err(dev, "OF: voltage-ranges unspecified\n");
|
|
goto err_ocr;
|
|
}
|
|
|
|
for (i = 0; i < num_ranges; i++) {
|
|
const int j = i * 2;
|
|
u32 mask;
|
|
|
|
mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]),
|
|
be32_to_cpu(voltage_ranges[j + 1]));
|
|
if (!mask) {
|
|
dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
|
|
goto err_ocr;
|
|
}
|
|
oms->pdata.ocr_mask |= mask;
|
|
}
|
|
|
|
oms->detect_irq = irq_of_parse_and_map(np, 0);
|
|
if (oms->detect_irq != 0) {
|
|
oms->pdata.init = of_mmc_spi_init;
|
|
oms->pdata.exit = of_mmc_spi_exit;
|
|
} else {
|
|
oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
|
|
}
|
|
|
|
dev->platform_data = &oms->pdata;
|
|
return dev->platform_data;
|
|
err_ocr:
|
|
kfree(oms);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL(mmc_spi_get_pdata);
|
|
|
|
void mmc_spi_put_pdata(struct spi_device *spi)
|
|
{
|
|
struct device *dev = &spi->dev;
|
|
struct device_node *np = dev->of_node;
|
|
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
|
|
|
|
if (!dev->platform_data || !np)
|
|
return;
|
|
|
|
kfree(oms);
|
|
dev->platform_data = NULL;
|
|
}
|
|
EXPORT_SYMBOL(mmc_spi_put_pdata);
|