brintos

brintos / linux-shallow public Read only

0
0
Text · 2.3 KiB · 05939f3 Raw
99 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * OpenFirmware bindings for the MMC-over-SPI driver4 *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_DESCRIPTION("OpenFirmware bindings for the MMC-over-SPI driver");23MODULE_LICENSE("GPL");24 25struct of_mmc_spi {26	struct mmc_spi_platform_data pdata;27	int detect_irq;28};29 30static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)31{32	return container_of(dev->platform_data, struct of_mmc_spi, pdata);33}34 35static int of_mmc_spi_init(struct device *dev,36			   irqreturn_t (*irqhandler)(int, void *), void *mmc)37{38	struct of_mmc_spi *oms = to_of_mmc_spi(dev);39 40	return request_threaded_irq(oms->detect_irq, NULL, irqhandler,41					IRQF_ONESHOT, dev_name(dev), mmc);42}43 44static void of_mmc_spi_exit(struct device *dev, void *mmc)45{46	struct of_mmc_spi *oms = to_of_mmc_spi(dev);47 48	free_irq(oms->detect_irq, mmc);49}50 51struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)52{53	struct mmc_host *mmc = dev_get_drvdata(&spi->dev);54	struct device *dev = &spi->dev;55	struct of_mmc_spi *oms;56 57	if (dev->platform_data || !dev_fwnode(dev))58		return dev->platform_data;59 60	oms = kzalloc(sizeof(*oms), GFP_KERNEL);61	if (!oms)62		return NULL;63 64	if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0)65		goto err_ocr;66 67	oms->detect_irq = spi->irq;68	if (oms->detect_irq > 0) {69		oms->pdata.init = of_mmc_spi_init;70		oms->pdata.exit = of_mmc_spi_exit;71	} else {72		oms->pdata.caps |= MMC_CAP_NEEDS_POLL;73	}74	if (device_property_read_bool(dev, "cap-sd-highspeed"))75		oms->pdata.caps |= MMC_CAP_SD_HIGHSPEED;76	if (device_property_read_bool(dev, "cap-mmc-highspeed"))77		oms->pdata.caps |= MMC_CAP_MMC_HIGHSPEED;78 79	dev->platform_data = &oms->pdata;80	return dev->platform_data;81err_ocr:82	kfree(oms);83	return NULL;84}85EXPORT_SYMBOL(mmc_spi_get_pdata);86 87void mmc_spi_put_pdata(struct spi_device *spi)88{89	struct device *dev = &spi->dev;90	struct of_mmc_spi *oms = to_of_mmc_spi(dev);91 92	if (!dev->platform_data || !dev_fwnode(dev))93		return;94 95	kfree(oms);96	dev->platform_data = NULL;97}98EXPORT_SYMBOL(mmc_spi_put_pdata);99