/*
* intel_mid_dma.c - Intel Langwell DMA Drivers
*
* Copyright (C) 2008-10 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* The driver design is based on dw_dmac driver
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*
*/
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/intel_mid_dma.h>
#define MAX_CHAN 4 /*max ch across controllers*/
#include "intel_mid_dma_regs.h"
#define INTEL_MID_DMAC1_ID 0x0814
#define INTEL_MID_DMAC2_ID 0x0813
#define INTEL_MID_GP_DMAC2_ID 0x0827
#define INTEL_MFLD_DMAC1_ID 0x0830
#define LNW_PERIPHRAL_MASK_BASE 0xFFAE8008
#define LNW_PERIPHRAL_MASK_SIZE 0x10
#define LNW_PERIPHRAL_STATUS 0x0
#define LNW_PERIPHRAL_MASK 0x8
struct intel_mid_dma_probe_info {
u8 max_chan;
u8 ch_base;
u16 block_size;
u32 pimr_mask;
};
#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \
((kernel_ulong_t)&(struct intel_mid_dma_probe_info) { \
.max_chan = (_max_chan), \
.ch_base = (_ch_base), \
.block_size = (_block_size), \
.pimr_mask = (_pimr_mask), \
})
/*****************************************************************************
Utility Functions*/
/**
* get_ch_index - convert status to channel
* @status: status mask
* @base: dma ch base value
*
* Modify the status mask and return the channel index needing
* attention (or -1 if neither)
*/
static int get_ch_index(int *status, unsigned int base)
{
int i;
for (i = 0; i < MAX_CHAN; i++) {
if (*status & (1 << (i + base))) {
*status = *status & ~(1