// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the MMC / SD / SDIO IP found in:
*
* TC6393XB, TC6391XB, TC6387XB, T7L66XB, ASIC3, SH-Mobile SoCs
*
* Copyright (C) 2015-19 Renesas Electronics Corporation
* Copyright (C) 2016-19 Sang Engineering, Wolfram Sang
* Copyright (C) 2017 Horms Solutions, Simon Horman
* Copyright (C) 2011 Guennadi Liakhovetski
* Copyright (C) 2007 Ian Molton
* Copyright (C) 2004 Ian Molton
*
* This driver draws mainly on scattered spec sheets, Reverse engineering
* of the toshiba e800 SD driver and some parts of the 2.4 ASIC3 driver (4 bit
* support). (Further 4 bit support from a later datasheet).
*
* TODO:
* Investigate using a workqueue for PIO transfers
* Eliminate FIXMEs
* Better Power management
* Handle MMC errors better
* double buffer support
*
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/mmc/sdio.h>
#include <linux/scatterlist.h>
#include <linux/sizes.h>
#include <linux/spinlock.h>
#include <linux/swiotlb.h>
#include <linux/workqueue.h>
#include "tmio_mmc.h"
static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data)
{
if (host->dma_ops)
host->dma_ops->start(host, data);
}
static inline void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
{
if (host->dma_ops)
host->dma_ops->enable(host, enable);
}
static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
struct tmio_mmc_data *pdata)
{
if (host->dma_ops) {
host->dma_ops->request(host, pdata);
} else {
host->chan_tx = NULL;
host->chan_rx = NULL;
}
}
static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
{
if (host->dma_ops)
host->dma_ops->release(host);
}
static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
{
if (host->dma_ops)
host->dma_ops->abort(host);
}
static inline void tmio_mmc_dataend_dma(struct tmio_mmc_host *host)
{
if (host->dma_ops)