diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.26/1027-glamo-mmc.patch.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches-2.6.26/1027-glamo-mmc.patch.patch | 1188 |
1 files changed, 0 insertions, 1188 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.26/1027-glamo-mmc.patch.patch b/target/linux/s3c24xx/patches-2.6.26/1027-glamo-mmc.patch.patch deleted file mode 100755 index 0eefdb7d66..0000000000 --- a/target/linux/s3c24xx/patches-2.6.26/1027-glamo-mmc.patch.patch +++ /dev/null @@ -1,1188 +0,0 @@ -From 448ffab41f86596340e9f34dc8141bf2ca857e4e Mon Sep 17 00:00:00 2001 -From: mokopatches <mokopatches@openmoko.org> -Date: Wed, 16 Jul 2008 14:44:51 +0100 -Subject: [PATCH] glamo-mmc.patch - ---- - drivers/mfd/glamo/Kconfig | 9 + - drivers/mfd/glamo/Makefile | 1 + - drivers/mfd/glamo/glamo-core.c | 17 +- - drivers/mfd/glamo/glamo-mci.c | 837 ++++++++++++++++++++++++++++++++++++++++ - drivers/mfd/glamo/glamo-mci.h | 76 ++++ - drivers/mfd/glamo/glamo-regs.h | 169 ++++++++- - 6 files changed, 1099 insertions(+), 10 deletions(-) - create mode 100644 drivers/mfd/glamo/glamo-mci.c - create mode 100644 drivers/mfd/glamo/glamo-mci.h - -diff --git a/drivers/mfd/glamo/Kconfig b/drivers/mfd/glamo/Kconfig -index b99f2b2..ec2ae3d 100644 ---- a/drivers/mfd/glamo/Kconfig -+++ b/drivers/mfd/glamo/Kconfig -@@ -33,3 +33,12 @@ config MFD_GLAMO_SPI_FB - control channel. This SPI interface is frequently used to - interconnect the LCM control interface. - -+config MFD_GLAMO_MCI -+ tristate "Glamo S3C SD/MMC Card Interface support" -+ depends on MFD_GLAMO && MMC -+ help -+ This selects a driver for the MCI interface found in -+ the S-Media GLAMO chip, as used in OpenMoko -+ neo1973 GTA-02. -+ -+ If unsure, say N. -\ No newline at end of file -diff --git a/drivers/mfd/glamo/Makefile b/drivers/mfd/glamo/Makefile -index fb53982..dc64d50 100644 ---- a/drivers/mfd/glamo/Makefile -+++ b/drivers/mfd/glamo/Makefile -@@ -8,4 +8,5 @@ obj-$(CONFIG_MFD_GLAMO_SPI_GPIO) += glamo-spi-gpio.o - - obj-$(CONFIG_MFD_GLAMO_FB) += glamo-fb.o - obj-$(CONFIG_MFD_GLAMO_SPI_FB) += glamo-lcm-spi.o -+obj-$(CONFIG_MFD_GLAMO_MCI) += glamo-mci.o - -diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c -index acf545f..8497de2 100644 ---- a/drivers/mfd/glamo/glamo-core.c -+++ b/drivers/mfd/glamo/glamo-core.c -@@ -440,7 +440,22 @@ int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) - { - spin_lock(&glamo->lock); - switch (engine) { -- /* FIXME: Implementation */ -+ case GLAMO_ENGINE_MMC: -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC, 0, -+ GLAMO_CLOCK_MMC_EN_M9CLK | -+ GLAMO_CLOCK_MMC_EN_TCLK | -+ GLAMO_CLOCK_MMC_DG_M9CLK | -+ GLAMO_CLOCK_MMC_DG_TCLK); -+ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), 0, -+ GLAMO_HOSTBUS2_MMIO_EN_MMC); -+ /* disable the TCLK divider clk input */ -+ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, 0, -+ GLAMO_CLOCK_GEN51_EN_DIV_TCLK); -+ /* good idea to hold the thing in reset when we power it off? */ -+/* writew(readw(glamo->base + GLAMO_REG_CLOCK_MMC) | -+ GLAMO_CLOCK_MMC_RESET, glamo->base + GLAMO_REG_CLOCK_MMC); -+*/ -+ break; - default: - break; - } -diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c -new file mode 100644 -index 0000000..f559e5e ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-mci.c -@@ -0,0 +1,837 @@ -+/* -+ * linux/drivers/mmc/host/glamo-mmc.c - Glamo MMC driver -+ * -+ * Copyright (C) 2007 OpenMoko, Inc, Andy Green <andy@openmoko.com> -+ * Based on S3C MMC driver that was: -+ * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/dma-mapping.h> -+#include <linux/clk.h> -+#include <linux/mmc/mmc.h> -+#include <linux/mmc/host.h> -+#include <linux/platform_device.h> -+#include <linux/irq.h> -+#include <linux/pcf50633.h> -+#include <linux/delay.h> -+#include <linux/interrupt.h> -+ -+#include <asm/dma.h> -+#include <asm/dma-mapping.h> -+#include <asm/io.h> -+ -+#include "glamo-mci.h" -+#include "glamo-core.h" -+#include "glamo-regs.h" -+ -+/* from glamo-core.c */ -+extern struct glamo_mci_pdata glamo_mci_def_pdata; -+ -+ -+#define DRIVER_NAME "glamo-mci" -+#define RESSIZE(ressource) (((ressource)->end - (ressource)->start) + 1) -+ -+static void glamo_mci_send_request(struct mmc_host *mmc); -+ -+unsigned char CRC7(u8 * pu8, int cnt) -+{ -+ u8 crc = 0; -+ -+ while (cnt--) { -+ int n; -+ u8 d = *pu8++; -+ for (n = 0; n < 8; n++) { -+ crc <<= 1; -+ if ((d & 0x80) ^ (crc & 0x80)) -+ crc ^= 0x09; -+ d <<= 1; -+ } -+ } -+ return (crc << 1) | 1; -+} -+ -+/* these _dly versions account for the dead time rules for reg access */ -+static u16 readw_dly(u16 __iomem * pu16) -+{ -+ glamo_reg_access_delay(); -+ return readw(pu16); -+} -+ -+static void writew_dly(u16 val, u16 __iomem * pu16) -+{ -+ glamo_reg_access_delay(); -+ writew(val, pu16); -+} -+ -+static int get_data_buffer(struct glamo_mci_host *host, -+ volatile u32 *words, volatile u16 **pointer) -+{ -+ struct scatterlist *sg; -+ -+ *words = 0; -+ *pointer = NULL; -+ -+ if (host->pio_active == XFER_NONE) -+ return -EINVAL; -+ -+ if ((!host->mrq) || (!host->mrq->data)) -+ return -EINVAL; -+ -+ if (host->pio_sgptr >= host->mrq->data->sg_len) { -+ dev_dbg(&host->pdev->dev, "no more buffers (%i/%i)\n", -+ host->pio_sgptr, host->mrq->data->sg_len); -+ return -EBUSY; -+ } -+ sg = &host->mrq->data->sg[host->pio_sgptr]; -+ -+ *words = sg->length >> 1; /* we are working with a 16-bit data bus */ -+ *pointer = page_address(sg_page(sg)) + sg->offset; -+ -+ BUG_ON(((long)(*pointer)) & 1); -+ -+ host->pio_sgptr++; -+ -+ /* dev_info(&host->pdev->dev, "new buffer (%i/%i)\n", -+ host->pio_sgptr, host->mrq->data->sg_len); */ -+ return 0; -+} -+ -+static void do_pio_read(struct glamo_mci_host *host) -+{ -+ int res; -+ u16 __iomem *from_ptr = host->base_data + (RESSIZE(host->mem_data) / -+ sizeof(u16) / 2); -+#ifdef DEBUG -+ u16 * block; -+#endif -+ -+ while (1) { -+ res = get_data_buffer(host, &host->pio_words, &host->pio_ptr); -+ if (res) { -+ host->pio_active = XFER_NONE; -+ host->complete_what = COMPLETION_FINALIZE; -+ -+ dev_dbg(&host->pdev->dev, "pio_read(): " -+ "complete (no more data).\n"); -+ return; -+ } -+ -+ dev_dbg(&host->pdev->dev, "pio_read(): host->pio_words: %d\n", -+ host->pio_words); -+ -+ host->pio_count += host->pio_words << 1; -+ -+#ifdef DEBUG -+ block = (u16 *)host->pio_ptr; -+ res = host->pio_words << 1; -+#endif -+ while (host->pio_words--) -+ *host->pio_ptr++ = *from_ptr++; -+#ifdef DEBUG -+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, -+ (void *)block, res, 1); -+#endif -+ } -+} -+ -+static int do_pio_write(struct glamo_mci_host *host) -+{ -+ int res = 0; -+ volatile u16 __iomem *to_ptr = host->base_data; -+ int err = 0; -+ -+ dev_dbg(&host->pdev->dev, "pio_write():\n"); -+ while (!res) { -+ res = get_data_buffer(host, &host->pio_words, &host->pio_ptr); -+ if (res) -+ continue; -+ -+ dev_dbg(&host->pdev->dev, "pio_write():new source: [%i]@[%p]\n", -+ host->pio_words, host->pio_ptr); -+ -+ host->pio_count += host->pio_words << 1; -+ while (host->pio_words--) -+ writew(*host->pio_ptr++, to_ptr++); -+ } -+ -+ dev_dbg(&host->pdev->dev, "pio_write(): complete\n"); -+ host->pio_active = XFER_NONE; -+ return err; -+} -+ -+static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc) -+{ -+ struct glamo_mci_host *host = (struct glamo_mci_host *) -+ desc->handler_data; -+ u16 status; -+ struct mmc_command *cmd; -+ unsigned long iflags; -+ -+ if (!host) -+ return; -+ if (!host->mrq) -+ return; -+ cmd = host->mrq->cmd; -+ if (!cmd) -+ return; -+ -+ spin_lock_irqsave(&host->complete_lock, iflags); -+ -+ status = readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1); -+ -+ /* ack this interrupt source */ -+ writew(GLAMO_IRQ_MMC, -+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_IRQ_CLEAR); -+ -+ if (status & (GLAMO_STAT1_MMC_RTOUT | -+ GLAMO_STAT1_MMC_DTOUT)) -+ cmd->error = -ETIMEDOUT; -+ if (status & (GLAMO_STAT1_MMC_BWERR | -+ GLAMO_STAT1_MMC_BRERR)) -+ cmd->error = -EILSEQ; -+ if (cmd->error) { -+ dev_err(&host->pdev->dev, "Error after cmd: 0x%x\n", status); -+ goto done; -+ } -+ -+ if (host->pio_active == XFER_READ) -+ do_pio_read(host); -+ -+ host->mrq->data->bytes_xfered = host->pio_count; -+ dev_dbg(&host->pdev->dev, "status = 0x%04x count=%d\n", -+ status, host->pio_count); -+ -+ /* issue STOP if we have been given one to use */ -+ if (host->mrq->stop) { -+ host->cmd_is_stop = 1; -+ glamo_mci_send_request(host->mmc); -+ host->cmd_is_stop = 0; -+ } -+done: -+ host->complete_what = COMPLETION_NONE; -+ host->mrq = NULL; -+ mmc_request_done(host->mmc, cmd->mrq); -+ spin_unlock_irqrestore(&host->complete_lock, iflags); -+} -+ -+static int glamo_mci_send_command(struct glamo_mci_host *host, -+ struct mmc_command *cmd) -+{ -+ u8 u8a[6]; -+ u16 fire = 0; -+ -+ /* if we can't do it, reject as busy */ -+ if (!readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1) & -+ GLAMO_STAT1_MMC_IDLE) { -+ host->mrq = NULL; -+ cmd->error = -EBUSY; -+ mmc_request_done(host->mmc, host->mrq); -+ return -EBUSY; -+ } -+ -+ /* create an array in wire order for CRC computation */ -+ u8a[0] = 0x40 | (cmd->opcode & 0x3f); -+ u8a[1] = (u8)(cmd->arg >> 24); -+ u8a[2] = (u8)(cmd->arg >> 16); -+ u8a[3] = (u8)(cmd->arg >> 8); -+ u8a[4] = (u8)cmd->arg; -+ u8a[5] = CRC7(&u8a[0], 5); /* CRC7 on first 5 bytes of packet */ -+ -+ /* issue the wire-order array including CRC in register order */ -+ writew_dly((u8a[4] << 8) | u8a[5], host->base + GLAMO_REG_MMC_CMD_REG1); -+ writew_dly((u8a[2] << 8) | u8a[3], host->base + GLAMO_REG_MMC_CMD_REG2); -+ writew_dly((u8a[0] << 8) | u8a[1], host->base + GLAMO_REG_MMC_CMD_REG3); -+ -+ /* command index toggle */ -+ fire |= (host->ccnt & 1) << 12; -+ -+ /* set type of command */ -+ switch (mmc_cmd_type(cmd)) { -+ case MMC_CMD_BC: -+ fire |= GLAMO_FIRE_MMC_CMDT_BNR; -+ break; -+ case MMC_CMD_BCR: -+ fire |= GLAMO_FIRE_MMC_CMDT_BR; -+ break; -+ case MMC_CMD_AC: -+ fire |= GLAMO_FIRE_MMC_CMDT_AND; -+ break; -+ case MMC_CMD_ADTC: -+ fire |= GLAMO_FIRE_MMC_CMDT_AD; -+ break; -+ } -+ /* -+ * if it expects a response, set the type expected -+ * -+ * R1, Length : 48bit, Normal response -+ * R1b, Length : 48bit, same R1, but added card busy status -+ * R2, Length : 136bit (really 128 bits with CRC snipped) -+ * R3, Length : 48bit (OCR register value) -+ * R4, Length : 48bit, SDIO_OP_CONDITION, Reverse SDIO Card -+ * R5, Length : 48bit, IO_RW_DIRECTION, Reverse SDIO Card -+ * R6, Length : 48bit (RCA register) -+ * R7, Length : 48bit (interface condition, VHS(voltage supplied), -+ * check pattern, CRC7) -+ */ -+ switch (mmc_resp_type(cmd)) { -+ case MMC_RSP_R6: /* same index as R7 and R1 */ -+ fire |= GLAMO_FIRE_MMC_RSPT_R1; -+ break; -+ case MMC_RSP_R1B: -+ fire |= GLAMO_FIRE_MMC_RSPT_R1b; -+ break; -+ case MMC_RSP_R2: -+ fire |= GLAMO_FIRE_MMC_RSPT_R2; -+ break; -+ case MMC_RSP_R3: -+ fire |= GLAMO_FIRE_MMC_RSPT_R3; -+ break; -+ /* R4 and R5 supported by chip not defined in linux/mmc/core.h (sdio) */ -+ } -+ /* -+ * From the command index, set up the command class in the host ctrllr -+ * -+ * missing guys present on chip but couldn't figure out how to use yet: -+ * 0x0 "stream read" -+ * 0x9 "cancel running command" -+ */ -+ switch (cmd->opcode) { -+ case MMC_READ_SINGLE_BLOCK: -+ fire |= GLAMO_FIRE_MMC_CC_SBR; /* single block read */ -+ break; -+ case MMC_SWITCH: /* 64 byte payload */ -+ case 0x33: /* observed issued by MCI */ -+ case MMC_READ_MULTIPLE_BLOCK: -+ /* we will get an interrupt off this */ -+ if (!cmd->mrq->stop) -+ /* multiblock no stop */ -+ fire |= GLAMO_FIRE_MMC_CC_MBRNS; -+ else -+ /* multiblock with stop */ -+ fire |= GLAMO_FIRE_MMC_CC_MBRS; -+ break; -+ case MMC_WRITE_BLOCK: -+ fire |= GLAMO_FIRE_MMC_CC_SBW; /* single block write */ -+ break; -+ case MMC_WRITE_MULTIPLE_BLOCK: -+ if (cmd->mrq->stop) -+ /* multiblock with stop */ -+ fire |= GLAMO_FIRE_MMC_CC_MBWS; -+ else -+ /* multiblock NO stop-- 'RESERVED'? */ -+ fire |= GLAMO_FIRE_MMC_CC_MBWNS; -+ break; -+ case MMC_STOP_TRANSMISSION: -+ fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */ -+ break; -+ default: -+ fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */ -+ break; -+ } -+ /* enforce timeout */ -+ if (cmd->data) { -+ if (cmd->data->timeout_clks) -+ writew_dly(cmd->data->timeout_clks >> 4, /* / 16 clks */ -+ host->base + GLAMO_REG_MMC_TIMEOUT); -+ else -+ writew_dly(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT); -+ } else -+ writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT); -+ -+ /* Generate interrupt on txfer; drive strength max */ -+ writew_dly((readw_dly(host->base + GLAMO_REG_MMC_BASIC) & 0xfe) | -+ 0x0800 | GLAMO_BASIC_MMC_NO_CLK_RD_WAIT | -+ GLAMO_BASIC_MMC_EN_COMPL_INT | -+ GLAMO_BASIC_MMC_EN_DR_STR0 | -+ GLAMO_BASIC_MMC_EN_DR_STR1, -+ host->base + GLAMO_REG_MMC_BASIC); -+ -+ /* send the command out on the wire */ -+ /* dev_info(&host->pdev->dev, "Using FIRE %04X\n", fire); */ -+ writew_dly(fire, host->base + GLAMO_REG_MMC_CMD_FIRE); -+ cmd->error = 0; -+ return 0; -+} -+ -+static int glamo_mci_prepare_pio(struct glamo_mci_host *host, -+ struct mmc_data *data) -+{ -+ /* -+ * the S-Media-internal RAM offset for our MMC buffer -+ * Read is halfway up the buffer and write is at the start -+ */ -+ if (data->flags & MMC_DATA_READ) { -+ writew_dly((u16)(GLAMO_FB_SIZE + (RESSIZE(host->mem_data) / 2)), -+ host->base + GLAMO_REG_MMC_WDATADS1); -+ writew_dly((u16)((GLAMO_FB_SIZE + -+ (RESSIZE(host->mem_data) / 2)) >> 16), -+ host->base + GLAMO_REG_MMC_WDATADS2); -+ } else { -+ writew_dly((u16)GLAMO_FB_SIZE, host->base + -+ GLAMO_REG_MMC_RDATADS1); -+ writew_dly((u16)(GLAMO_FB_SIZE >> 16), host->base + -+ GLAMO_REG_MMC_RDATADS2); -+ } -+ -+ /* set up the block info */ -+ writew_dly(data->blksz, host->base + GLAMO_REG_MMC_DATBLKLEN); -+ writew_dly(data->blocks, host->base + GLAMO_REG_MMC_DATBLKCNT); -+ dev_dbg(&host->pdev->dev, "(blksz=%d, count=%d)\n", -+ data->blksz, data->blocks); -+ host->pio_sgptr = 0; -+ host->pio_words = 0; -+ host->pio_count = 0; -+ host->pio_active = 0; -+ /* if write, prep the write into the shared RAM before the command */ -+ if (data->flags & MMC_DATA_WRITE) { -+ host->pio_active = XFER_WRITE; -+ return do_pio_write(host); -+ } -+ host->pio_active = XFER_READ; -+ return 0; -+} -+ -+static void glamo_mci_send_request(struct mmc_host *mmc) -+{ -+ struct glamo_mci_host *host = mmc_priv(mmc); -+ struct mmc_request *mrq = host->mrq; -+ struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd; -+ u16 * pu16 = (u16 *)&cmd->resp[0]; -+ u16 * reg_resp = (u16 *)(host->base + GLAMO_REG_MMC_CMD_RSP1); -+ u16 status; -+ int n; -+ -+ host->ccnt++; -+ /* -+ * somehow 2.6.24 MCI manages to issue MMC_WRITE_BLOCK *without* the -+ * MMC_DATA_WRITE flag, WTF? Work around the madness. -+ */ -+ if (cmd->opcode == MMC_WRITE_BLOCK) -+ if (mrq->data) -+ mrq->data->flags |= MMC_DATA_WRITE; -+ -+ /* this guy has data to read/write? */ -+ if ((!host->cmd_is_stop) && cmd->data) { -+ int res; -+ host->dcnt++; -+ res = glamo_mci_prepare_pio(host, cmd->data); -+ if (res) { -+ cmd->error = -EIO; -+ cmd->data->error = -EIO; -+ mmc_request_done(mmc, mrq); -+ return; -+ } -+ } -+ -+ dev_dbg(&host->pdev->dev,"cmd 0x%x, " -+ "arg 0x%x data=%p mrq->stop=%p flags 0x%x\n", -+ cmd->opcode, cmd->arg, cmd->data, cmd->mrq->stop, -+ cmd->flags); -+ -+ if (glamo_mci_send_command(host, cmd)) -+ return; -+ /* -+ * we must spin until response is ready or timed out -+ * -- we don't get interrupts unless there is a bulk rx -+ */ -+ do -+ status = readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1); -+ while ((((status >> 15) & 1) != (host->ccnt & 1)) || -+ (!(status & (GLAMO_STAT1_MMC_RB_RRDY | -+ GLAMO_STAT1_MMC_RTOUT | -+ GLAMO_STAT1_MMC_DTOUT | -+ GLAMO_STAT1_MMC_BWERR | -+ GLAMO_STAT1_MMC_BRERR)))); -+ -+ if (status & (GLAMO_STAT1_MMC_RTOUT | -+ GLAMO_STAT1_MMC_DTOUT)) -+ cmd->error = -ETIMEDOUT; -+ if (status & (GLAMO_STAT1_MMC_BWERR | -+ GLAMO_STAT1_MMC_BRERR)) -+ cmd->error = -EILSEQ; -+ -+ if (host->cmd_is_stop) -+ return; -+ -+ if (cmd->error) { -+ dev_err(&host->pdev->dev, "Error after cmd: 0x%x\n", status); -+ goto done; -+ } -+ /* -+ * mangle the response registers in two different exciting -+ * undocumented ways discovered by trial and error -+ */ -+ if (mmc_resp_type(cmd) == MMC_RSP_R2) -+ /* grab the response */ -+ for (n = 0; n < 8; n++) /* super mangle power 1 */ -+ pu16[n ^ 6] = readw_dly(®_resp[n]); -+ else -+ for (n = 0; n < 3; n++) /* super mangle power 2 */ -+ pu16[n] = (readw_dly(®_resp[n]) >> 8) | -+ (readw_dly(®_resp[n + 1]) << 8); -+ /* -+ * if we don't have bulk data to take care of, we're done -+ */ -+ if (!cmd->data) -+ goto done; -+ if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE))) -+ goto done; -+ /* -+ * Otherwise can can use the interrupt as async completion -- -+ * if there is read data coming, or we wait for write data to complete, -+ * exit without mmc_request_done() as the payload interrupt -+ * will service it -+ */ -+ dev_dbg(&host->pdev->dev, "Waiting for payload data\n"); -+ /* -+ * if the glamo INT# line isn't wired (*cough* it can happen) -+ * I'm afraid we have to spin on the IRQ status bit and "be -+ * our own INT# line" -+ */ -+ if (!glamo_mci_def_pdata.pglamo->irq_works) { -+ /* we have faith we will get an "interrupt"... */ -+ while (!(readw_dly(glamo_mci_def_pdata.pglamo->base + -+ GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) -+ ; -+ /* yay we are an interrupt controller! -- call the ISR */ -+ glamo_mci_irq(IRQ_GLAMO(GLAMO_IRQIDX_MMC), -+ irq_desc + IRQ_GLAMO(GLAMO_IRQIDX_MMC)); -+ } -+ return; -+ -+done: -+ host->complete_what = COMPLETION_NONE; -+ host->mrq = NULL; -+ mmc_request_done(host->mmc, cmd->mrq); -+} -+ -+static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct glamo_mci_host *host = mmc_priv(mmc); -+ -+ host->cmd_is_stop = 0; -+ host->mrq = mrq; -+ glamo_mci_send_request(mmc); -+} -+ -+static void glamo_mci_reset(struct glamo_mci_host *host) -+{ -+ /* reset MMC controller */ -+ writew_dly(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK | -+ GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK | -+ GLAMO_CLOCK_MMC_EN_M9CLK, -+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_MMC); -+ msleep(1); -+ /* and disable reset */ -+ writew_dly(GLAMO_CLOCK_MMC_DG_TCLK | -+ GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK | -+ GLAMO_CLOCK_MMC_EN_M9CLK, -+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_MMC); -+} -+ -+static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct glamo_mci_host *host = mmc_priv(mmc); -+ int mci_psc = 0; -+ int n = 0; -+ -+ /* Set power */ -+ switch(ios->power_mode) { -+ case MMC_POWER_ON: -+ case MMC_POWER_UP: -+ if (host->power_mode_current != MMC_POWER_OFF) -+ break; -+ if (host->vdd_current != ios->vdd) { -+ host->pdata->glamo_set_mci_power(ios->power_mode, -+ ios->vdd); -+ host->vdd_current = ios->vdd; -+ } -+ glamo_engine_enable(glamo_mci_def_pdata.pglamo, -+ GLAMO_ENGINE_MMC); -+ glamo_mci_reset(host); -+ break; -+ -+ case MMC_POWER_OFF: -+ default: -+ if (host->power_mode_current == MMC_POWER_OFF) -+ break; -+ glamo_engine_disable(glamo_mci_def_pdata.pglamo, -+ GLAMO_ENGINE_MMC); -+ host->pdata->glamo_set_mci_power(MMC_POWER_OFF, 0); -+ host->vdd_current = -1; -+ break; -+ } -+ host->power_mode_current = ios->power_mode; -+ -+ /* Set clock */ -+/* if (ios->clock) { */ -+ for (mci_psc = 0; mci_psc < 256; mci_psc++) { -+ host->real_rate = host->clk_rate / (mci_psc + 1); -+ if (host->real_rate <= ios->clock) -+ break; -+ } -+ if (mci_psc > 255) -+ mci_psc = 255; -+ host->clk_div = mci_psc; -+ /* set the nearest prescaler factor -+ * -+ * register shared with SCLK divisor -- no chance of race because -+ * we don't use sensor interface -+ */ -+ writew_dly((readw(glamo_mci_def_pdata.pglamo->base + -+ GLAMO_REG_CLOCK_GEN8) & 0xff00) | host->clk_div, -+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8); -+ /* enable clock to divider input */ -+ writew_dly(readw(glamo_mci_def_pdata.pglamo->base + -+ GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK, -+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1); -+#if 0 -+ } else { /* stop clock */ -+ host->real_rate = 0; -+ /* remove clock from divider input */ -+ writew(readw(glamo_mci_def_pdata.pglamo->base + -+ GLAMO_REG_CLOCK_GEN5_1) & (~GLAMO_CLOCK_GEN51_EN_DIV_TCLK), -+ glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1); -+ } -+#endif -+ if ((ios->power_mode == MMC_POWER_ON) || -+ (ios->power_mode == MMC_POWER_UP)) { -+ dev_info(&host->pdev->dev, -+ "powered (vdd = %d) clk: %lukHz div=%d (req: %ukHz). " -+ "Bus width=%d\n",ios->vdd, -+ host->real_rate / 1000, mci_psc, -+ ios->clock / 1000, ios->bus_width); -+ } else -+ dev_info(&host->pdev->dev, "glamo_mci_set_ios: power down.\n"); -+ -+ /* set bus width */ -+ host->bus_width = ios->bus_width; -+ if (host->bus_width == MMC_BUS_WIDTH_4) -+ n = GLAMO_BASIC_MMC_EN_4BIT_DATA; -+ writew_dly((readw_dly(host->base + GLAMO_REG_MMC_BASIC) & -+ (~GLAMO_BASIC_MMC_EN_4BIT_DATA)) | n, -+ host->base + GLAMO_REG_MMC_BASIC); -+} -+ -+ -+/* -+ * no physical write protect supported by us -+ */ -+static int glamo_mci_get_ro(struct mmc_host *mmc) -+{ -+ return 0; -+} -+ -+static struct mmc_host_ops glamo_mci_ops = { -+ .request = glamo_mci_request, -+ .set_ios = glamo_mci_set_ios, -+ .get_ro = glamo_mci_get_ro, -+}; -+ -+static int glamo_mci_probe(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc; -+ struct glamo_mci_host *host; -+ int ret; -+ -+ dev_info(&pdev->dev, "glamo_mci driver (C)2007 OpenMoko, Inc\n"); -+ -+ mmc = mmc_alloc_host(sizeof(struct glamo_mci_host), &pdev->dev); -+ if (!mmc) { -+ ret = -ENOMEM; -+ goto probe_out; -+ } -+ -+ host = mmc_priv(mmc); -+ host->mmc = mmc; -+ host->pdev = pdev; -+ host->pdata = &glamo_mci_def_pdata; -+ host->power_mode_current = MMC_POWER_OFF; -+ -+ host->complete_what = COMPLETION_NONE; -+ host->pio_active = XFER_NONE; -+ -+ spin_lock_init(&host->complete_lock); -+ -+ host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!host->mem) { -+ dev_err(&pdev->dev, -+ "failed to get io memory region resouce.\n"); -+ -+ ret = -ENOENT; -+ goto probe_free_host; -+ } -+ -+ host->mem = request_mem_region(host->mem->start, -+ RESSIZE(host->mem), pdev->name); -+ -+ if (!host->mem) { -+ dev_err(&pdev->dev, "failed to request io memory region.\n"); -+ ret = -ENOENT; -+ goto probe_free_host; -+ } -+ -+ host->base = ioremap(host->mem->start, RESSIZE(host->mem)); -+ if (!host->base) { -+ dev_err(&pdev->dev, "failed to ioremap() io memory region.\n"); -+ ret = -EINVAL; -+ goto probe_free_mem_region; -+ } -+ -+ /* set the handler for our bit of the shared chip irq register */ -+ set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_MMC), glamo_mci_irq); -+ /* stash host as our handler's private data */ -+ set_irq_data(IRQ_GLAMO(GLAMO_IRQIDX_MMC), host); -+ -+ /* Get ahold of our data buffer we use for data in and out on MMC */ -+ host->mem_data = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (!host->mem_data) { -+ dev_err(&pdev->dev, -+ "failed to get io memory region resource.\n"); -+ ret = -ENOENT; -+ goto probe_iounmap; -+ } -+ -+ host->mem_data = request_mem_region(host->mem_data->start, -+ RESSIZE(host->mem_data), pdev->name); -+ -+ if (!host->mem_data) { -+ dev_err(&pdev->dev, "failed to request io memory region.\n"); -+ ret = -ENOENT; -+ goto probe_iounmap; -+ } -+ host->base_data = ioremap(host->mem_data->start, -+ RESSIZE(host->mem_data)); -+ host->data_max_size = RESSIZE(host->mem_data); -+ -+ if (host->base_data == 0) { -+ dev_err(&pdev->dev, "failed to ioremap() io memory region.\n"); -+ ret = -EINVAL; -+ goto probe_free_mem_region_data; -+ } -+ -+ host->vdd_current = 0; -+ host->clk_rate = 50000000; /* really it's 49152000 */ -+ host->clk_div = 16; -+ -+ /* explain our host controller capabilities */ -+ mmc->ops = &glamo_mci_ops; -+ mmc->ocr_avail = host->pdata->ocr_avail; -+ mmc->caps = MMC_CAP_4_BIT_DATA | -+ MMC_CAP_MULTIWRITE | -+ MMC_CAP_MMC_HIGHSPEED | -+ MMC_CAP_SD_HIGHSPEED; -+ mmc->f_min = host->clk_rate / 256; -+ /* -+ * held at /4 due to concerns of 100R recommended series resistor -+ * allows 16MHz @ 4-bit --> 8MBytes/sec raw -+ */ -+ mmc->f_max = host->clk_rate / 3; -+ -+ mmc->max_blk_count = (1 << 16) - 1; /* GLAMO_REG_MMC_RB_BLKCNT */ -+ mmc->max_blk_size = (1 << 12) - 1; /* GLAMO_REG_MMC_RB_BLKLEN */ -+ mmc->max_req_size = RESSIZE(host->mem_data) / 2; -+ mmc->max_seg_size = mmc->max_req_size; -+ mmc->max_phys_segs = 1; /* hw doesn't talk about segs??? */ -+ mmc->max_hw_segs = 1; -+ -+ dev_info(&host->pdev->dev, "probe: mapped mci_base:%p irq:%u.\n", -+ host->base, host->irq); -+ -+ if ((ret = mmc_add_host(mmc))) { -+ dev_err(&pdev->dev, "failed to add mmc host.\n"); -+ goto probe_free_mem_region_data; -+ } -+ -+ platform_set_drvdata(pdev, mmc); -+ -+ dev_info(&pdev->dev,"initialisation done.\n"); -+ return 0; -+ -+ probe_free_mem_region_data: -+ release_mem_region(host->mem_data->start, RESSIZE(host->mem_data)); -+ -+ probe_iounmap: -+ iounmap(host->base); -+ -+ probe_free_mem_region: -+ release_mem_region(host->mem->start, RESSIZE(host->mem)); -+ -+ probe_free_host: -+ mmc_free_host(mmc); -+ probe_out: -+ return ret; -+} -+ -+static int glamo_mci_remove(struct platform_device *pdev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(pdev); -+ struct glamo_mci_host *host = mmc_priv(mmc); -+ -+ mmc_remove_host(mmc); -+ /* stop using our handler, revert it to default */ -+ set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_MMC), handle_level_irq); -+ iounmap(host->base); -+ iounmap(host->base_data); -+ release_mem_region(host->mem->start, RESSIZE(host->mem)); -+ release_mem_region(host->mem_data->start, RESSIZE(host->mem_data)); -+ mmc_free_host(mmc); -+ -+ glamo_engine_disable(glamo_mci_def_pdata.pglamo, GLAMO_ENGINE_MMC); -+ return 0; -+} -+ -+ -+#ifdef CONFIG_PM -+ -+static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(dev); -+ -+ return mmc_suspend_host(mmc, state); -+} -+ -+static int glamo_mci_resume(struct platform_device *dev) -+{ -+ struct mmc_host *mmc = platform_get_drvdata(dev); -+ -+ return mmc_resume_host(mmc); -+} -+ -+#else /* CONFIG_PM */ -+#define glamo_mci_suspend NULL -+#define glamo_mci_resume NULL -+#endif /* CONFIG_PM */ -+ -+ -+static struct platform_driver glamo_mci_driver = -+{ -+ .driver.name = "glamo-mci", -+ .probe = glamo_mci_probe, -+ .remove = glamo_mci_remove, -+ .suspend = glamo_mci_suspend, -+ .resume = glamo_mci_resume, -+}; -+ -+static int __init glamo_mci_init(void) -+{ -+ platform_driver_register(&glamo_mci_driver); -+ return 0; -+} -+ -+static void __exit glamo_mci_exit(void) -+{ -+ platform_driver_unregister(&glamo_mci_driver); -+} -+ -+module_init(glamo_mci_init); -+module_exit(glamo_mci_exit); -+ -+MODULE_DESCRIPTION("Glamo MMC/SD Card Interface driver"); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Andy Green <andy@openmoko.com>"); -diff --git a/drivers/mfd/glamo/glamo-mci.h b/drivers/mfd/glamo/glamo-mci.h -new file mode 100644 -index 0000000..40c3e24 ---- /dev/null -+++ b/drivers/mfd/glamo/glamo-mci.h -@@ -0,0 +1,76 @@ -+/* -+ * linux/drivers/mmc/host/glamo-mmc.h - GLAMO MCI driver -+ * -+ * Copyright (C) 2007-2008 OpenMoko, Inc, Andy Green <andy@openmoko.com> -+ * based on S3C MMC driver --> -+ * Copyright (C) 2004-2006 Thomas Kleffel, All Rights Reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+ -+enum glamo_mci_waitfor { -+ COMPLETION_NONE, -+ COMPLETION_FINALIZE, -+ COMPLETION_CMDSENT, -+ COMPLETION_RSPFIN, -+ COMPLETION_XFERFINISH, -+ COMPLETION_XFERFINISH_RSPFIN, -+}; -+ -+struct glamo_mci_host { -+ struct platform_device *pdev; -+ struct glamo_mci_pdata *pdata; -+ struct mmc_host *mmc; -+ struct resource *mem; -+ struct resource *mem_data; -+ struct clk *clk; -+ void __iomem *base; -+ u16 __iomem *base_data; -+ int irq; -+ int irq_cd; -+ int dma; -+ int data_max_size; -+ -+ int power_mode_current; -+ unsigned int vdd_current; -+ -+ unsigned long clk_rate; -+ unsigned long clk_div; -+ unsigned long real_rate; -+ u8 prescaler; -+ -+ unsigned sdiimsk; -+ int dodma; -+ -+ volatile int dmatogo; -+ -+ struct mmc_request *mrq; -+ int cmd_is_stop; -+ -+ spinlock_t complete_lock; -+ volatile enum glamo_mci_waitfor -+ complete_what; -+ -+ volatile int dma_complete; -+ -+ volatile u32 pio_sgptr; -+ volatile u32 pio_words; -+ volatile u32 pio_count; -+ volatile u16 *pio_ptr; -+#define XFER_NONE 0 -+#define XFER_READ 1 -+#define XFER_WRITE 2 -+ volatile u32 pio_active; -+ -+ int bus_width; -+ -+ char dbgmsg_cmd[301]; -+ char dbgmsg_dat[301]; -+ volatile char *status; -+ -+ unsigned int ccnt, dcnt; -+ struct tasklet_struct pio_tasklet; -+}; -diff --git a/drivers/mfd/glamo/glamo-regs.h b/drivers/mfd/glamo/glamo-regs.h -index 151cd66..8f6c45c 100644 ---- a/drivers/mfd/glamo/glamo-regs.h -+++ b/drivers/mfd/glamo/glamo-regs.h -@@ -150,16 +150,28 @@ enum glamo_reg_mem_dram2 { - GLAMO_MEM_DRAM2_DEEP_PWRDOWN = (1 << 12), - }; - -+enum glamo_irq_index { -+ GLAMO_IRQIDX_HOSTBUS = 0, -+ GLAMO_IRQIDX_JPEG = 1, -+ GLAMO_IRQIDX_MPEG = 2, -+ GLAMO_IRQIDX_MPROC1 = 3, -+ GLAMO_IRQIDX_MPROC0 = 4, -+ GLAMO_IRQIDX_CMDQUEUE = 5, -+ GLAMO_IRQIDX_2D = 6, -+ GLAMO_IRQIDX_MMC = 7, -+ GLAMO_IRQIDX_RISC = 8, -+}; -+ - enum glamo_irq { -- GLAMO_IRQ_HOSTBUS = 0x0001, -- GLAMO_IRQ_JPEG = 0x0002, -- GLAMO_IRQ_MPEG = 0x0004, -- GLAMO_IRQ_MPROC1 = 0x0008, -- GLAMO_IRQ_MPROC0 = 0x0010, -- GLAMO_IRQ_CMDQUEUE = 0x0020, -- GLAMO_IRQ_2D = 0x0040, -- GLAMO_IRQ_MMC = 0x0080, -- GLAMO_IRQ_RISC = 0x0100, -+ GLAMO_IRQ_HOSTBUS = (1 << GLAMO_IRQIDX_HOSTBUS), -+ GLAMO_IRQ_JPEG = (1 << GLAMO_IRQIDX_JPEG), -+ GLAMO_IRQ_MPEG = (1 << GLAMO_IRQIDX_MPEG), -+ GLAMO_IRQ_MPROC1 = (1 << GLAMO_IRQIDX_MPROC1), -+ GLAMO_IRQ_MPROC0 = (1 << GLAMO_IRQIDX_MPROC0), -+ GLAMO_IRQ_CMDQUEUE = (1 << GLAMO_IRQIDX_CMDQUEUE), -+ GLAMO_IRQ_2D = (1 << GLAMO_IRQIDX_2D), -+ GLAMO_IRQ_MMC = (1 << GLAMO_IRQIDX_MMC), -+ GLAMO_IRQ_RISC = (1 << GLAMO_IRQIDX_RISC), - }; - - enum glamo_reg_clock_host { -@@ -197,6 +209,145 @@ enum glamo_reg_clock_mmc { - GLAMO_CLOCK_MMC_RESET = 0x1000, - }; - -+enum glamo_reg_basic_mmc { -+ /* set to disable CRC error rejection */ -+ GLAMO_BASIC_MMC_DISABLE_CRC = 0x0001, -+ /* enable completion interrupt */ -+ GLAMO_BASIC_MMC_EN_COMPL_INT = 0x0002, -+ /* stop MMC clock while enforced idle waiting for data from card */ -+ GLAMO_BASIC_MMC_NO_CLK_RD_WAIT = 0x0004, -+ /* 0 = 1-bit bus to card, 1 = use 4-bit bus (has to be negotiated) */ -+ GLAMO_BASIC_MMC_EN_4BIT_DATA = 0x0008, -+ /* enable 75K pullups on D3..D0 */ -+ GLAMO_BASIC_MMC_EN_DATA_PUPS = 0x0010, -+ /* enable 75K pullup on CMD */ -+ GLAMO_BASIC_MMC_EN_CMD_PUP = 0x0020, -+ /* IO drive strength 00=weak -> 11=strongest */ -+ GLAMO_BASIC_MMC_EN_DR_STR0 = 0x0040, -+ GLAMO_BASIC_MMC_EN_DR_STR1 = 0x0080, -+ /* TCLK delay stage A, 0000 = 500ps --> 1111 = 8ns */ -+ GLAMO_BASIC_MMC_EN_TCLK_DLYA0 = 0x0100, -+ GLAMO_BASIC_MMC_EN_TCLK_DLYA1 = 0x0200, -+ GLAMO_BASIC_MMC_EN_TCLK_DLYA2 = 0x0400, -+ GLAMO_BASIC_MMC_EN_TCLK_DLYA3 = 0x0800, -+ /* TCLK delay stage B (cumulative), 0000 = 500ps --> 1111 = 8ns */ -+ GLAMO_BASIC_MMC_EN_TCLK_DLYB0 = 0x1000, -+ GLAMO_BASIC_MMC_EN_TCLK_DLYB1 = 0x2000, -+ GLAMO_BASIC_MMC_EN_TCLK_DLYB2 = 0x4000, -+ GLAMO_BASIC_MMC_EN_TCLK_DLYB3 = 0x8000, -+}; -+ -+enum glamo_reg_stat1_mmc { -+ /* command "counter" (really: toggle) */ -+ GLAMO_STAT1_MMC_CMD_CTR = 0x8000, -+ /* engine is idle */ -+ GLAMO_STAT1_MMC_IDLE = 0x4000, -+ /* readback response is ready */ -+ GLAMO_STAT1_MMC_RB_RRDY = 0x0200, -+ /* readback data is ready */ -+ GLAMO_STAT1_MMC_RB_DRDY = 0x0100, -+ /* no response timeout */ -+ GLAMO_STAT1_MMC_RTOUT = 0x0020, -+ /* no data timeout */ -+ GLAMO_STAT1_MMC_DTOUT = 0x0010, -+ /* CRC error on block write */ -+ GLAMO_STAT1_MMC_BWERR = 0x0004, -+ /* CRC error on block read */ -+ GLAMO_STAT1_MMC_BRERR = 0x0002 -+}; -+ -+enum glamo_reg_fire_mmc { -+ /* command "counter" (really: toggle) -+ * the STAT1 register reflects this so you can ensure you don't look -+ * at status for previous command -+ */ -+ GLAMO_FIRE_MMC_CMD_CTR = 0x8000, -+ /* sets kind of response expected */ -+ GLAMO_FIRE_MMC_RES_MASK = 0x0700, -+ /* sets command type */ -+ GLAMO_FIRE_MMC_TYP_MASK = 0x00C0, -+ /* sets command class */ -+ GLAMO_FIRE_MMC_CLS_MASK = 0x000F, -+}; -+ -+enum glamo_fire_mmc_response_types { -+ GLAMO_FIRE_MMC_RSPT_R1 = 0x0000, -+ GLAMO_FIRE_MMC_RSPT_R1b = 0x0100, -+ GLAMO_FIRE_MMC_RSPT_R2 = 0x0200, -+ GLAMO_FIRE_MMC_RSPT_R3 = 0x0300, -+ GLAMO_FIRE_MMC_RSPT_R4 = 0x0400, -+ GLAMO_FIRE_MMC_RSPT_R5 = 0x0500, -+}; -+ -+enum glamo_fire_mmc_command_types { -+ /* broadcast, no response */ -+ GLAMO_FIRE_MMC_CMDT_BNR = 0x0000, -+ /* broadcast, with response */ -+ GLAMO_FIRE_MMC_CMDT_BR = 0x0040, -+ /* addressed, no data */ -+ GLAMO_FIRE_MMC_CMDT_AND = 0x0080, -+ /* addressed, with data */ -+ GLAMO_FIRE_MMC_CMDT_AD = 0x00C0, -+}; -+ -+enum glamo_fire_mmc_command_class { -+ /* "Stream Read" */ -+ GLAMO_FIRE_MMC_CC_STRR = 0x0000, -+ /* Single Block Read */ -+ GLAMO_FIRE_MMC_CC_SBR = 0x0001, -+ /* Multiple Block Read With Stop */ -+ GLAMO_FIRE_MMC_CC_MBRS = 0x0002, -+ /* Multiple Block Read No Stop */ -+ GLAMO_FIRE_MMC_CC_MBRNS = 0x0003, -+ /* RESERVED for "Stream Write" */ -+ GLAMO_FIRE_MMC_CC_STRW = 0x0004, -+ /* "Stream Write" */ -+ GLAMO_FIRE_MMC_CC_SBW = 0x0005, -+ /* RESERVED for Multiple Block Write With Stop */ -+ GLAMO_FIRE_MMC_CC_MBWS = 0x0006, -+ /* Multiple Block Write No Stop */ -+ GLAMO_FIRE_MMC_CC_MBWNS = 0x0007, -+ /* STOP command */ -+ GLAMO_FIRE_MMC_CC_STOP = 0x0008, -+ /* Cancel on Running Command */ -+ GLAMO_FIRE_MMC_CC_CANCL = 0x0009, -+ /* "Basic Command" */ -+ GLAMO_FIRE_MMC_CC_BASIC = 0x000a, -+}; -+ -+/* these are offsets from the start of the MMC register region */ -+enum glamo_register_mmc { -+ /* MMC command, b15..8 = cmd arg b7..0; b7..1 = CRC; b0 = end bit */ -+ GLAMO_REG_MMC_CMD_REG1 = 0x00, -+ /* MMC command, b15..0 = cmd arg b23 .. 8 */ -+ GLAMO_REG_MMC_CMD_REG2 = 0x02, -+ /* MMC command, b15=start, b14=transmission, -+ * b13..8=cmd idx, b7..0=cmd arg b31..24 -+ */ -+ GLAMO_REG_MMC_CMD_REG3 = 0x04, -+ GLAMO_REG_MMC_CMD_FIRE = 0x06, -+ GLAMO_REG_MMC_CMD_RSP1 = 0x10, -+ GLAMO_REG_MMC_CMD_RSP2 = 0x12, -+ GLAMO_REG_MMC_CMD_RSP3 = 0x14, -+ GLAMO_REG_MMC_CMD_RSP4 = 0x16, -+ GLAMO_REG_MMC_CMD_RSP5 = 0x18, -+ GLAMO_REG_MMC_CMD_RSP6 = 0x1a, -+ GLAMO_REG_MMC_CMD_RSP7 = 0x1c, -+ GLAMO_REG_MMC_CMD_RSP8 = 0x1e, -+ GLAMO_REG_MMC_RB_STAT1 = 0x20, -+ GLAMO_REG_MMC_RB_BLKCNT = 0x22, -+ GLAMO_REG_MMC_RB_BLKLEN = 0x24, -+ GLAMO_REG_MMC_BASIC = 0x30, -+ GLAMO_REG_MMC_RDATADS1 = 0x34, -+ GLAMO_REG_MMC_RDATADS2 = 0x36, -+ GLAMO_REG_MMC_WDATADS1 = 0x38, -+ GLAMO_REG_MMC_WDATADS2 = 0x3a, -+ GLAMO_REG_MMC_DATBLKCNT = 0x3c, -+ GLAMO_REG_MMC_DATBLKLEN = 0x3e, -+ GLAMO_REG_MMC_TIMEOUT = 0x40, -+ -+}; -+ - enum glamo_reg_clock_isp { - GLAMO_CLOCK_ISP_DG_I1CLK = 0x0001, - GLAMO_CLOCK_ISP_EN_I1CLK = 0x0002, --- -1.5.6.3 - |