1ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov/* 270f10482c668301c483acded13bf68780ad352b9Pierre Ossman * linux/drivers/mmc/host/au1xmmc.c - AU1XX0 MMC driver 3ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * 4ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * Copyright (c) 2005, Advanced Micro Devices, Inc. 5ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * 6ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * Developed with help from the 2.4.30 MMC AU1XXX controller including 7ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * the following copyright notices: 8ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * Copyright (c) 2003-2004 Embedded Edge, LLC. 9ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * Portions Copyright (C) 2002 Embedix, Inc 10ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * Copyright 2002 Hewlett-Packard Company 11ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 12ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * 2.6 version of this driver inspired by: 13ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * (drivers/mmc/wbsd.c) Copyright (C) 2004-2005 Pierre Ossman, 14ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * All Rights Reserved. 15ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * (drivers/mmc/pxa.c) Copyright (C) 2003 Russell King, 16ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * All Rights Reserved. 17ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * 18ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 19ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * This program is free software; you can redistribute it and/or modify 20ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * it under the terms of the GNU General Public License version 2 as 21ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * published by the Free Software Foundation. 22ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov */ 23ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 24e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss/* Why don't we use the SD controllers' carddetect feature? 25ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * 26ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * From the AU1100 MMC application guide: 27ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * If the Au1100-based design is intended to support both MultiMediaCards 28ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * and 1- or 4-data bit SecureDigital cards, then the solution is to 29ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * connect a weak (560KOhm) pull-up resistor to connector pin 1. 30ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * In doing so, a MMC card never enters SPI-mode communications, 31ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * but now the SecureDigital card-detect feature of CD/DAT3 is ineffective 32ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov * (the low to high transition will not occur). 33ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov */ 34ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 35ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <linux/module.h> 36ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <linux/init.h> 37b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayr#include <linux/platform_device.h> 38ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <linux/mm.h> 39ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <linux/interrupt.h> 40ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <linux/dma-mapping.h> 410ada7a02ad870f8586176ff5c4f0db2a40ba3fabAl Viro#include <linux/scatterlist.h> 42c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#include <linux/leds.h> 43ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <linux/mmc/host.h> 445a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 45c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 46ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <asm/io.h> 47ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <asm/mach-au1x00/au1000.h> 48ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <asm/mach-au1x00/au1xxx_dbdma.h> 49ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#include <asm/mach-au1x00/au1100_mmc.h> 50ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 51ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#define DRIVER_NAME "au1xxx-mmc" 52ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 53ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov/* Set this to enable special debugging macros */ 54c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss/* #define DEBUG */ 55ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 56c65631781eb0f2e81865017c1484e9aef76e1b61Russell King#ifdef DEBUG 575c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define DBG(fmt, idx, args...) \ 58a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_debug("au1xmmc(%d): DEBUG: " fmt, idx, ##args) 59ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#else 605c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define DBG(fmt, idx, args...) do {} while (0) 61ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#endif 62ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 635c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* Hardware definitions */ 645c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define AU1XMMC_DESCRIPTOR_COUNT 1 65e491d230fd398bb730e3c2dd734c5447463b9d38Manuel Lauss 66e491d230fd398bb730e3c2dd734c5447463b9d38Manuel Lauss/* max DMA seg size: 64KB on Au1100, 4MB on Au1200 */ 671177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss#define AU1100_MMC_DESCRIPTOR_SIZE 0x0000ffff 681177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss#define AU1200_MMC_DESCRIPTOR_SIZE 0x003fffff 695c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 705c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \ 715c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \ 725c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36) 735c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 745c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* This gives us a hard value for the stop command that we can write directly 755c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss * to the command register. 765c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss */ 775c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define STOP_CMD \ 785c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss (SD_CMD_RT_1B | SD_CMD_CT_7 | (0xC << SD_CMD_CI_SHIFT) | SD_CMD_GO) 795c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 805c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* This is the set of interrupts that we configure by default. */ 815c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define AU1XMMC_INTERRUPTS \ 825c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_RAT | \ 835c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss SD_CONFIG_CR | SD_CONFIG_I) 845c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 855c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* The poll event (looking for insert/remove events runs twice a second. */ 865c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define AU1XMMC_DETECT_TIMEOUT (HZ/2) 875c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 885c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Laussstruct au1xmmc_host { 895c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct mmc_host *mmc; 905c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct mmc_request *mrq; 915c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 925c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 flags; 935c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 iobase; 945c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 clock; 955c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 bus_width; 965c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 power_mode; 975c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 985c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int status; 995c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1005c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct { 1015c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int len; 1025c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int dir; 1035c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss } dma; 1045c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1055c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct { 1065c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int index; 1075c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int offset; 1085c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int len; 1095c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss } pio; 1105c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1115c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 tx_chan; 1125c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 rx_chan; 1135c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1145c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int irq; 1155c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1165c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct tasklet_struct finish_task; 1175c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct tasklet_struct data_task; 1185c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct au1xmmc_platform_data *platdata; 1195c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct platform_device *pdev; 1205c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct resource *ioarea; 1215c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss}; 1225c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1235c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* Status flags used by the host structure */ 1245c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_F_XMIT 0x0001 1255c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_F_RECV 0x0002 1265c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_F_DMA 0x0010 1271177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss#define HOST_F_DBDMA 0x0020 1285c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_F_ACTIVE 0x0100 1295c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_F_STOP 0x1000 1305c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1315c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_S_IDLE 0x0001 1325c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_S_CMD 0x0002 1335c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_S_DATA 0x0003 1345c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_S_STOP 0x0004 1355c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1365c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* Easy access macros */ 1375c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_STATUS(h) ((h)->iobase + SD_STATUS) 1385c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_CONFIG(h) ((h)->iobase + SD_CONFIG) 1395c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_ENABLE(h) ((h)->iobase + SD_ENABLE) 1405c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_TXPORT(h) ((h)->iobase + SD_TXPORT) 1415c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_RXPORT(h) ((h)->iobase + SD_RXPORT) 1425c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_CMDARG(h) ((h)->iobase + SD_CMDARG) 1435c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_BLKSIZE(h) ((h)->iobase + SD_BLKSIZE) 1445c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_CMD(h) ((h)->iobase + SD_CMD) 1455c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_CONFIG2(h) ((h)->iobase + SD_CONFIG2) 1465c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_TIMEOUT(h) ((h)->iobase + SD_TIMEOUT) 1475c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define HOST_DEBUG(h) ((h)->iobase + SD_DEBUG) 1485c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1495c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss#define DMA_CHANNEL(h) \ 1505c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss (((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan) 1515c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss 1521177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Laussstatic inline int has_dbdma(void) 1531177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss{ 1541177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss switch (alchemy_get_cputype()) { 1551177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss case ALCHEMY_CPU_AU1200: 156809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_CPU_AU1300: 1571177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss return 1; 1581177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss default: 1591177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss return 0; 1601177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss } 1611177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss} 1621177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss 163ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic inline void IRQ_ON(struct au1xmmc_host *host, u32 mask) 164ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 165ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 val = au_readl(HOST_CONFIG(host)); 166ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov val |= mask; 167ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(val, HOST_CONFIG(host)); 168ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 169ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 170ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 171ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic inline void FLUSH_FIFO(struct au1xmmc_host *host) 172ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 173ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 val = au_readl(HOST_CONFIG2(host)); 174ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 175ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host)); 176ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync_delay(1); 177ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 178ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* SEND_STOP will turn off clock control - this re-enables it */ 179ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov val &= ~SD_CONFIG2_DF; 180ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 181ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(val, HOST_CONFIG2(host)); 182ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 183ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 184ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 185ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask) 186ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 187ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 val = au_readl(HOST_CONFIG(host)); 188ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov val &= ~mask; 189ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(val, HOST_CONFIG(host)); 190ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 191ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 192ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 193ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic inline void SEND_STOP(struct au1xmmc_host *host) 194ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 195281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss u32 config2; 196ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 197ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov WARN_ON(host->status != HOST_S_DATA); 198ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->status = HOST_S_STOP; 199ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 200281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss config2 = au_readl(HOST_CONFIG2(host)); 201281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host)); 202ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 203ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 204b595076a180a56d1bb170e6eceda6eb9d76f4cd3Uwe Kleine-König /* Send the stop command */ 205ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(STOP_CMD, HOST_CMD(host)); 206ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 207ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 208ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_set_power(struct au1xmmc_host *host, int state) 209ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 210c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->set_power) 211c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->platdata->set_power(host->mmc, state); 212ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 213ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 214e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Laussstatic int au1xmmc_card_inserted(struct mmc_host *mmc) 215ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 216e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss struct au1xmmc_host *host = mmc_priv(mmc); 217c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 218c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->card_inserted) 219e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss return !!host->platdata->card_inserted(host->mmc); 220c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 221e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss return -ENOSYS; 222ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 223ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 22482999770d6926193f50b42e713a92ee4028398e3Manuel Laussstatic int au1xmmc_card_readonly(struct mmc_host *mmc) 225ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 22682999770d6926193f50b42e713a92ee4028398e3Manuel Lauss struct au1xmmc_host *host = mmc_priv(mmc); 227c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 228c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->card_readonly) 229e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss return !!host->platdata->card_readonly(mmc); 230c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 231e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss return -ENOSYS; 232ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 233ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 234ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_finish_request(struct au1xmmc_host *host) 235ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 236ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct mmc_request *mrq = host->mrq; 237ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 238ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->mrq = NULL; 239c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->flags &= HOST_F_ACTIVE | HOST_F_DMA; 240ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 241ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->dma.len = 0; 242ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->dma.dir = 0; 243ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 244ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.index = 0; 245ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.offset = 0; 246ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len = 0; 247ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 248ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->status = HOST_S_IDLE; 249ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 250ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov mmc_request_done(host->mmc, mrq); 251ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 252ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 253ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_tasklet_finish(unsigned long param) 254ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 255ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct au1xmmc_host *host = (struct au1xmmc_host *) param; 256ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_finish_request(host); 257ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 258ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 259ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic int au1xmmc_send_command(struct au1xmmc_host *host, int wait, 260be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman struct mmc_command *cmd, struct mmc_data *data) 261ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 262ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); 263ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 264e142c24cf8f471c2a6cb95a4a26923d9621770ffMartin Michlmayr switch (mmc_resp_type(cmd)) { 265279bc4450989215e741c2c9d3a726f1ac96ede40Manuel Lauss case MMC_RSP_NONE: 266279bc4450989215e741c2c9d3a726f1ac96ede40Manuel Lauss break; 267ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov case MMC_RSP_R1: 268ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov mmccmd |= SD_CMD_RT_1; 269ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 270ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov case MMC_RSP_R1B: 271ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov mmccmd |= SD_CMD_RT_1B; 272ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 273ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov case MMC_RSP_R2: 274ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov mmccmd |= SD_CMD_RT_2; 275ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 276ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov case MMC_RSP_R3: 277ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov mmccmd |= SD_CMD_RT_3; 278ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 279279bc4450989215e741c2c9d3a726f1ac96ede40Manuel Lauss default: 280a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info("au1xmmc: unhandled response type %02x\n", 281279bc4450989215e741c2c9d3a726f1ac96ede40Manuel Lauss mmc_resp_type(cmd)); 28217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman return -EINVAL; 283ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 284ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 285be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman if (data) { 2866356a9d955e1898eadaa8cba9a5137b1787c0c7ePierre Ossman if (data->flags & MMC_DATA_READ) { 287be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman if (data->blocks > 1) 288be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman mmccmd |= SD_CMD_CT_4; 289be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman else 290be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman mmccmd |= SD_CMD_CT_2; 2916356a9d955e1898eadaa8cba9a5137b1787c0c7ePierre Ossman } else if (data->flags & MMC_DATA_WRITE) { 292be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman if (data->blocks > 1) 293be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman mmccmd |= SD_CMD_CT_3; 294be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman else 295be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman mmccmd |= SD_CMD_CT_1; 296be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman } 297ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 298ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 299ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(cmd->arg, HOST_CMDARG(host)); 300ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 301ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 302ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (wait) 303ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov IRQ_OFF(host, SD_CONFIG_CR); 304ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 305ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host)); 306ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 307ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 308ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Wait for the command to go on the line */ 3095c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss while (au_readl(HOST_CMD(host)) & SD_CMD_GO) 3105c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss /* nop */; 311ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 312ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Wait for the command to come back */ 313ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (wait) { 314ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 status = au_readl(HOST_STATUS(host)); 315ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 3165c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss while (!(status & SD_STATUS_CR)) 317ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov status = au_readl(HOST_STATUS(host)); 318ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 319ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Clear the CR status */ 320ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_STATUS_CR, HOST_STATUS(host)); 321ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 322ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov IRQ_ON(host, SD_CONFIG_CR); 323ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 324ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 32517b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman return 0; 326ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 327ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 328ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status) 329ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 330ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct mmc_request *mrq = host->mrq; 331ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct mmc_data *data; 332ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 crc; 333ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 3345c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss WARN_ON((host->status != HOST_S_DATA) && (host->status != HOST_S_STOP)); 335ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 336ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->mrq == NULL) 337ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov return; 338ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 339ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data = mrq->cmd->data; 340ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 341ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (status == 0) 342ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov status = au_readl(HOST_STATUS(host)); 343ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 344ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* The transaction is really over when the SD_STATUS_DB bit is clear */ 3455c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB)) 346ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov status = au_readl(HOST_STATUS(host)); 347ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 34817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = 0; 349ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir); 350ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 351ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Process any errors */ 352ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov crc = (status & (SD_STATUS_WC | SD_STATUS_RC)); 353ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->flags & HOST_F_XMIT) 354ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov crc |= ((status & 0x07) == 0x02) ? 0 : 1; 355ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 356ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (crc) 35717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman data->error = -EILSEQ; 358ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 359ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Clear the CRC bits */ 360ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host)); 361ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 362ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data->bytes_xfered = 0; 363ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 36417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (!data->error) { 3651177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) { 366ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 chan = DMA_CHANNEL(host); 367ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 3685c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss chan_tab_t *c = *((chan_tab_t **)chan); 369ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1x_dma_chan_t *cp = c->chan_ptr; 370ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data->bytes_xfered = cp->ddma_bytecnt; 3715c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss } else 372ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data->bytes_xfered = 3735c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss (data->blocks * data->blksz) - host->pio.len; 374ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 375ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 376ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_finish_request(host); 377ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 378ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 379ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_tasklet_data(unsigned long param) 380ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 3815c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct au1xmmc_host *host = (struct au1xmmc_host *)param; 382ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 383ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 status = au_readl(HOST_STATUS(host)); 384ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_data_complete(host, status); 385ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 386ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 387ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#define AU1XMMC_MAX_TRANSFER 8 388ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 389ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_send_pio(struct au1xmmc_host *host) 390ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 3915c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct mmc_data *data; 3925c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int sg_len, max, count; 3935c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss unsigned char *sg_ptr, val; 3945c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 status; 395ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct scatterlist *sg; 396ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 397ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data = host->mrq->data; 398ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 399ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (!(host->flags & HOST_F_XMIT)) 400ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov return; 401ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 402ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* This is the pointer to the data buffer */ 403ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov sg = &data->sg[host->pio.index]; 40445711f1af6eff1a6d010703b4862e0d2b9afd056Jens Axboe sg_ptr = sg_virt(sg) + host->pio.offset; 405ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 406ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* This is the space left inside the buffer */ 407ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov sg_len = data->sg[host->pio.index].length - host->pio.offset; 408ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 4095c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss /* Check if we need less than the size of the sg_buffer */ 410ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov max = (sg_len > host->pio.len) ? host->pio.len : sg_len; 4115c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss if (max > AU1XMMC_MAX_TRANSFER) 4125c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss max = AU1XMMC_MAX_TRANSFER; 413ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 4145c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss for (count = 0; count < max; count++) { 415ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov status = au_readl(HOST_STATUS(host)); 416ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 417ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (!(status & SD_STATUS_TH)) 418ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 419ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 420ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov val = *sg_ptr++; 421ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 4225c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss au_writel((unsigned long)val, HOST_TXPORT(host)); 423ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 424ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 425ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 426ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len -= count; 427ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.offset += count; 428ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 429ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (count == sg_len) { 430ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.index++; 431ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.offset = 0; 432ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 433ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 434ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->pio.len == 0) { 435ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov IRQ_OFF(host, SD_CONFIG_TH); 436ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 437ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->flags & HOST_F_STOP) 438ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov SEND_STOP(host); 439ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 440ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov tasklet_schedule(&host->data_task); 441ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 442ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 443ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 444ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_receive_pio(struct au1xmmc_host *host) 445ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 4465c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct mmc_data *data; 4475c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int max, count, sg_len = 0; 4485c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss unsigned char *sg_ptr = NULL; 4495c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 status, val; 450ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct scatterlist *sg; 451ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 452ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data = host->mrq->data; 453ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 454ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (!(host->flags & HOST_F_RECV)) 455ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov return; 456ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 457ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov max = host->pio.len; 458ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 459ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->pio.index < host->dma.len) { 460ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov sg = &data->sg[host->pio.index]; 46145711f1af6eff1a6d010703b4862e0d2b9afd056Jens Axboe sg_ptr = sg_virt(sg) + host->pio.offset; 462ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 463ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* This is the space left inside the buffer */ 464ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; 465ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 4665c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss /* Check if we need less than the size of the sg_buffer */ 4675c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss if (sg_len < max) 4685c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss max = sg_len; 469ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 470ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 471ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (max > AU1XMMC_MAX_TRANSFER) 472ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov max = AU1XMMC_MAX_TRANSFER; 473ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 4745c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss for (count = 0; count < max; count++) { 475ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov status = au_readl(HOST_STATUS(host)); 476ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 477ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (!(status & SD_STATUS_NE)) 478ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 479ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 480ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (status & SD_STATUS_RC) { 481c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss DBG("RX CRC Error [%d + %d].\n", host->pdev->id, 482ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len, count); 483ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 484ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 485ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 486ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (status & SD_STATUS_RO) { 487c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss DBG("RX Overrun [%d + %d]\n", host->pdev->id, 488ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len, count); 489ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 490ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 491ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov else if (status & SD_STATUS_RU) { 492c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss DBG("RX Underrun [%d + %d]\n", host->pdev->id, 493ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len, count); 494ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov break; 495ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 496ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 497ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov val = au_readl(HOST_RXPORT(host)); 498ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 499ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (sg_ptr) 5005c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss *sg_ptr++ = (unsigned char)(val & 0xFF); 501ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 502ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 503ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len -= count; 504ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.offset += count; 505ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 506ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (sg_len && count == sg_len) { 507ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.index++; 508ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.offset = 0; 509ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 510ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 511ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->pio.len == 0) { 5125c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss /* IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF); */ 513ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov IRQ_OFF(host, SD_CONFIG_NE); 514ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 515ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->flags & HOST_F_STOP) 516ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov SEND_STOP(host); 517ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 518ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov tasklet_schedule(&host->data_task); 519ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 520ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 521ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 5225c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* This is called when a command has been completed - grab the response 5235c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss * and check for errors. Then start the data transfer if it is indicated. 5245c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss */ 525ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status) 526ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 527ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct mmc_request *mrq = host->mrq; 528ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct mmc_command *cmd; 5295c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss u32 r[4]; 5305c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss int i, trans; 531ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 532ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (!host->mrq) 533ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov return; 534ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 535ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov cmd = mrq->cmd; 53617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = 0; 537ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 538e92251762d02a46177d4105d1744041e3f8bc465Russell King if (cmd->flags & MMC_RSP_PRESENT) { 539e92251762d02a46177d4105d1744041e3f8bc465Russell King if (cmd->flags & MMC_RSP_136) { 540e92251762d02a46177d4105d1744041e3f8bc465Russell King r[0] = au_readl(host->iobase + SD_RESP3); 541e92251762d02a46177d4105d1744041e3f8bc465Russell King r[1] = au_readl(host->iobase + SD_RESP2); 542e92251762d02a46177d4105d1744041e3f8bc465Russell King r[2] = au_readl(host->iobase + SD_RESP1); 543e92251762d02a46177d4105d1744041e3f8bc465Russell King r[3] = au_readl(host->iobase + SD_RESP0); 544e92251762d02a46177d4105d1744041e3f8bc465Russell King 545e92251762d02a46177d4105d1744041e3f8bc465Russell King /* The CRC is omitted from the response, so really 546e92251762d02a46177d4105d1744041e3f8bc465Russell King * we only got 120 bytes, but the engine expects 5475c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss * 128 bits, so we have to shift things up. 548e92251762d02a46177d4105d1744041e3f8bc465Russell King */ 5495c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss for (i = 0; i < 4; i++) { 550e92251762d02a46177d4105d1744041e3f8bc465Russell King cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8; 551e92251762d02a46177d4105d1744041e3f8bc465Russell King if (i != 3) 552e92251762d02a46177d4105d1744041e3f8bc465Russell King cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24; 553e92251762d02a46177d4105d1744041e3f8bc465Russell King } 554e92251762d02a46177d4105d1744041e3f8bc465Russell King } else { 555e92251762d02a46177d4105d1744041e3f8bc465Russell King /* Techincally, we should be getting all 48 bits of 556e92251762d02a46177d4105d1744041e3f8bc465Russell King * the response (SD_RESP1 + SD_RESP2), but because 557e92251762d02a46177d4105d1744041e3f8bc465Russell King * our response omits the CRC, our data ends up 558e92251762d02a46177d4105d1744041e3f8bc465Russell King * being shifted 8 bits to the right. In this case, 559e92251762d02a46177d4105d1744041e3f8bc465Russell King * that means that the OSR data starts at bit 31, 5605c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss * so we can just read RESP0 and return that. 561e92251762d02a46177d4105d1744041e3f8bc465Russell King */ 562e92251762d02a46177d4105d1744041e3f8bc465Russell King cmd->resp[0] = au_readl(host->iobase + SD_RESP0); 563ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 564ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 565ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 566ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Figure out errors */ 567ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC)) 56817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman cmd->error = -EILSEQ; 569ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 570ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov trans = host->flags & (HOST_F_XMIT | HOST_F_RECV); 571ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 57217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (!trans || cmd->error) { 5735c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF); 574ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov tasklet_schedule(&host->finish_task); 575ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov return; 576ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 577ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 578ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->status = HOST_S_DATA; 579ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 5801177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if ((host->flags & (HOST_F_DMA | HOST_F_DBDMA))) { 581ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 channel = DMA_CHANNEL(host); 582ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 5831177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss /* Start the DBDMA as soon as the buffer gets something in it */ 584ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 585ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->flags & HOST_F_RECV) { 586ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 mask = SD_STATUS_DB | SD_STATUS_NE; 587ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 588ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov while((status & mask) != mask) 589ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov status = au_readl(HOST_STATUS(host)); 590ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 591ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 592ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xxx_dbdma_start(channel); 593ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 594ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 595ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 596ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_set_clock(struct au1xmmc_host *host, int rate) 597ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 598ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov unsigned int pbus = get_au1x00_speed(); 599ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov unsigned int divisor; 600ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 config; 601ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 602ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* From databook: 6035c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss * divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1 6045c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss */ 605ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2); 606ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov pbus /= 2; 607ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov divisor = ((pbus / rate) / 2) - 1; 608ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 609ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov config = au_readl(HOST_CONFIG(host)); 610ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 611ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov config &= ~(SD_CONFIG_DIV); 612ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE; 613ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 614ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(config, HOST_CONFIG(host)); 615ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 616ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 617ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 6185c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Laussstatic int au1xmmc_prepare_data(struct au1xmmc_host *host, 6195c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss struct mmc_data *data) 620ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 6212c171bf13423dc5293188cea7f6c2da1720926e2Pavel Pisa int datalen = data->blocks * data->blksz; 622ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 623ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (data->flags & MMC_DATA_READ) 624ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->flags |= HOST_F_RECV; 625ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov else 626ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->flags |= HOST_F_XMIT; 627ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 628ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->mrq->stop) 629ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->flags |= HOST_F_STOP; 630ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 631ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->dma.dir = DMA_BIDIRECTIONAL; 632ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 633ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg, 634ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov data->sg_len, host->dma.dir); 635ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 636ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->dma.len == 0) 63717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman return -ETIMEDOUT; 638ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 6392c171bf13423dc5293188cea7f6c2da1720926e2Pavel Pisa au_writel(data->blksz - 1, HOST_BLKSIZE(host)); 640ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 6411177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) { 642ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov int i; 643ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 channel = DMA_CHANNEL(host); 644ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 645ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xxx_dbdma_stop(channel); 646ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 6475c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss for (i = 0; i < host->dma.len; i++) { 648ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 ret = 0, flags = DDMA_FLAGS_NOIE; 649ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct scatterlist *sg = &data->sg[i]; 650ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov int sg_len = sg->length; 651ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 652ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov int len = (datalen > sg_len) ? sg_len : datalen; 653ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 654ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (i == host->dma.len - 1) 655ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov flags = DDMA_FLAGS_IE; 656ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 6575c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss if (host->flags & HOST_F_XMIT) { 658ea071cc705e8bfba0c8bf84be8d4f9f4e9da6962Manuel Lauss ret = au1xxx_dbdma_put_source(channel, 659963accbc82a0912b39de39d59e2fd6741db3aa4bManuel Lauss sg_phys(sg), len, flags); 6605c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss } else { 661ea071cc705e8bfba0c8bf84be8d4f9f4e9da6962Manuel Lauss ret = au1xxx_dbdma_put_dest(channel, 662963accbc82a0912b39de39d59e2fd6741db3aa4bManuel Lauss sg_phys(sg), len, flags); 663ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 664ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 665c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!ret) 666ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov goto dataerr; 667ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 668ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov datalen -= len; 669ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 6705c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss } else { 671ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.index = 0; 672ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.offset = 0; 673ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->pio.len = datalen; 674ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 675ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (host->flags & HOST_F_XMIT) 676ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov IRQ_ON(host, SD_CONFIG_TH); 677ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov else 678ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov IRQ_ON(host, SD_CONFIG_NE); 6795c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss /* IRQ_ON(host, SD_CONFIG_RA | SD_CONFIG_RF); */ 680ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 681ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 68217b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman return 0; 683ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 684c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussdataerr: 685c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 686c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->dma.dir); 68717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman return -ETIMEDOUT; 688ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 689ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 6905c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Lauss/* This actually starts a command or data transaction */ 691ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) 692ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 693ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct au1xmmc_host *host = mmc_priv(mmc); 69417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman int ret = 0; 695ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 696ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov WARN_ON(irqs_disabled()); 697ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov WARN_ON(host->status != HOST_S_IDLE); 698ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 699ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->mrq = mrq; 700ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->status = HOST_S_CMD; 701ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 70288b8d9a83431237bf3eec1f2968f763607811171Manuel Lauss /* fail request immediately if no card is present */ 703e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss if (0 == au1xmmc_card_inserted(mmc)) { 70488b8d9a83431237bf3eec1f2968f763607811171Manuel Lauss mrq->cmd->error = -ENOMEDIUM; 70588b8d9a83431237bf3eec1f2968f763607811171Manuel Lauss au1xmmc_finish_request(host); 70688b8d9a83431237bf3eec1f2968f763607811171Manuel Lauss return; 70788b8d9a83431237bf3eec1f2968f763607811171Manuel Lauss } 70888b8d9a83431237bf3eec1f2968f763607811171Manuel Lauss 709ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (mrq->data) { 710ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov FLUSH_FIFO(host); 711ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov ret = au1xmmc_prepare_data(host, mrq->data); 712ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 713ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 71417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (!ret) 715be0192aae1aed3fbf172e3f9a22ec75392c1b175Pierre Ossman ret = au1xmmc_send_command(host, 0, mrq->cmd, mrq->data); 716ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 71717b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman if (ret) { 718ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov mrq->cmd->error = ret; 719ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_finish_request(host); 720ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 721ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 722ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 723ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void au1xmmc_reset_controller(struct au1xmmc_host *host) 724ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 725ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Apply the clock */ 726ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_ENABLE_CE, HOST_ENABLE(host)); 727ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync_delay(1); 728ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 729ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host)); 730ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync_delay(5); 731ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 732ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(~0, HOST_STATUS(host)); 733ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 734ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 735ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(0, HOST_BLKSIZE(host)); 736ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(0x001fffff, HOST_TIMEOUT(host)); 737ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 738ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 739ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host)); 740ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 741ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 742ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host)); 743ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync_delay(1); 744ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 745ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host)); 746ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 747ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 748ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov /* Configure interrupts */ 749ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host)); 750ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au_sync(); 751ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 752ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 753ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 7545c0a889df56c9f6c5a68ec7aa222082569b35fd9Manuel Laussstatic void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 755ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 756ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov struct au1xmmc_host *host = mmc_priv(mmc); 757281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss u32 config2; 758ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 759ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (ios->power_mode == MMC_POWER_OFF) 760ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_set_power(host, 0); 761ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov else if (ios->power_mode == MMC_POWER_ON) { 762ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_set_power(host, 1); 763ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 764ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 765ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov if (ios->clock && ios->clock != host->clock) { 766ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_set_clock(host, ios->clock); 767ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov host->clock = ios->clock; 768ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 769281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss 770281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss config2 = au_readl(HOST_CONFIG2(host)); 771281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss switch (ios->bus_width) { 772809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case MMC_BUS_WIDTH_8: 773809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss config2 |= SD_CONFIG2_BB; 774809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 775281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss case MMC_BUS_WIDTH_4: 776809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss config2 &= ~SD_CONFIG2_BB; 777281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss config2 |= SD_CONFIG2_WB; 778281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss break; 779281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss case MMC_BUS_WIDTH_1: 780809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB); 781281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss break; 782281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss } 783281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss au_writel(config2, HOST_CONFIG2(host)); 784281dd23ea03e9893c02d237d9e35a7d20d412452Manuel Lauss au_sync(); 785ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 786ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 787ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT) 788ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#define STATUS_DATA_IN (SD_STATUS_NE) 789ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#define STATUS_DATA_OUT (SD_STATUS_TH) 790ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 7917d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t au1xmmc_irq(int irq, void *dev_id) 792ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 793c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct au1xmmc_host *host = dev_id; 794ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov u32 status; 795ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 796c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss status = au_readl(HOST_STATUS(host)); 797ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 798c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!(status & SD_STATUS_I)) 799c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return IRQ_NONE; /* not ours */ 800ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 80120f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss if (status & SD_STATUS_SI) /* SDIO */ 80220f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss mmc_signal_sdio_irq(host->mmc); 80320f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss 804c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->mrq && (status & STATUS_TIMEOUT)) { 805c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (status & SD_STATUS_RAT) 806c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->mrq->cmd->error = -ETIMEDOUT; 807c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss else if (status & SD_STATUS_DT) 808c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->mrq->data->error = -ETIMEDOUT; 809ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 810c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* In PIO mode, interrupts might still be enabled */ 811c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH); 812ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 813c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF); */ 814c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss tasklet_schedule(&host->finish_task); 815c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 816ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov#if 0 817c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss else if (status & SD_STATUS_DD) { 818c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* Sometimes we get a DD before a NE in PIO mode */ 819c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!(host->flags & HOST_F_DMA) && (status & SD_STATUS_NE)) 820c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_receive_pio(host); 821c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss else { 822c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_data_complete(host, status); 823c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* tasklet_schedule(&host->data_task); */ 824ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 825ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 826c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#endif 827c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss else if (status & SD_STATUS_CR) { 828c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->status == HOST_S_CMD) 829c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_cmd_complete(host, status); 830c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 831c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } else if (!(host->flags & HOST_F_DMA)) { 832c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if ((host->flags & HOST_F_XMIT) && (status & STATUS_DATA_OUT)) 833c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_send_pio(host); 834c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss else if ((host->flags & HOST_F_RECV) && (status & STATUS_DATA_IN)) 835c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_receive_pio(host); 836c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 837c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } else if (status & 0x203F3C70) { 838c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss DBG("Unhandled status %8.8x\n", host->pdev->id, 839c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss status); 840ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 841ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 842c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(status, HOST_STATUS(host)); 843c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_sync(); 844ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 845c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return IRQ_HANDLED; 846ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 847ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 848c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss/* 8bit memory DMA device */ 849c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussstatic dbdev_tab_t au1xmmc_mem_dbdev = { 850c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_id = DSCR_CMD0_ALWAYS, 851c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_flags = DEV_FLAGS_ANYUSE, 852c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_tsize = 0, 853c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_devwidth = 8, 854c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_physaddr = 0x00000000, 855c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_intlevel = 0, 856c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss .dev_intpolarity = 0, 857ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov}; 858c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussstatic int memid; 859ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 860c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussstatic void au1xmmc_dbdma_callback(int irq, void *dev_id) 861ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 862c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct au1xmmc_host *host = (struct au1xmmc_host *)dev_id; 863ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 864c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* Avoid spurious interrupts */ 865c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!host->mrq) 866c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return; 867ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 868c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->flags & HOST_F_STOP) 869c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss SEND_STOP(host); 870ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 871c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss tasklet_schedule(&host->data_task); 872c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss} 873ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 874c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussstatic int au1xmmc_dbdma_init(struct au1xmmc_host *host) 875c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss{ 876c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct resource *res; 877c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss int txid, rxid; 878c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 879c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss res = platform_get_resource(host->pdev, IORESOURCE_DMA, 0); 880c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!res) 881c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return -ENODEV; 882c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss txid = res->start; 883c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 884c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss res = platform_get_resource(host->pdev, IORESOURCE_DMA, 1); 885c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!res) 886c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return -ENODEV; 887c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss rxid = res->start; 888c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 889c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!memid) 890c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return -ENODEV; 891c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 892c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->tx_chan = au1xxx_dbdma_chan_alloc(memid, txid, 893c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_dbdma_callback, (void *)host); 894c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!host->tx_chan) { 895c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&host->pdev->dev, "cannot allocate TX DMA\n"); 896c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return -ENODEV; 897c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 898c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 899c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->rx_chan = au1xxx_dbdma_chan_alloc(rxid, memid, 900c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_dbdma_callback, (void *)host); 901c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!host->rx_chan) { 902c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&host->pdev->dev, "cannot allocate RX DMA\n"); 903c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_chan_free(host->tx_chan); 904c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return -ENODEV; 905c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 906ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 907c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_set_devwidth(host->tx_chan, 8); 908c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_set_devwidth(host->rx_chan, 8); 909ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 910c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_ring_alloc(host->tx_chan, AU1XMMC_DESCRIPTOR_COUNT); 911c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_ring_alloc(host->rx_chan, AU1XMMC_DESCRIPTOR_COUNT); 912ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 913c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* DBDMA is good to go */ 9141177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss host->flags |= HOST_F_DMA | HOST_F_DBDMA; 915ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 916c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return 0; 917c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss} 918ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 919c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussstatic void au1xmmc_dbdma_shutdown(struct au1xmmc_host *host) 920c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss{ 921c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->flags & HOST_F_DMA) { 922c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->flags &= ~HOST_F_DMA; 923c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_chan_free(host->tx_chan); 924c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_dbdma_chan_free(host->rx_chan); 925c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 926ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 927ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 92820f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Laussstatic void au1xmmc_enable_sdio_irq(struct mmc_host *mmc, int en) 92920f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss{ 93020f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss struct au1xmmc_host *host = mmc_priv(mmc); 93120f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss 93220f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss if (en) 93320f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss IRQ_ON(host, SD_CONFIG_SI); 93420f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss else 93520f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss IRQ_OFF(host, SD_CONFIG_SI); 93620f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss} 93720f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss 938bf8c80a6a5153e7f170f240731c650eeed6d78ffYoichi Yuasastatic const struct mmc_host_ops au1xmmc_ops = { 939ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov .request = au1xmmc_request, 940ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov .set_ios = au1xmmc_set_ios, 94182999770d6926193f50b42e713a92ee4028398e3Manuel Lauss .get_ro = au1xmmc_card_readonly, 942e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss .get_cd = au1xmmc_card_inserted, 94320f522ff5583a818922b3f650f6f7ef0e3e1aa68Manuel Lauss .enable_sdio_irq = au1xmmc_enable_sdio_irq, 944ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov}; 945ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 946c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussstatic int __devinit au1xmmc_probe(struct platform_device *pdev) 947c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss{ 948c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct mmc_host *mmc; 949c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct au1xmmc_host *host; 950c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct resource *r; 951809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss int ret, iflag; 952c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 953c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev); 954c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!mmc) { 955c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&pdev->dev, "no memory for mmc_host\n"); 956c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss ret = -ENOMEM; 957c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out0; 958ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 959ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 960c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host = mmc_priv(mmc); 961c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->mmc = mmc; 962c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->platdata = pdev->dev.platform_data; 963c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->pdev = pdev; 964ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 965c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss ret = -ENODEV; 966c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 967c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!r) { 968c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&pdev->dev, "no mmio defined\n"); 969c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out1; 970c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 971ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 9727a5ea56abc493fd43fb8d5b2f55d18396ec048f1H Hartley Sweeten host->ioarea = request_mem_region(r->start, resource_size(r), 973c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss pdev->name); 974c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!host->ioarea) { 975c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&pdev->dev, "mmio already in use\n"); 976c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out1; 977c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 978ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 979c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->iobase = (unsigned long)ioremap(r->start, 0x3c); 980c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!host->iobase) { 981c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&pdev->dev, "cannot remap mmio\n"); 982c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out2; 983c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 984c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 985c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 986c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (!r) { 987c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&pdev->dev, "no IRQ defined\n"); 988c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out3; 989c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 990c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->irq = r->start; 991ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 992c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss mmc->ops = &au1xmmc_ops; 993ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 994c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss mmc->f_min = 450000; 995c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss mmc->f_max = 24000000; 996fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman 997809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->max_blk_size = 2048; 998809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->max_blk_count = 512; 999809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 1000809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->ocr_avail = AU1XMMC_OCR; 1001809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; 1002809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; 1003809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 1004809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss iflag = IRQF_SHARED; /* Au1100/Au1200: one int for both ctrls */ 1005809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 10061177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss switch (alchemy_get_cputype()) { 10071177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss case ALCHEMY_CPU_AU1100: 10081177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE; 10091177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss break; 10101177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss case ALCHEMY_CPU_AU1200: 10111177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE; 1012809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 1013809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_CPU_AU1300: 1014809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss iflag = 0; /* nothing is shared */ 1015809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE; 1016809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->f_max = 52000000; 1017809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (host->ioarea->start == AU1100_SD0_PHYS_ADDR) 1018809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss mmc->caps |= MMC_CAP_8_BIT_DATA; 10191177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss break; 10201177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss } 1021ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1022809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss ret = request_irq(host->irq, au1xmmc_irq, iflag, DRIVER_NAME, host); 1023809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (ret) { 1024809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss dev_err(&pdev->dev, "cannot grab IRQ\n"); 1025809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss goto out3; 1026809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 1027ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1028c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->status = HOST_S_IDLE; 1029ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1030c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss /* board-specific carddetect setup, if any */ 1031c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->cd_setup) { 1032c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss ret = host->platdata->cd_setup(mmc, 1); 1033c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (ret) { 1034e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss dev_warn(&pdev->dev, "board CD setup failed\n"); 1035e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss mmc->caps |= MMC_CAP_NEEDS_POLL; 1036c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 1037e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss } else 1038e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss mmc->caps |= MMC_CAP_NEEDS_POLL; 1039ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 10403b839070f11295735ce8d9ef580c5eb23417aabfManuel Lauss /* platform may not be able to use all advertised caps */ 10413b839070f11295735ce8d9ef580c5eb23417aabfManuel Lauss if (host->platdata) 10423b839070f11295735ce8d9ef580c5eb23417aabfManuel Lauss mmc->caps &= ~(host->platdata->mask_host_caps); 10433b839070f11295735ce8d9ef580c5eb23417aabfManuel Lauss 1044c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss tasklet_init(&host->data_task, au1xmmc_tasklet_data, 1045c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss (unsigned long)host); 1046ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1047c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss tasklet_init(&host->finish_task, au1xmmc_tasklet_finish, 1048c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss (unsigned long)host); 1049ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 10501177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (has_dbdma()) { 10511177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss ret = au1xmmc_dbdma_init(host); 10521177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (ret) 1053d6748066ad0e8b2514545998f8367ebb3906f299Linus Torvalds pr_info(DRIVER_NAME ": DBDMA init failed; using PIO\n"); 10541177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss } 1055ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1056c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#ifdef CONFIG_LEDS_CLASS 1057c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->led) { 1058c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss struct led_classdev *led = host->platdata->led; 1059c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss led->name = mmc_hostname(mmc); 1060c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss led->brightness = LED_OFF; 1061c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss led->default_trigger = mmc_hostname(mmc); 1062c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss ret = led_classdev_register(mmc_dev(mmc), led); 1063c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (ret) 1064c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out5; 1065c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 1066c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#endif 1067ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1068c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xmmc_reset_controller(host); 1069ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1070c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss ret = mmc_add_host(mmc); 1071c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (ret) { 1072c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss dev_err(&pdev->dev, "cannot add mmc host\n"); 1073c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss goto out6; 1074c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss } 1075ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1076dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss platform_set_drvdata(pdev, host); 1077ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1078a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X" 1079c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss " (mode=%s)\n", pdev->id, host->iobase, 1080c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->flags & HOST_F_DMA ? "dma" : "pio"); 1081ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1082c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return 0; /* all ok */ 1083ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1084c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussout6: 1085c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#ifdef CONFIG_LEDS_CLASS 1086c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->led) 1087c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss led_classdev_unregister(host->platdata->led); 1088c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussout5: 1089c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#endif 1090c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(0, HOST_ENABLE(host)); 1091c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(0, HOST_CONFIG(host)); 1092c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(0, HOST_CONFIG2(host)); 1093c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_sync(); 1094c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 10951177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (host->flags & HOST_F_DBDMA) 10961177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss au1xmmc_dbdma_shutdown(host); 1097c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 1098c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss tasklet_kill(&host->data_task); 1099c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss tasklet_kill(&host->finish_task); 1100c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 1101e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss if (host->platdata && host->platdata->cd_setup && 1102e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss !(mmc->caps & MMC_CAP_NEEDS_POLL)) 1103c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss host->platdata->cd_setup(mmc, 0); 1104e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss 1105c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss free_irq(host->irq, host); 1106c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussout3: 1107c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss iounmap((void *)host->iobase); 1108c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussout2: 1109c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss release_resource(host->ioarea); 1110c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss kfree(host->ioarea); 1111c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussout1: 1112c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss mmc_free_host(mmc); 1113c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Laussout0: 1114c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss return ret; 1115ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 1116ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1117b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayrstatic int __devexit au1xmmc_remove(struct platform_device *pdev) 1118ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 1119dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss struct au1xmmc_host *host = platform_get_drvdata(pdev); 1120c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss 1121dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss if (host) { 1122dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss mmc_remove_host(host->mmc); 1123ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1124c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#ifdef CONFIG_LEDS_CLASS 1125c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss if (host->platdata && host->platdata->led) 1126c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss led_classdev_unregister(host->platdata->led); 1127c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss#endif 1128ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1129e2d2647702702ea08cb78cdc9eca8c24242aa9beManuel Lauss if (host->platdata && host->platdata->cd_setup && 1130dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss !(host->mmc->caps & MMC_CAP_NEEDS_POLL)) 1131dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss host->platdata->cd_setup(host->mmc, 0); 1132ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1133c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(0, HOST_ENABLE(host)); 1134c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(0, HOST_CONFIG(host)); 1135c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_writel(0, HOST_CONFIG2(host)); 1136c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au_sync(); 1137ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1138ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov tasklet_kill(&host->data_task); 1139ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov tasklet_kill(&host->finish_task); 1140ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 11411177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (host->flags & HOST_F_DBDMA) 11421177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss au1xmmc_dbdma_shutdown(host); 11431177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss 1144ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov au1xmmc_set_power(host, 0); 1145ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1146c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss free_irq(host->irq, host); 1147c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss iounmap((void *)host->iobase); 1148c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss release_resource(host->ioarea); 1149c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss kfree(host->ioarea); 1150ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1151dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss mmc_free_host(host->mmc); 1152dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss platform_set_drvdata(pdev, NULL); 1153ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov } 1154ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov return 0; 1155ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 1156ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1157dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss#ifdef CONFIG_PM 1158dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Laussstatic int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state) 1159dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss{ 1160dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss struct au1xmmc_host *host = platform_get_drvdata(pdev); 1161dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss int ret; 1162dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 11631a13f8fa76c880be41d6b1e6a2b44404bcbfdf9eMatt Fleming ret = mmc_suspend_host(host->mmc); 1164dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss if (ret) 1165dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss return ret; 1166dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 1167dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss au_writel(0, HOST_CONFIG2(host)); 1168dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss au_writel(0, HOST_CONFIG(host)); 1169dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss au_writel(0xffffffff, HOST_STATUS(host)); 1170dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss au_writel(0, HOST_ENABLE(host)); 1171dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss au_sync(); 1172dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 1173dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss return 0; 1174dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss} 1175dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 1176dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Laussstatic int au1xmmc_resume(struct platform_device *pdev) 1177dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss{ 1178dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss struct au1xmmc_host *host = platform_get_drvdata(pdev); 1179dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 1180dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss au1xmmc_reset_controller(host); 1181dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 1182dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss return mmc_resume_host(host->mmc); 1183dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss} 1184dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss#else 1185dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss#define au1xmmc_suspend NULL 1186dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss#define au1xmmc_resume NULL 1187dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss#endif 1188dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss 1189b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayrstatic struct platform_driver au1xmmc_driver = { 1190ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov .probe = au1xmmc_probe, 1191ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov .remove = au1xmmc_remove, 1192dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss .suspend = au1xmmc_suspend, 1193dd8572af68229a65b6716b286395ad7f5e2ecc48Manuel Lauss .resume = au1xmmc_resume, 1194b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayr .driver = { 1195b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayr .name = DRIVER_NAME, 1196bc65c724d5a2c61539b2c52680941505152fcf30Kay Sievers .owner = THIS_MODULE, 1197b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayr }, 1198ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov}; 1199ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1200ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic int __init au1xmmc_init(void) 1201ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 12021177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (has_dbdma()) { 12031177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride 12041177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss * of 8 bits. And since devices are shared, we need to create 12051177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss * our own to avoid freaking out other devices. 12061177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss */ 12071177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev); 12081177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (!memid) 1209d6748066ad0e8b2514545998f8367ebb3906f299Linus Torvalds pr_err("au1xmmc: cannot add memory dbdma\n"); 12101177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss } 1211b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayr return platform_driver_register(&au1xmmc_driver); 1212ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 1213ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1214ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovstatic void __exit au1xmmc_exit(void) 1215ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov{ 12161177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss if (has_dbdma() && memid) 1217c4223c2c91fa9e5addd6eadd804e57a925ac5e5eManuel Lauss au1xxx_ddma_del_device(memid); 12181177d99df2a0712764c03d13a3dda6f4e2b23725Manuel Lauss 1219b256f9df4a7da248263ed95c2517ddb714f9ca95Martin Michlmayr platform_driver_unregister(&au1xmmc_driver); 1220ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov} 1221ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1222ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovmodule_init(au1xmmc_init); 1223ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popovmodule_exit(au1xmmc_exit); 1224ba264b340396b8dd7348ef8531e5ac003a34ff4ePete Popov 1225ba264b340396b8dd7348ef8531e5ac003a34ff4ePete PopovMODULE_AUTHOR("Advanced Micro Devices, Inc"); 1226ba264b340396b8dd7348ef8531e5ac003a34ff4ePete PopovMODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX"); 1227ba264b340396b8dd7348ef8531e5ac003a34ff4ePete PopovMODULE_LICENSE("GPL"); 1228bc65c724d5a2c61539b2c52680941505152fcf30Kay SieversMODULE_ALIAS("platform:au1xxx-mmc"); 1229