cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

of_mmc_spi.c (2333B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * OpenFirmware bindings for the MMC-over-SPI driver
      4 *
      5 * Copyright (c) MontaVista Software, Inc. 2008.
      6 *
      7 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/device.h>
     13#include <linux/slab.h>
     14#include <linux/irq.h>
     15#include <linux/of.h>
     16#include <linux/of_irq.h>
     17#include <linux/spi/spi.h>
     18#include <linux/spi/mmc_spi.h>
     19#include <linux/mmc/core.h>
     20#include <linux/mmc/host.h>
     21
     22MODULE_LICENSE("GPL");
     23
     24struct of_mmc_spi {
     25	struct mmc_spi_platform_data pdata;
     26	int detect_irq;
     27};
     28
     29static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
     30{
     31	return container_of(dev->platform_data, struct of_mmc_spi, pdata);
     32}
     33
     34static int of_mmc_spi_init(struct device *dev,
     35			   irqreturn_t (*irqhandler)(int, void *), void *mmc)
     36{
     37	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
     38
     39	return request_threaded_irq(oms->detect_irq, NULL, irqhandler,
     40					IRQF_ONESHOT, dev_name(dev), mmc);
     41}
     42
     43static void of_mmc_spi_exit(struct device *dev, void *mmc)
     44{
     45	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
     46
     47	free_irq(oms->detect_irq, mmc);
     48}
     49
     50struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
     51{
     52	struct mmc_host *mmc = dev_get_drvdata(&spi->dev);
     53	struct device *dev = &spi->dev;
     54	struct of_mmc_spi *oms;
     55
     56	if (dev->platform_data || !dev_fwnode(dev))
     57		return dev->platform_data;
     58
     59	oms = kzalloc(sizeof(*oms), GFP_KERNEL);
     60	if (!oms)
     61		return NULL;
     62
     63	if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0)
     64		goto err_ocr;
     65
     66	oms->detect_irq = spi->irq;
     67	if (oms->detect_irq > 0) {
     68		oms->pdata.init = of_mmc_spi_init;
     69		oms->pdata.exit = of_mmc_spi_exit;
     70	} else {
     71		oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
     72	}
     73	if (device_property_read_bool(dev, "cap-sd-highspeed"))
     74		oms->pdata.caps |= MMC_CAP_SD_HIGHSPEED;
     75	if (device_property_read_bool(dev, "cap-mmc-highspeed"))
     76		oms->pdata.caps |= MMC_CAP_MMC_HIGHSPEED;
     77
     78	dev->platform_data = &oms->pdata;
     79	return dev->platform_data;
     80err_ocr:
     81	kfree(oms);
     82	return NULL;
     83}
     84EXPORT_SYMBOL(mmc_spi_get_pdata);
     85
     86void mmc_spi_put_pdata(struct spi_device *spi)
     87{
     88	struct device *dev = &spi->dev;
     89	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
     90
     91	if (!dev->platform_data || !dev_fwnode(dev))
     92		return;
     93
     94	kfree(oms);
     95	dev->platform_data = NULL;
     96}
     97EXPORT_SYMBOL(mmc_spi_put_pdata);