* [PATCH 0/5] ARM: sunxi: Add driver for SD/MMC hosts found on allwinner sunxi SOCs @ 2013-12-14 21:58 Hans de Goede [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-14 21:58 UTC (permalink / raw) To: Chris Ball, Maxime Ripard Cc: David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi All, This patchset adds support for the SD/MMC hosts found on sun4i, sun5i and sun7i SOCs. It is based on the driver Allwinner ships in their Android kernel sources. Initial porting to upstream kernels done by David Lanzendörfer. I've spend a lot of time cleaning this up, so hopefuly it is ready to go upstream now, please review. Note David Lanzendörfer will maintain this driver in the future. I jumped into the process of creating this driver to iron out a few blocker bugs and ended up also doing a lot of cleanup as David was busy. David should have time to work on this again now, so if a v2 of the patch-set is needed, he will likely post it. Thanks & Regards, Hans -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out. ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-14 21:58 ` Hans de Goede [not found] ` <1387058295-20641-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-17 13:43 ` Mark Brown 2013-12-14 21:58 ` [PATCH 2/5] ARM: dts: sun4i: Add support for mmc Hans de Goede ` (3 subsequent siblings) 4 siblings, 2 replies; 31+ messages in thread From: Hans de Goede @ 2013-12-14 21:58 UTC (permalink / raw) To: Chris Ball, Maxime Ripard Cc: David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hans de Goede From: David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org> This is based on the driver Allwinner ships in there Android kernel sources. Initial porting to upstream kernels done by David Lanzendörfer, additional fixes and cleanups by Hans de Goede. Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> --- drivers/mmc/host/Kconfig | 8 + drivers/mmc/host/Makefile | 2 + drivers/mmc/host/sunxi-mci.c | 908 +++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/host/sunxi-mci.h | 246 ++++++++++++ include/linux/clk/sunxi.h | 22 ++ 5 files changed, 1186 insertions(+) create mode 100644 drivers/mmc/host/sunxi-mci.c create mode 100644 drivers/mmc/host/sunxi-mci.h create mode 100644 include/linux/clk/sunxi.h diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 7fc5099..69a7171 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI help Say Y here to include driver code to support SD/MMC card interface of Realtek PCI-E card reader + +config MMC_SUNXI + tristate "Allwinner sunxi SD/MMC Host Controller support" + depends on ARCH_SUNXI + default y + help + This selects support for the SD/MMC Host Controller on + Allwinner sunxi SoCs. diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index c41d0c3..f76f783 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -52,6 +52,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o +obj-$(CONFIG_MMC_SUNXI) += sunxi-mci.o + obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o diff --git a/drivers/mmc/host/sunxi-mci.c b/drivers/mmc/host/sunxi-mci.c new file mode 100644 index 0000000..e091ebb --- /dev/null +++ b/drivers/mmc/host/sunxi-mci.c @@ -0,0 +1,908 @@ +/* + * Driver for sunxi SD/MMC host controllers + * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. + * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh-jFKXxz0WcGyYHARAtoI1EgC/G2K4zDHf@public.gmane.org> + * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch> + * (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch> + * (C) Copyright 2013-2013 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/err.h> + +#include <linux/clk.h> +#include <linux/clk-private.h> +#include <linux/clk/sunxi.h> + +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/scatterlist.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/regulator/consumer.h> + +#include <linux/of_address.h> +#include <linux/of_gpio.h> +#include <linux/of_platform.h> + +#include <linux/mmc/host.h> +#include <linux/mmc/sd.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/core.h> +#include <linux/mmc/card.h> + +#include "sunxi-mci.h" + +static void sunxi_mmc_init_host(struct mmc_host *mmc) +{ + u32 rval; + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); + + /* reset controller */ + rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset; + mci_writel(smc_host, REG_GCTRL, rval); + + mci_writel(smc_host, REG_FTRGL, 0x20070008); + mci_writel(smc_host, REG_TMOUT, 0xffffffff); + mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask); + mci_writel(smc_host, REG_RINTR, 0xffffffff); + mci_writel(smc_host, REG_DBGC, 0xdeb); + mci_writel(smc_host, REG_FUNS, 0xceaa0000); + mci_writel(smc_host, REG_DLBA, smc_host->sg_dma); + rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb; + rval &= ~SDXC_AccessDoneDirect; + mci_writel(smc_host, REG_GCTRL, rval); +} + +static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host) +{ + mci_writel(smc_host, REG_GCTRL, SDXC_HWReset); +} + +/* /\* UHS-I Operation Modes */ +/* * DS 25MHz 12.5MB/s 3.3V */ +/* * HS 50MHz 25MB/s 3.3V */ +/* * SDR12 25MHz 12.5MB/s 1.8V */ +/* * SDR25 50MHz 25MB/s 1.8V */ +/* * SDR50 100MHz 50MB/s 1.8V */ +/* * SDR104 208MHz 104MB/s 1.8V */ +/* * DDR50 50MHz 50MB/s 1.8V */ +/* * MMC Operation Modes */ +/* * DS 26MHz 26MB/s 3/1.8/1.2V */ +/* * HS 52MHz 52MB/s 3/1.8/1.2V */ +/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */ +/* * HS200 200MHz 200MB/s 1.8/1.2V */ +/* * */ +/* * Spec. Timing */ +/* * SD3.0 */ +/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */ +/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */ +/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */ +/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */ +/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */ +/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */ +/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ + +/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */ +/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */ +/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */ +/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */ +/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */ + +/* * eMMC4.5 */ +/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */ +/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ +/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ +/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */ +/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ +/* *\/ */ + +static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, + struct mmc_data *data) +{ + struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; + struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma; + int i, max_len = (1 << host->idma_des_size_bits); + + for (i = 0; i < data->sg_len; i++) { + pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | + SDXC_IDMAC_DES0_DIC; + + if (data->sg[i].length == max_len) + pdes[i].buf_size = 0; /* 0 == max_len */ + else + pdes[i].buf_size = data->sg[i].length; + + pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); + pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1]; + } + pdes[0].config |= SDXC_IDMAC_DES0_FD; + pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD; + + wmb(); /* Ensure idma_des hit main mem before we start the idmac */ +} + +static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data) +{ + if (data->flags & MMC_DATA_WRITE) + return DMA_TO_DEVICE; + else + return DMA_FROM_DEVICE; +} + +static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host, + struct mmc_data *data) +{ + u32 dma_len; + u32 i; + u32 temp; + struct scatterlist *sg; + + dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len, + sunxi_mmc_get_dma_dir(data)); + if (dma_len == 0) { + dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n"); + return -ENOMEM; + } + + for_each_sg(data->sg, sg, data->sg_len, i) { + if (sg->offset & 3 || sg->length & 3) { + dev_err(mmc_dev(smc_host->mmc), + "unaligned scatterlist: os %x length %d\n", + sg->offset, sg->length); + return -EINVAL; + } + } + + sunxi_mmc_init_idma_des(smc_host, data); + + temp = mci_readl(smc_host, REG_GCTRL); + temp |= SDXC_DMAEnb; + mci_writel(smc_host, REG_GCTRL, temp); + temp |= SDXC_DMAReset; + mci_writel(smc_host, REG_GCTRL, temp); + + mci_writel(smc_host, REG_DMAC, SDXC_IDMACSoftRST); + + if (!(data->flags & MMC_DATA_WRITE)) + mci_writel(smc_host, REG_IDIE, SDXC_IDMACReceiveInt); + + mci_writel(smc_host, REG_DMAC, SDXC_IDMACFixBurst | SDXC_IDMACIDMAOn); + + return 0; +} + +static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, + struct mmc_request *req) +{ + u32 cmd_val = SDXC_Start | SDXC_RspExp | SDXC_StopAbortCMD + | SDXC_CheckRspCRC | MMC_STOP_TRANSMISSION; + u32 ri = 0; + unsigned long expire = jiffies + msecs_to_jiffies(1000); + + mci_writel(host, REG_CARG, 0); + mci_writel(host, REG_CMDR, cmd_val); + do { + ri = mci_readl(host, REG_RINTR); + } while (!(ri & (SDXC_CmdDone | SDXC_IntErrBit)) && + time_before(jiffies, expire)); + + if (ri & SDXC_IntErrBit) { + dev_err(mmc_dev(host->mmc), "send stop command failed\n"); + if (req->stop) + req->stop->resp[0] = -ETIMEDOUT; + } else { + if (req->stop) + req->stop->resp[0] = mci_readl(host, REG_RESP0); + } + + mci_writel(host, REG_RINTR, 0xffff); +} + +static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host) +{ + struct mmc_command *cmd = smc_host->mrq->cmd; + struct mmc_data *data = smc_host->mrq->data; + + /* For some cmds timeout is normal with sd/mmc cards */ + if ((smc_host->int_sum & SDXC_IntErrBit) == SDXC_RespTimeout && + (cmd->opcode == 5 || cmd->opcode == 52)) + return; + + dev_err(mmc_dev(smc_host->mmc), + "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", + smc_host->mmc->index, cmd->opcode, + data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", + smc_host->int_sum & SDXC_RespErr ? " RE" : "", + smc_host->int_sum & SDXC_RespCRCErr ? " RCE" : "", + smc_host->int_sum & SDXC_DataCRCErr ? " DCE" : "", + smc_host->int_sum & SDXC_RespTimeout ? " RTO" : "", + smc_host->int_sum & SDXC_DataTimeout ? " DTO" : "", + smc_host->int_sum & SDXC_FIFORunErr ? " FE" : "", + smc_host->int_sum & SDXC_HardWLocked ? " HL" : "", + smc_host->int_sum & SDXC_StartBitErr ? " SBE" : "", + smc_host->int_sum & SDXC_EndBitErr ? " EBE" : "" + ); +} + +static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) +{ + struct mmc_request *mrq; + unsigned long iflags; + + spin_lock_irqsave(&host->lock, iflags); + + mrq = host->mrq; + if (!mrq) { + spin_unlock_irqrestore(&host->lock, iflags); + dev_err(mmc_dev(host->mmc), "no request to finalize\n"); + return; + } + + if (host->int_sum & SDXC_IntErrBit) { + sunxi_mmc_dump_errinfo(host); + mrq->cmd->error = -ETIMEDOUT; + if (mrq->data) + mrq->data->error = -ETIMEDOUT; + if (mrq->stop) + mrq->stop->error = -ETIMEDOUT; + } else { + if (mrq->cmd->flags & MMC_RSP_136) { + mrq->cmd->resp[0] = mci_readl(host, REG_RESP3); + mrq->cmd->resp[1] = mci_readl(host, REG_RESP2); + mrq->cmd->resp[2] = mci_readl(host, REG_RESP1); + mrq->cmd->resp[3] = mci_readl(host, REG_RESP0); + } else { + mrq->cmd->resp[0] = mci_readl(host, REG_RESP0); + } + if (mrq->data) + mrq->data->bytes_xfered = + mrq->data->blocks * mrq->data->blksz; + } + + if (mrq->data) { + struct mmc_data *data = mrq->data; + u32 temp; + + mci_writel(host, REG_IDST, 0x337); + mci_writel(host, REG_DMAC, 0); + temp = mci_readl(host, REG_GCTRL); + mci_writel(host, REG_GCTRL, temp|SDXC_DMAReset); + temp &= ~SDXC_DMAEnb; + mci_writel(host, REG_GCTRL, temp); + temp |= SDXC_FIFOReset; + mci_writel(host, REG_GCTRL, temp); + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + sunxi_mmc_get_dma_dir(data)); + } + + mci_writel(host, REG_RINTR, 0xffff); + + dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n", + mrq->cmd->resp[0], mrq->cmd->resp[1], + mrq->cmd->resp[2], mrq->cmd->resp[3]); + + host->mrq = NULL; + host->int_sum = 0; + host->wait_dma = 0; + + spin_unlock_irqrestore(&host->lock, iflags); + + if (mrq->data && mrq->data->error) { + dev_err(mmc_dev(host->mmc), + "data error, sending stop command\n"); + sunxi_mmc_send_manual_stop(host, mrq); + } + + mmc_request_done(host->mmc, mrq); +} + +static s32 sunxi_mmc_get_ro(struct mmc_host *mmc) +{ + struct sunxi_mmc_host *host = mmc_priv(mmc); + + int read_only = 0; + + if (gpio_is_valid(host->wp_pin)) { + pinctrl_request_gpio(host->wp_pin); + read_only = gpio_get_value(host->wp_pin); + } + + return read_only; +} + +static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) +{ + struct sunxi_mmc_host *host = dev_id; + u32 finalize = 0; + u32 sdio_int = 0; + u32 msk_int; + u32 idma_int; + + spin_lock(&host->lock); + + idma_int = mci_readl(host, REG_IDST); + msk_int = mci_readl(host, REG_MISTA); + + dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", + host->mrq, msk_int, idma_int); + + if (host->mrq) { + if (idma_int & SDXC_IDMACReceiveInt) + host->wait_dma = 0; + + host->int_sum |= msk_int; + + /* Wait for CmdDone on RespTimeout before finishing the req */ + if ((host->int_sum & SDXC_RespTimeout) && + !(host->int_sum & SDXC_CmdDone)) + mci_writel(host, REG_IMASK, + host->sdio_imask | SDXC_CmdDone); + else if (host->int_sum & SDXC_IntErrBit) + finalize = 1; /* Don't wait for dma on error */ + else if (host->int_sum & SDXC_IntDoneBit && !host->wait_dma) + finalize = 1; /* Done */ + + if (finalize) { + mci_writel(host, REG_IMASK, host->sdio_imask); + mci_writel(host, REG_IDIE, 0); + } + } + + if (msk_int & SDXC_SDIOInt) + sdio_int = 1; + + mci_writel(host, REG_RINTR, msk_int); + mci_writel(host, REG_IDST, idma_int); + + spin_unlock(&host->lock); + + if (finalize) + tasklet_schedule(&host->tasklet); + + if (sdio_int) + mmc_signal_sdio_irq(host->mmc); + + return IRQ_HANDLED; +} + +static void sunxi_mmc_tasklet(unsigned long data) +{ + struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data; + sunxi_mmc_finalize_request(smc_host); +} + +static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) +{ + unsigned long expire = jiffies + msecs_to_jiffies(2000); + u32 rval; + + rval = mci_readl(host, REG_CLKCR); + rval &= ~(SDXC_CardClkOn | SDXC_LowPowerOn); + if (oclk_en) + rval |= SDXC_CardClkOn; + if (!host->io_flag) + rval |= SDXC_LowPowerOn; + mci_writel(host, REG_CLKCR, rval); + + rval = SDXC_Start | SDXC_UPCLKOnly | SDXC_WaitPreOver; + if (host->voltage_switching) + rval |= SDXC_VolSwitch; + mci_writel(host, REG_CMDR, rval); + do { + rval = mci_readl(host, REG_CMDR); + } while (time_before(jiffies, expire) && (rval & SDXC_Start)); + + if (rval & SDXC_Start) { + dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); + host->ferror = 1; + } +} + +static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host, + u32 oclk_dly, u32 sclk_dly) +{ + unsigned long iflags; + struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod); + + spin_lock_irqsave(&smc_host->lock, iflags); + clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly); + spin_unlock_irqrestore(&smc_host->lock, iflags); +} + +struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = { + { MMC_CLK_400K, 0, 7 }, + { MMC_CLK_25M, 0, 5 }, + { MMC_CLK_50M, 3, 5 }, + { MMC_CLK_50MDDR, 2, 4 }, + { MMC_CLK_50MDDR_8BIT, 2, 4 }, + { MMC_CLK_100M, 1, 4 }, + { MMC_CLK_200M, 1, 4 }, +}; + +static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host, + unsigned int rate) +{ + u32 newrate; + u32 src_clk; + u32 oclk_dly; + u32 sclk_dly; + u32 temp; + struct sunxi_mmc_clk_dly *dly = NULL; + + newrate = clk_round_rate(smc_host->clk_mod, rate); + if (smc_host->clk_mod_rate == newrate) { + dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n", + rate, newrate); + return; + } + + dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n", + rate, newrate); + + /* setting clock rate */ + clk_disable(smc_host->clk_mod); + clk_set_rate(smc_host->clk_mod, newrate); + clk_enable(smc_host->clk_mod); + smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod); + dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate); + + sunxi_mmc_oclk_onoff(smc_host, 0); + /* clear internal divider */ + temp = mci_readl(smc_host, REG_CLKCR); + temp &= ~0xff; + mci_writel(smc_host, REG_CLKCR, temp); + + /* determine delays */ + if (rate <= 400000) { + dly = &mmc_clk_dly[MMC_CLK_400K]; + } else if (rate <= 25000000) { + dly = &mmc_clk_dly[MMC_CLK_25M]; + } else if (rate <= 50000000) { + if (smc_host->ddr) { + if (smc_host->bus_width == 8) + dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT]; + else + dly = &mmc_clk_dly[MMC_CLK_50MDDR]; + } else { + dly = &mmc_clk_dly[MMC_CLK_50M]; + } + } else if (rate <= 104000000) { + dly = &mmc_clk_dly[MMC_CLK_100M]; + } else if (rate <= 208000000) { + dly = &mmc_clk_dly[MMC_CLK_200M]; + } else + dly = &mmc_clk_dly[MMC_CLK_50M]; + + oclk_dly = dly->oclk_dly; + sclk_dly = dly->sclk_dly; + + src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod)); + if (src_clk >= 300000000 && src_clk <= 400000000) { + if (oclk_dly) + oclk_dly--; + if (sclk_dly) + sclk_dly--; + } + + sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly); + sunxi_mmc_oclk_onoff(smc_host, 1); + + /* oclk_onoff sets various irq status bits, clear these */ + mci_writel(smc_host, REG_RINTR, + mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIOInt); +} + +static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sunxi_mmc_host *host = mmc_priv(mmc); + u32 temp; + s32 err; + + /* Set the power state */ + switch (ios->power_mode) { + case MMC_POWER_ON: + break; + + case MMC_POWER_UP: + if (!IS_ERR(host->vmmc)) { + mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd); + udelay(200); + } + + err = clk_prepare_enable(host->clk_ahb); + if (err) { + dev_err(mmc_dev(host->mmc), "AHB clk err %d\n", err); + host->ferror = 1; + return; + } + err = clk_prepare_enable(host->clk_mod); + if (err) { + dev_err(mmc_dev(host->mmc), "MOD clk err %d\n", err); + host->ferror = 1; + return; + } + + sunxi_mmc_init_host(mmc); + enable_irq(host->irq); + + dev_dbg(mmc_dev(host->mmc), "power on!\n"); + host->ferror = 0; + break; + + case MMC_POWER_OFF: + dev_dbg(mmc_dev(host->mmc), "power off!\n"); + disable_irq(host->irq); + sunxi_mmc_exit_host(host); + clk_disable_unprepare(host->clk_ahb); + clk_disable_unprepare(host->clk_mod); + if (!IS_ERR(host->vmmc)) + mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); + host->ferror = 0; + break; + } + + /* set bus width */ + switch (ios->bus_width) { + case MMC_BUS_WIDTH_1: + mci_writel(host, REG_WIDTH, SDXC_WIDTH1); + host->bus_width = 1; + break; + case MMC_BUS_WIDTH_4: + mci_writel(host, REG_WIDTH, SDXC_WIDTH4); + host->bus_width = 4; + break; + case MMC_BUS_WIDTH_8: + mci_writel(host, REG_WIDTH, SDXC_WIDTH8); + host->bus_width = 8; + break; + } + + /* set ddr mode */ + temp = mci_readl(host, REG_GCTRL); + if (ios->timing == MMC_TIMING_UHS_DDR50) { + temp |= SDXC_DDR_MODE; + host->ddr = 1; + } else { + temp &= ~SDXC_DDR_MODE; + host->ddr = 0; + } + mci_writel(host, REG_GCTRL, temp); + + /* set up clock */ + if (ios->clock && ios->power_mode) { + dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock); + sunxi_mmc_clk_set_rate(host, ios->clock); + usleep_range(50000, 55000); + } +} + +static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); + unsigned long flags; + u32 imask; + + spin_lock_irqsave(&smc_host->lock, flags); + imask = mci_readl(smc_host, REG_IMASK); + if (enable) { + smc_host->sdio_imask = SDXC_SDIOInt; + imask |= SDXC_SDIOInt; + } else { + smc_host->sdio_imask = 0; + imask &= ~SDXC_SDIOInt; + } + mci_writel(smc_host, REG_IMASK, imask); + spin_unlock_irqrestore(&smc_host->lock, flags); +} + +static void sunxi_mmc_hw_reset(struct mmc_host *mmc) +{ + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); + mci_writel(smc_host, REG_HWRST, 0); + udelay(10); + mci_writel(smc_host, REG_HWRST, 1); + udelay(300); +} + +static int sunxi_mmc_card_present(struct mmc_host *mmc) +{ + struct sunxi_mmc_host *host = mmc_priv(mmc); + + switch (host->cd_mode) { + case CARD_DETECT_BY_GPIO_POLL: + return !gpio_get_value(host->cd_pin); /* Signal inverted */ + case CARD_ALWAYS_PRESENT: + return 1; + } + return 0; /* Never reached */ +} + +static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct sunxi_mmc_host *host = mmc_priv(mmc); + struct mmc_command *cmd = mrq->cmd; + struct mmc_data *data = mrq->data; + unsigned long iflags; + u32 imask = SDXC_IntErrBit; + u32 cmd_val = SDXC_Start | (cmd->opcode & 0x3f); + u32 byte_cnt = 0; + int ret; + + if (!sunxi_mmc_card_present(mmc) || host->ferror) { + dev_dbg(mmc_dev(host->mmc), "no medium present\n"); + mrq->cmd->error = -ENOMEDIUM; + mmc_request_done(mmc, mrq); + return; + } + + if (data) { + byte_cnt = data->blksz * data->blocks; + mci_writel(host, REG_BLKSZ, data->blksz); + mci_writel(host, REG_BCNTR, byte_cnt); + ret = sunxi_mmc_prepare_dma(host, data); + if (ret < 0) { + dev_err(mmc_dev(host->mmc), "prepare DMA failed\n"); + cmd->error = ret; + cmd->data->error = ret; + mmc_request_done(host->mmc, mrq); + return; + } + } + + if (cmd->opcode == MMC_GO_IDLE_STATE) { + cmd_val |= SDXC_SendInitSeq; + imask |= SDXC_CmdDone; + } + + if (cmd->opcode == SD_SWITCH_VOLTAGE) { + cmd_val |= SDXC_VolSwitch; + imask |= SDXC_VolChgDone; + host->voltage_switching = 1; + sunxi_mmc_oclk_onoff(host, 1); + } + + if (cmd->flags & MMC_RSP_PRESENT) { + cmd_val |= SDXC_RspExp; + if (cmd->flags & MMC_RSP_136) + cmd_val |= SDXC_LongRsp; + if (cmd->flags & MMC_RSP_CRC) + cmd_val |= SDXC_CheckRspCRC; + + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) { + cmd_val |= SDXC_DataExp | SDXC_WaitPreOver; + if (cmd->data->flags & MMC_DATA_STREAM) { + imask |= SDXC_AutoCMDDone; + cmd_val |= SDXC_Seqmod | SDXC_SendAutoStop; + } + if (cmd->data->stop) { + imask |= SDXC_AutoCMDDone; + cmd_val |= SDXC_SendAutoStop; + } else + imask |= SDXC_DataOver; + + if (cmd->data->flags & MMC_DATA_WRITE) + cmd_val |= SDXC_Write; + else + host->wait_dma = 1; + } else + imask |= SDXC_CmdDone; + } else + imask |= SDXC_CmdDone; + + dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n", + cmd_val & 0x3f, cmd_val, cmd->arg, imask, + mrq->data ? mrq->data->blksz * mrq->data->blocks : 0); + + spin_lock_irqsave(&host->lock, iflags); + host->mrq = mrq; + mci_writel(host, REG_IMASK, host->sdio_imask | imask); + spin_unlock_irqrestore(&host->lock, iflags); + + mci_writel(host, REG_CARG, cmd->arg); + mci_writel(host, REG_CMDR, cmd_val); +} + +static const struct of_device_id sunxi_mmc_of_match[] = { + { .compatible = "allwinner,sun4i-mmc", }, + { .compatible = "allwinner,sun5i-mmc", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); + +static struct mmc_host_ops sunxi_mmc_ops = { + .request = sunxi_mmc_request, + .set_ios = sunxi_mmc_set_ios, + .get_ro = sunxi_mmc_get_ro, + .get_cd = sunxi_mmc_card_present, + .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, + .hw_reset = sunxi_mmc_hw_reset, +}; + +static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + int ret; + + if (of_device_is_compatible(np, "allwinner,sun4i-mmc")) + host->idma_des_size_bits = 13; + else + host->idma_des_size_bits = 16; + + host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc"); + if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + host->reg_base = devm_ioremap_resource(&pdev->dev, + platform_get_resource(pdev, IORESOURCE_MEM, 0)); + if (IS_ERR(host->reg_base)) + return PTR_ERR(host->reg_base); + + host->irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0, + "sunxi-mci", host); + if (ret) + return ret; + disable_irq(host->irq); + + host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(host->clk_ahb)) { + dev_err(&pdev->dev, "Could not get ahb clock\n"); + return PTR_ERR(host->clk_ahb); + } + + host->clk_mod = devm_clk_get(&pdev->dev, "mod"); + if (IS_ERR(host->clk_mod)) { + dev_err(&pdev->dev, "Could not get mod clock\n"); + return PTR_ERR(host->clk_mod); + } + + of_property_read_u32(np, "bus-width", &host->bus_width); + if (host->bus_width != 1 && host->bus_width != 4) { + dev_err(&pdev->dev, "Invalid bus-width %d\n", host->bus_width); + return -EINVAL; + } + + of_property_read_u32(np, "cd-mode", &host->cd_mode); + switch (host->cd_mode) { + case CARD_DETECT_BY_GPIO_POLL: + host->cd_pin = of_get_named_gpio(np, "cd-gpios", 0); + if (!gpio_is_valid(host->cd_pin)) { + dev_err(&pdev->dev, "Invalid cd-gpios\n"); + return -EINVAL; + } + ret = devm_gpio_request(&pdev->dev, host->cd_pin, "mmc_cd"); + if (ret) { + dev_err(&pdev->dev, "Could not get cd-gpios\n"); + return ret; + } + gpio_direction_input(host->cd_pin); + break; + case CARD_ALWAYS_PRESENT: + break; + default: + dev_err(&pdev->dev, "Invalid cd-mode %d\n", host->cd_mode); + return -EINVAL; + } + + host->wp_pin = of_get_named_gpio(np, "wp-gpios", 0); + if (gpio_is_valid(host->wp_pin)) { + ret = devm_gpio_request(&pdev->dev, host->wp_pin, "mmc_wp"); + if (ret) { + dev_err(&pdev->dev, "Could not get wp-gpios\n"); + return ret; + } + gpio_direction_input(host->wp_pin); + } + + return 0; +} + +static int sunxi_mmc_probe(struct platform_device *pdev) +{ + struct sunxi_mmc_host *host; + struct mmc_host *mmc; + int ret; + + mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); + if (!mmc) { + dev_err(&pdev->dev, "mmc alloc host failed\n"); + return -ENOMEM; + } + + host = mmc_priv(mmc); + host->mmc = mmc; + spin_lock_init(&host->lock); + tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host); + + ret = sunxi_mmc_resource_request(host, pdev); + if (ret) + goto error_free_host; + + host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, + &host->sg_dma, GFP_KERNEL); + if (!host->sg_cpu) { + dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n"); + ret = -ENOMEM; + goto error_free_host; + } + + mmc->ops = &sunxi_mmc_ops; + mmc->max_blk_count = 8192; + mmc->max_blk_size = 4096; + mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); + mmc->max_seg_size = (1 << host->idma_des_size_bits); + mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; + /* 400kHz ~ 50MHz */ + mmc->f_min = 400000; + mmc->f_max = 50000000; + /* available voltages */ + if (!IS_ERR(host->vmmc)) + mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc); + else + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | + MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | + MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL | + MMC_CAP_DRIVER_TYPE_A; + if (host->bus_width == 4) + mmc->caps |= MMC_CAP_4_BIT_DATA; + mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP; + + ret = mmc_add_host(mmc); + if (ret) + goto error_free_dma; + + dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); + platform_set_drvdata(pdev, mmc); + return 0; + +error_free_dma: + dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); +error_free_host: + mmc_free_host(mmc); + return ret; +} + +static int sunxi_mmc_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct sunxi_mmc_host *host = mmc_priv(mmc); + + mmc_remove_host(mmc); + sunxi_mmc_exit_host(host); + tasklet_disable(&host->tasklet); + dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); + mmc_free_host(mmc); + + return 0; +} + +static struct platform_driver sunxi_mmc_driver = { + .driver = { + .name = "sunxi-mci", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sunxi_mmc_of_match), + }, + .probe = sunxi_mmc_probe, + .remove = sunxi_mmc_remove, +}; +module_platform_driver(sunxi_mmc_driver); + +MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org>"); +MODULE_ALIAS("platform:sunxi-mmc"); diff --git a/drivers/mmc/host/sunxi-mci.h b/drivers/mmc/host/sunxi-mci.h new file mode 100644 index 0000000..332d3ae --- /dev/null +++ b/drivers/mmc/host/sunxi-mci.h @@ -0,0 +1,246 @@ +/* + * Driver for sunxi SD/MMC host controllers + * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. + * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh-jFKXxz0WcGyYHARAtoI1EgC/G2K4zDHf@public.gmane.org> + * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch> + * (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch> + * (C) Copyright 2013-2013 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#ifndef __SUNXI_MCI_H__ +#define __SUNXI_MCI_H__ + +/* register offset define */ +#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */ +#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */ +#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */ +#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */ +#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */ +#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */ +#define SDXC_REG_CMDR (0x18) /* SMC Command Register */ +#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */ +#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */ +#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */ +#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */ +#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */ +#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */ +#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ +#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ +#define SDXC_REG_STAS (0x3C) /* SMC Status Register */ +#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ +#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ +#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ +#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ +#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ +#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ +#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ +#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ +#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ +#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ +#define SDXC_REG_CHDA (0x90) +#define SDXC_REG_CBDA (0x94) + +#define mci_readl(host, reg) \ + __raw_readl((host)->reg_base + SDXC_##reg) +#define mci_writel(host, reg, value) \ + __raw_writel((value), (host)->reg_base + SDXC_##reg) + +/* global control register bits */ +#define SDXC_SoftReset BIT(0) +#define SDXC_FIFOReset BIT(1) +#define SDXC_DMAReset BIT(2) +#define SDXC_HWReset (SDXC_SoftReset|SDXC_FIFOReset|SDXC_DMAReset) +#define SDXC_INTEnb BIT(4) +#define SDXC_DMAEnb BIT(5) +#define SDXC_DebounceEnb BIT(8) +#define SDXC_PosedgeLatchData BIT(9) +#define SDXC_DDR_MODE BIT(10) +#define SDXC_MemAccessDone BIT(29) +#define SDXC_AccessDoneDirect BIT(30) +#define SDXC_ACCESS_BY_AHB BIT(31) +#define SDXC_ACCESS_BY_DMA (0U << 31) +/* clock control bits */ +#define SDXC_CardClkOn BIT(16) +#define SDXC_LowPowerOn BIT(17) +/* bus width */ +#define SDXC_WIDTH1 (0) +#define SDXC_WIDTH4 (1) +#define SDXC_WIDTH8 (2) +/* smc command bits */ +#define SDXC_RspExp BIT(6) +#define SDXC_LongRsp BIT(7) +#define SDXC_CheckRspCRC BIT(8) +#define SDXC_DataExp BIT(9) +#define SDXC_Write BIT(10) +#define SDXC_Seqmod BIT(11) +#define SDXC_SendAutoStop BIT(12) +#define SDXC_WaitPreOver BIT(13) +#define SDXC_StopAbortCMD BIT(14) +#define SDXC_SendInitSeq BIT(15) +#define SDXC_UPCLKOnly BIT(21) +#define SDXC_RdCEATADev BIT(22) +#define SDXC_CCSExp BIT(23) +#define SDXC_EnbBoot BIT(24) +#define SDXC_AltBootOpt BIT(25) +#define SDXC_BootACKExp BIT(26) +#define SDXC_BootAbort BIT(27) +#define SDXC_VolSwitch BIT(28) +#define SDXC_UseHoldReg BIT(29) +#define SDXC_Start BIT(31) +/* interrupt bits */ +#define SDXC_RespErr BIT(1) +#define SDXC_CmdDone BIT(2) +#define SDXC_DataOver BIT(3) +#define SDXC_TxDataReq BIT(4) +#define SDXC_RxDataReq BIT(5) +#define SDXC_RespCRCErr BIT(6) +#define SDXC_DataCRCErr BIT(7) +#define SDXC_RespTimeout BIT(8) +#define SDXC_DataTimeout BIT(9) +#define SDXC_VolChgDone BIT(10) +#define SDXC_FIFORunErr BIT(11) +#define SDXC_HardWLocked BIT(12) +#define SDXC_StartBitErr BIT(13) +#define SDXC_AutoCMDDone BIT(14) +#define SDXC_EndBitErr BIT(15) +#define SDXC_SDIOInt BIT(16) +#define SDXC_CardInsert BIT(30) +#define SDXC_CardRemove BIT(31) +#define SDXC_IntErrBit (SDXC_RespErr | SDXC_RespCRCErr | \ + SDXC_DataCRCErr | SDXC_RespTimeout | \ + SDXC_DataTimeout | SDXC_FIFORunErr | \ + SDXC_HardWLocked | SDXC_StartBitErr | \ + SDXC_EndBitErr) /* 0xbbc2 */ +#define SDXC_IntDoneBit (SDXC_AutoCMDDone | SDXC_DataOver | \ + SDXC_CmdDone | SDXC_VolChgDone) +/* status */ +#define SDXC_RXWLFlag BIT(0) +#define SDXC_TXWLFlag BIT(1) +#define SDXC_FIFOEmpty BIT(2) +#define SDXC_FIFOFull BIT(3) +#define SDXC_CardPresent BIT(8) +#define SDXC_CardDataBusy BIT(9) +#define SDXC_DataFSMBusy BIT(10) +#define SDXC_DMAReq BIT(31) +#define SDXC_FIFO_SIZE (16) +/* Function select */ +#define SDXC_CEATAOn (0xceaaU << 16) +#define SDXC_SendIrqRsp BIT(0) +#define SDXC_SDIORdWait BIT(1) +#define SDXC_AbtRdData BIT(2) +#define SDXC_SendCCSD BIT(8) +#define SDXC_SendAutoStopCCSD BIT(9) +#define SDXC_CEATADevIntEnb BIT(10) +/* IDMA controller bus mod bit field */ +#define SDXC_IDMACSoftRST BIT(0) +#define SDXC_IDMACFixBurst BIT(1) +#define SDXC_IDMACIDMAOn BIT(7) +#define SDXC_IDMACRefetchDES BIT(31) +/* IDMA status bit field */ +#define SDXC_IDMACTransmitInt BIT(0) +#define SDXC_IDMACReceiveInt BIT(1) +#define SDXC_IDMACFatalBusErr BIT(2) +#define SDXC_IDMACDesInvalid BIT(4) +#define SDXC_IDMACCardErrSum BIT(5) +#define SDXC_IDMACNormalIntSum BIT(8) +#define SDXC_IDMACAbnormalIntSum BIT(9) +#define SDXC_IDMACHostAbtInTx BIT(10) +#define SDXC_IDMACHostAbtInRx BIT(10) +#define SDXC_IDMACIdle (0U << 13) +#define SDXC_IDMACSuspend (1U << 13) +#define SDXC_IDMACDESCRd (2U << 13) +#define SDXC_IDMACDESCCheck (3U << 13) +#define SDXC_IDMACRdReqWait (4U << 13) +#define SDXC_IDMACWrReqWait (5U << 13) +#define SDXC_IDMACRd (6U << 13) +#define SDXC_IDMACWr (7U << 13) +#define SDXC_IDMACDESCClose (8U << 13) + +struct sunxi_idma_des { + u32 config; +#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */ +#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */ +#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */ +#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */ +#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */ +#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ +#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ + + /* + * If the idma-des-size-bits of property is ie 13, bufsize bits are: + * Bits 0-12: buf1 size + * Bits 13-25: buf2 size + * Bits 26-31: not used + * Since we only ever set buf1 size, we can simply store it directly. + */ + u32 buf_size; + u32 buf_addr_ptr1; + u32 buf_addr_ptr2; +}; + +struct sunxi_mmc_host { + struct mmc_host *mmc; + struct regulator *vmmc; + + /* IO mapping base */ + void __iomem *reg_base; + + spinlock_t lock; + struct tasklet_struct tasklet; + + /* clock management */ + struct clk *clk_ahb; + struct clk *clk_mod; + + /* indicator pins */ + int wp_pin; + int cd_pin; + int cd_mode; +#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */ +#define CARD_ALWAYS_PRESENT (2) /* mmc always present */ + + /* ios information */ + u32 clk_mod_rate; + u32 bus_width; + u32 idma_des_size_bits; + u32 ddr; + u32 voltage_switching; + + /* irq */ + int irq; + u32 int_sum; + u32 sdio_imask; + + /* flags */ + u32 power_on:1; + u32 io_flag:1; + u32 wait_dma:1; + + dma_addr_t sg_dma; + void *sg_cpu; + + struct mmc_request *mrq; + u32 ferror; +}; + +#define MMC_CLK_400K 0 +#define MMC_CLK_25M 1 +#define MMC_CLK_50M 2 +#define MMC_CLK_50MDDR 3 +#define MMC_CLK_50MDDR_8BIT 4 +#define MMC_CLK_100M 5 +#define MMC_CLK_200M 6 +#define MMC_CLK_MOD_NUM 7 + +struct sunxi_mmc_clk_dly { + u32 mode; + u32 oclk_dly; + u32 sclk_dly; +}; + +#endif diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h new file mode 100644 index 0000000..1ef5c89 --- /dev/null +++ b/include/linux/clk/sunxi.h @@ -0,0 +1,22 @@ +/* + * Copyright 2013 - Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LINUX_CLK_SUNXI_H_ +#define __LINUX_CLK_SUNXI_H_ + +#include <linux/clk.h> + +void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); + +#endif -- 1.8.4.2 -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out. ^ permalink raw reply related [flat|nested] 31+ messages in thread
[parent not found: <1387058295-20641-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <1387058295-20641-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-15 13:44 ` Maxime Ripard 2013-12-15 14:20 ` Hans de Goede ` (2 more replies) 0 siblings, 3 replies; 31+ messages in thread From: Maxime Ripard @ 2013-12-15 13:44 UTC (permalink / raw) To: Hans de Goede Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 43138 bytes --] Hi Hans, I won't comment on the MMC driver itself, and leave Chris comment on that, but still, I have a few things. On Sat, Dec 14, 2013 at 10:58:11PM +0100, Hans de Goede wrote: > From: David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org> > > This is based on the driver Allwinner ships in there Android kernel sources. > > Initial porting to upstream kernels done by David Lanzendörfer, additional > fixes and cleanups by Hans de Goede. > > Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> Your commit log is a bit sparse. What capabilities this controller has? Is it using DMA? If so, how? What SoCs are supported/it has been tested on? etc. Also, you probably needs David's SoB here. > --- > drivers/mmc/host/Kconfig | 8 + > drivers/mmc/host/Makefile | 2 + > drivers/mmc/host/sunxi-mci.c | 908 +++++++++++++++++++++++++++++++++++++++++++ > drivers/mmc/host/sunxi-mci.h | 246 ++++++++++++ > include/linux/clk/sunxi.h | 22 ++ Please add your dt bindings documentation in Documentation/devicetree/bindings > 5 files changed, 1186 insertions(+) > create mode 100644 drivers/mmc/host/sunxi-mci.c > create mode 100644 drivers/mmc/host/sunxi-mci.h > create mode 100644 include/linux/clk/sunxi.h > > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig > index 7fc5099..69a7171 100644 > --- a/drivers/mmc/host/Kconfig > +++ b/drivers/mmc/host/Kconfig > @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI > help > Say Y here to include driver code to support SD/MMC card interface > of Realtek PCI-E card reader > + > +config MMC_SUNXI > + tristate "Allwinner sunxi SD/MMC Host Controller support" > + depends on ARCH_SUNXI > + default y I'm not that fond of these "default y" patterns. It forces the driver down to every user of the multiplatform kernels. I'd suggest removing the default and adding the driver to the defconfigs we have. > + help > + This selects support for the SD/MMC Host Controller on > + Allwinner sunxi SoCs. > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile > index c41d0c3..f76f783 100644 > --- a/drivers/mmc/host/Makefile > +++ b/drivers/mmc/host/Makefile > @@ -52,6 +52,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o > > obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o > > +obj-$(CONFIG_MMC_SUNXI) += sunxi-mci.o > + > obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o > obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o > obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o > diff --git a/drivers/mmc/host/sunxi-mci.c b/drivers/mmc/host/sunxi-mci.c > new file mode 100644 > index 0000000..e091ebb > --- /dev/null > +++ b/drivers/mmc/host/sunxi-mci.c > @@ -0,0 +1,908 @@ > +/* > + * Driver for sunxi SD/MMC host controllers > + * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. > + * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh-jFKXxz0WcGyYHARAtoI1EgC/G2K4zDHf@public.gmane.org> > + * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch> > + * (C) Copyright 2013-2013 David Lanzend?rfer <david.lanzendoerfer@o2s.ch> > + * (C) Copyright 2013-2013 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/io.h> > +#include <linux/device.h> > +#include <linux/interrupt.h> > +#include <linux/delay.h> > +#include <linux/err.h> > + > +#include <linux/clk.h> > +#include <linux/clk-private.h> > +#include <linux/clk/sunxi.h> > + > +#include <linux/gpio.h> > +#include <linux/platform_device.h> > +#include <linux/spinlock.h> > +#include <linux/scatterlist.h> > +#include <linux/dma-mapping.h> > +#include <linux/slab.h> > +#include <linux/regulator/consumer.h> > + > +#include <linux/of_address.h> > +#include <linux/of_gpio.h> > +#include <linux/of_platform.h> > + > +#include <linux/mmc/host.h> > +#include <linux/mmc/sd.h> > +#include <linux/mmc/mmc.h> > +#include <linux/mmc/core.h> > +#include <linux/mmc/card.h> > + > +#include "sunxi-mci.h" > + > +static void sunxi_mmc_init_host(struct mmc_host *mmc) > +{ > + u32 rval; > + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); > + > + /* reset controller */ > + rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset; > + mci_writel(smc_host, REG_GCTRL, rval); > + > + mci_writel(smc_host, REG_FTRGL, 0x20070008); > + mci_writel(smc_host, REG_TMOUT, 0xffffffff); > + mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask); > + mci_writel(smc_host, REG_RINTR, 0xffffffff); > + mci_writel(smc_host, REG_DBGC, 0xdeb); > + mci_writel(smc_host, REG_FUNS, 0xceaa0000); > + mci_writel(smc_host, REG_DLBA, smc_host->sg_dma); I suppose we have no idea what these magics are all about ? :( > + rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb; > + rval &= ~SDXC_AccessDoneDirect; > + mci_writel(smc_host, REG_GCTRL, rval); > +} > + > +static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host) > +{ > + mci_writel(smc_host, REG_GCTRL, SDXC_HWReset); > +} > + > +/* /\* UHS-I Operation Modes */ > +/* * DS 25MHz 12.5MB/s 3.3V */ > +/* * HS 50MHz 25MB/s 3.3V */ > +/* * SDR12 25MHz 12.5MB/s 1.8V */ > +/* * SDR25 50MHz 25MB/s 1.8V */ > +/* * SDR50 100MHz 50MB/s 1.8V */ > +/* * SDR104 208MHz 104MB/s 1.8V */ > +/* * DDR50 50MHz 50MB/s 1.8V */ > +/* * MMC Operation Modes */ > +/* * DS 26MHz 26MB/s 3/1.8/1.2V */ > +/* * HS 52MHz 52MB/s 3/1.8/1.2V */ > +/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */ > +/* * HS200 200MHz 200MB/s 1.8/1.2V */ > +/* * */ > +/* * Spec. Timing */ > +/* * SD3.0 */ > +/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */ > +/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */ > +/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */ > +/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */ > +/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */ > +/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */ > +/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ > + > +/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */ > +/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */ > +/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */ > +/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */ > +/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */ > + > +/* * eMMC4.5 */ > +/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */ > +/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ > +/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ > +/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */ > +/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ > +/* *\/ */ > + > +static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, > + struct mmc_data *data) > +{ > + struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; > + struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma; > + int i, max_len = (1 << host->idma_des_size_bits); > + > + for (i = 0; i < data->sg_len; i++) { > + pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | > + SDXC_IDMAC_DES0_DIC; > + > + if (data->sg[i].length == max_len) > + pdes[i].buf_size = 0; /* 0 == max_len */ > + else > + pdes[i].buf_size = data->sg[i].length; > + > + pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); > + pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1]; > + } Please add a newline. > + pdes[0].config |= SDXC_IDMAC_DES0_FD; > + pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD; > + > + wmb(); /* Ensure idma_des hit main mem before we start the idmac */ > +} > + > +static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data) > +{ > + if (data->flags & MMC_DATA_WRITE) > + return DMA_TO_DEVICE; > + else > + return DMA_FROM_DEVICE; > +} > + > +static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host, > + struct mmc_data *data) > +{ > + u32 dma_len; > + u32 i; > + u32 temp; > + struct scatterlist *sg; > + > + dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len, > + sunxi_mmc_get_dma_dir(data)); > + if (dma_len == 0) { > + dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n"); > + return -ENOMEM; > + } > + > + for_each_sg(data->sg, sg, data->sg_len, i) { > + if (sg->offset & 3 || sg->length & 3) { > + dev_err(mmc_dev(smc_host->mmc), > + "unaligned scatterlist: os %x length %d\n", > + sg->offset, sg->length); > + return -EINVAL; > + } > + } > + > + sunxi_mmc_init_idma_des(smc_host, data); > + > + temp = mci_readl(smc_host, REG_GCTRL); > + temp |= SDXC_DMAEnb; > + mci_writel(smc_host, REG_GCTRL, temp); > + temp |= SDXC_DMAReset; > + mci_writel(smc_host, REG_GCTRL, temp); > + > + mci_writel(smc_host, REG_DMAC, SDXC_IDMACSoftRST); > + > + if (!(data->flags & MMC_DATA_WRITE)) > + mci_writel(smc_host, REG_IDIE, SDXC_IDMACReceiveInt); > + > + mci_writel(smc_host, REG_DMAC, SDXC_IDMACFixBurst | SDXC_IDMACIDMAOn); > + > + return 0; > +} > + > +static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, > + struct mmc_request *req) > +{ > + u32 cmd_val = SDXC_Start | SDXC_RspExp | SDXC_StopAbortCMD > + | SDXC_CheckRspCRC | MMC_STOP_TRANSMISSION; > + u32 ri = 0; > + unsigned long expire = jiffies + msecs_to_jiffies(1000); > + > + mci_writel(host, REG_CARG, 0); > + mci_writel(host, REG_CMDR, cmd_val); Please add a newline. > + do { > + ri = mci_readl(host, REG_RINTR); > + } while (!(ri & (SDXC_CmdDone | SDXC_IntErrBit)) && > + time_before(jiffies, expire)); > + > + if (ri & SDXC_IntErrBit) { > + dev_err(mmc_dev(host->mmc), "send stop command failed\n"); > + if (req->stop) > + req->stop->resp[0] = -ETIMEDOUT; > + } else { > + if (req->stop) > + req->stop->resp[0] = mci_readl(host, REG_RESP0); > + } > + > + mci_writel(host, REG_RINTR, 0xffff); > +} > + > +static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host) > +{ > + struct mmc_command *cmd = smc_host->mrq->cmd; > + struct mmc_data *data = smc_host->mrq->data; > + > + /* For some cmds timeout is normal with sd/mmc cards */ > + if ((smc_host->int_sum & SDXC_IntErrBit) == SDXC_RespTimeout && > + (cmd->opcode == 5 || cmd->opcode == 52)) > + return; > + > + dev_err(mmc_dev(smc_host->mmc), > + "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", > + smc_host->mmc->index, cmd->opcode, > + data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", > + smc_host->int_sum & SDXC_RespErr ? " RE" : "", > + smc_host->int_sum & SDXC_RespCRCErr ? " RCE" : "", > + smc_host->int_sum & SDXC_DataCRCErr ? " DCE" : "", > + smc_host->int_sum & SDXC_RespTimeout ? " RTO" : "", > + smc_host->int_sum & SDXC_DataTimeout ? " DTO" : "", > + smc_host->int_sum & SDXC_FIFORunErr ? " FE" : "", > + smc_host->int_sum & SDXC_HardWLocked ? " HL" : "", > + smc_host->int_sum & SDXC_StartBitErr ? " SBE" : "", > + smc_host->int_sum & SDXC_EndBitErr ? " EBE" : "" > + ); > +} > + > +static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) > +{ > + struct mmc_request *mrq; > + unsigned long iflags; > + > + spin_lock_irqsave(&host->lock, iflags); > + > + mrq = host->mrq; > + if (!mrq) { > + spin_unlock_irqrestore(&host->lock, iflags); > + dev_err(mmc_dev(host->mmc), "no request to finalize\n"); > + return; > + } > + > + if (host->int_sum & SDXC_IntErrBit) { > + sunxi_mmc_dump_errinfo(host); > + mrq->cmd->error = -ETIMEDOUT; > + if (mrq->data) > + mrq->data->error = -ETIMEDOUT; > + if (mrq->stop) > + mrq->stop->error = -ETIMEDOUT; > + } else { > + if (mrq->cmd->flags & MMC_RSP_136) { > + mrq->cmd->resp[0] = mci_readl(host, REG_RESP3); > + mrq->cmd->resp[1] = mci_readl(host, REG_RESP2); > + mrq->cmd->resp[2] = mci_readl(host, REG_RESP1); > + mrq->cmd->resp[3] = mci_readl(host, REG_RESP0); > + } else { > + mrq->cmd->resp[0] = mci_readl(host, REG_RESP0); > + } > + if (mrq->data) > + mrq->data->bytes_xfered = > + mrq->data->blocks * mrq->data->blksz; > + } > + > + if (mrq->data) { > + struct mmc_data *data = mrq->data; > + u32 temp; > + > + mci_writel(host, REG_IDST, 0x337); > + mci_writel(host, REG_DMAC, 0); > + temp = mci_readl(host, REG_GCTRL); > + mci_writel(host, REG_GCTRL, temp|SDXC_DMAReset); > + temp &= ~SDXC_DMAEnb; > + mci_writel(host, REG_GCTRL, temp); > + temp |= SDXC_FIFOReset; > + mci_writel(host, REG_GCTRL, temp); > + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, > + sunxi_mmc_get_dma_dir(data)); > + } > + > + mci_writel(host, REG_RINTR, 0xffff); > + > + dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n", > + mrq->cmd->resp[0], mrq->cmd->resp[1], > + mrq->cmd->resp[2], mrq->cmd->resp[3]); > + > + host->mrq = NULL; > + host->int_sum = 0; > + host->wait_dma = 0; > + > + spin_unlock_irqrestore(&host->lock, iflags); > + > + if (mrq->data && mrq->data->error) { > + dev_err(mmc_dev(host->mmc), > + "data error, sending stop command\n"); > + sunxi_mmc_send_manual_stop(host, mrq); > + } > + > + mmc_request_done(host->mmc, mrq); > +} > + > +static s32 sunxi_mmc_get_ro(struct mmc_host *mmc) > +{ > + struct sunxi_mmc_host *host = mmc_priv(mmc); > + > + int read_only = 0; > + > + if (gpio_is_valid(host->wp_pin)) { > + pinctrl_request_gpio(host->wp_pin); This is actually not needed. It's already called by gpio_request. > + read_only = gpio_get_value(host->wp_pin); > + } > + > + return read_only; > +} > + > +static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) > +{ > + struct sunxi_mmc_host *host = dev_id; > + u32 finalize = 0; > + u32 sdio_int = 0; > + u32 msk_int; > + u32 idma_int; > + > + spin_lock(&host->lock); > + > + idma_int = mci_readl(host, REG_IDST); > + msk_int = mci_readl(host, REG_MISTA); > + > + dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", > + host->mrq, msk_int, idma_int); > + > + if (host->mrq) { > + if (idma_int & SDXC_IDMACReceiveInt) > + host->wait_dma = 0; > + > + host->int_sum |= msk_int; > + > + /* Wait for CmdDone on RespTimeout before finishing the req */ > + if ((host->int_sum & SDXC_RespTimeout) && > + !(host->int_sum & SDXC_CmdDone)) > + mci_writel(host, REG_IMASK, > + host->sdio_imask | SDXC_CmdDone); > + else if (host->int_sum & SDXC_IntErrBit) > + finalize = 1; /* Don't wait for dma on error */ > + else if (host->int_sum & SDXC_IntDoneBit && !host->wait_dma) > + finalize = 1; /* Done */ > + > + if (finalize) { > + mci_writel(host, REG_IMASK, host->sdio_imask); > + mci_writel(host, REG_IDIE, 0); > + } > + } > + > + if (msk_int & SDXC_SDIOInt) > + sdio_int = 1; > + > + mci_writel(host, REG_RINTR, msk_int); > + mci_writel(host, REG_IDST, idma_int); > + > + spin_unlock(&host->lock); > + > + if (finalize) > + tasklet_schedule(&host->tasklet); > + > + if (sdio_int) > + mmc_signal_sdio_irq(host->mmc); > + > + return IRQ_HANDLED; > +} > + > +static void sunxi_mmc_tasklet(unsigned long data) > +{ > + struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data; > + sunxi_mmc_finalize_request(smc_host); > +} > + > +static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) > +{ > + unsigned long expire = jiffies + msecs_to_jiffies(2000); > + u32 rval; > + > + rval = mci_readl(host, REG_CLKCR); > + rval &= ~(SDXC_CardClkOn | SDXC_LowPowerOn); Please add a newline. > + if (oclk_en) > + rval |= SDXC_CardClkOn; Please add a newline. > + if (!host->io_flag) > + rval |= SDXC_LowPowerOn; Please add a newline. > + mci_writel(host, REG_CLKCR, rval); > + > + rval = SDXC_Start | SDXC_UPCLKOnly | SDXC_WaitPreOver; > + if (host->voltage_switching) > + rval |= SDXC_VolSwitch; > + mci_writel(host, REG_CMDR, rval); > + do { > + rval = mci_readl(host, REG_CMDR); > + } while (time_before(jiffies, expire) && (rval & SDXC_Start)); > + > + if (rval & SDXC_Start) { > + dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); > + host->ferror = 1; > + } > +} > + > +static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host, > + u32 oclk_dly, u32 sclk_dly) > +{ > + unsigned long iflags; > + struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod); > + > + spin_lock_irqsave(&smc_host->lock, iflags); > + clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly); > + spin_unlock_irqrestore(&smc_host->lock, iflags); > +} > + > +struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = { > + { MMC_CLK_400K, 0, 7 }, > + { MMC_CLK_25M, 0, 5 }, > + { MMC_CLK_50M, 3, 5 }, > + { MMC_CLK_50MDDR, 2, 4 }, > + { MMC_CLK_50MDDR_8BIT, 2, 4 }, > + { MMC_CLK_100M, 1, 4 }, > + { MMC_CLK_200M, 1, 4 }, > +}; > + > +static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host, > + unsigned int rate) > +{ > + u32 newrate; > + u32 src_clk; > + u32 oclk_dly; > + u32 sclk_dly; > + u32 temp; > + struct sunxi_mmc_clk_dly *dly = NULL; > + > + newrate = clk_round_rate(smc_host->clk_mod, rate); > + if (smc_host->clk_mod_rate == newrate) { > + dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n", > + rate, newrate); > + return; > + } > + > + dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n", > + rate, newrate); > + > + /* setting clock rate */ > + clk_disable(smc_host->clk_mod); > + clk_set_rate(smc_host->clk_mod, newrate); > + clk_enable(smc_host->clk_mod); > + smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod); > + dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate); > + > + sunxi_mmc_oclk_onoff(smc_host, 0); > + /* clear internal divider */ > + temp = mci_readl(smc_host, REG_CLKCR); > + temp &= ~0xff; > + mci_writel(smc_host, REG_CLKCR, temp); > + > + /* determine delays */ > + if (rate <= 400000) { > + dly = &mmc_clk_dly[MMC_CLK_400K]; > + } else if (rate <= 25000000) { > + dly = &mmc_clk_dly[MMC_CLK_25M]; > + } else if (rate <= 50000000) { > + if (smc_host->ddr) { > + if (smc_host->bus_width == 8) > + dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT]; > + else > + dly = &mmc_clk_dly[MMC_CLK_50MDDR]; > + } else { > + dly = &mmc_clk_dly[MMC_CLK_50M]; > + } > + } else if (rate <= 104000000) { > + dly = &mmc_clk_dly[MMC_CLK_100M]; > + } else if (rate <= 208000000) { > + dly = &mmc_clk_dly[MMC_CLK_200M]; > + } else > + dly = &mmc_clk_dly[MMC_CLK_50M]; You need some brackets around that else statement > + > + oclk_dly = dly->oclk_dly; > + sclk_dly = dly->sclk_dly; > + > + src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod)); > + if (src_clk >= 300000000 && src_clk <= 400000000) { > + if (oclk_dly) > + oclk_dly--; > + if (sclk_dly) > + sclk_dly--; > + } > + > + sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly); > + sunxi_mmc_oclk_onoff(smc_host, 1); > + > + /* oclk_onoff sets various irq status bits, clear these */ > + mci_writel(smc_host, REG_RINTR, > + mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIOInt); > +} > + > +static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) > +{ > + struct sunxi_mmc_host *host = mmc_priv(mmc); > + u32 temp; > + s32 err; > + > + /* Set the power state */ > + switch (ios->power_mode) { > + case MMC_POWER_ON: > + break; > + > + case MMC_POWER_UP: > + if (!IS_ERR(host->vmmc)) { > + mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd); > + udelay(200); > + } > + > + err = clk_prepare_enable(host->clk_ahb); > + if (err) { > + dev_err(mmc_dev(host->mmc), "AHB clk err %d\n", err); > + host->ferror = 1; > + return; > + } > + err = clk_prepare_enable(host->clk_mod); > + if (err) { > + dev_err(mmc_dev(host->mmc), "MOD clk err %d\n", err); > + host->ferror = 1; > + return; > + } > + > + sunxi_mmc_init_host(mmc); > + enable_irq(host->irq); > + > + dev_dbg(mmc_dev(host->mmc), "power on!\n"); > + host->ferror = 0; > + break; > + > + case MMC_POWER_OFF: > + dev_dbg(mmc_dev(host->mmc), "power off!\n"); > + disable_irq(host->irq); > + sunxi_mmc_exit_host(host); > + clk_disable_unprepare(host->clk_ahb); > + clk_disable_unprepare(host->clk_mod); > + if (!IS_ERR(host->vmmc)) > + mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); > + host->ferror = 0; > + break; > + } > + > + /* set bus width */ > + switch (ios->bus_width) { > + case MMC_BUS_WIDTH_1: > + mci_writel(host, REG_WIDTH, SDXC_WIDTH1); > + host->bus_width = 1; > + break; > + case MMC_BUS_WIDTH_4: > + mci_writel(host, REG_WIDTH, SDXC_WIDTH4); > + host->bus_width = 4; > + break; > + case MMC_BUS_WIDTH_8: > + mci_writel(host, REG_WIDTH, SDXC_WIDTH8); > + host->bus_width = 8; > + break; > + } > + > + /* set ddr mode */ > + temp = mci_readl(host, REG_GCTRL); > + if (ios->timing == MMC_TIMING_UHS_DDR50) { > + temp |= SDXC_DDR_MODE; > + host->ddr = 1; > + } else { > + temp &= ~SDXC_DDR_MODE; > + host->ddr = 0; > + } > + mci_writel(host, REG_GCTRL, temp); > + > + /* set up clock */ > + if (ios->clock && ios->power_mode) { > + dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock); > + sunxi_mmc_clk_set_rate(host, ios->clock); > + usleep_range(50000, 55000); > + } > +} > + > +static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) > +{ > + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); > + unsigned long flags; > + u32 imask; > + > + spin_lock_irqsave(&smc_host->lock, flags); > + imask = mci_readl(smc_host, REG_IMASK); > + if (enable) { > + smc_host->sdio_imask = SDXC_SDIOInt; > + imask |= SDXC_SDIOInt; > + } else { > + smc_host->sdio_imask = 0; > + imask &= ~SDXC_SDIOInt; > + } > + mci_writel(smc_host, REG_IMASK, imask); > + spin_unlock_irqrestore(&smc_host->lock, flags); > +} > + > +static void sunxi_mmc_hw_reset(struct mmc_host *mmc) > +{ > + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); > + mci_writel(smc_host, REG_HWRST, 0); > + udelay(10); > + mci_writel(smc_host, REG_HWRST, 1); > + udelay(300); > +} > + > +static int sunxi_mmc_card_present(struct mmc_host *mmc) > +{ > + struct sunxi_mmc_host *host = mmc_priv(mmc); > + > + switch (host->cd_mode) { > + case CARD_DETECT_BY_GPIO_POLL: > + return !gpio_get_value(host->cd_pin); /* Signal inverted */ > + case CARD_ALWAYS_PRESENT: > + return 1; > + } > + return 0; /* Never reached */ > +} > + > +static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) > +{ > + struct sunxi_mmc_host *host = mmc_priv(mmc); > + struct mmc_command *cmd = mrq->cmd; > + struct mmc_data *data = mrq->data; > + unsigned long iflags; > + u32 imask = SDXC_IntErrBit; > + u32 cmd_val = SDXC_Start | (cmd->opcode & 0x3f); > + u32 byte_cnt = 0; > + int ret; > + > + if (!sunxi_mmc_card_present(mmc) || host->ferror) { > + dev_dbg(mmc_dev(host->mmc), "no medium present\n"); > + mrq->cmd->error = -ENOMEDIUM; > + mmc_request_done(mmc, mrq); > + return; > + } > + > + if (data) { > + byte_cnt = data->blksz * data->blocks; > + mci_writel(host, REG_BLKSZ, data->blksz); > + mci_writel(host, REG_BCNTR, byte_cnt); > + ret = sunxi_mmc_prepare_dma(host, data); > + if (ret < 0) { > + dev_err(mmc_dev(host->mmc), "prepare DMA failed\n"); > + cmd->error = ret; > + cmd->data->error = ret; > + mmc_request_done(host->mmc, mrq); > + return; > + } > + } > + > + if (cmd->opcode == MMC_GO_IDLE_STATE) { > + cmd_val |= SDXC_SendInitSeq; > + imask |= SDXC_CmdDone; > + } > + > + if (cmd->opcode == SD_SWITCH_VOLTAGE) { > + cmd_val |= SDXC_VolSwitch; > + imask |= SDXC_VolChgDone; > + host->voltage_switching = 1; > + sunxi_mmc_oclk_onoff(host, 1); > + } > + > + if (cmd->flags & MMC_RSP_PRESENT) { > + cmd_val |= SDXC_RspExp; > + if (cmd->flags & MMC_RSP_136) > + cmd_val |= SDXC_LongRsp; > + if (cmd->flags & MMC_RSP_CRC) > + cmd_val |= SDXC_CheckRspCRC; > + > + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) { > + cmd_val |= SDXC_DataExp | SDXC_WaitPreOver; > + if (cmd->data->flags & MMC_DATA_STREAM) { > + imask |= SDXC_AutoCMDDone; > + cmd_val |= SDXC_Seqmod | SDXC_SendAutoStop; > + } > + if (cmd->data->stop) { > + imask |= SDXC_AutoCMDDone; > + cmd_val |= SDXC_SendAutoStop; > + } else > + imask |= SDXC_DataOver; > + > + if (cmd->data->flags & MMC_DATA_WRITE) > + cmd_val |= SDXC_Write; > + else > + host->wait_dma = 1; > + } else > + imask |= SDXC_CmdDone; > + } else > + imask |= SDXC_CmdDone; > + > + dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n", > + cmd_val & 0x3f, cmd_val, cmd->arg, imask, > + mrq->data ? mrq->data->blksz * mrq->data->blocks : 0); > + > + spin_lock_irqsave(&host->lock, iflags); > + host->mrq = mrq; > + mci_writel(host, REG_IMASK, host->sdio_imask | imask); > + spin_unlock_irqrestore(&host->lock, iflags); > + > + mci_writel(host, REG_CARG, cmd->arg); > + mci_writel(host, REG_CMDR, cmd_val); > +} > + > +static const struct of_device_id sunxi_mmc_of_match[] = { > + { .compatible = "allwinner,sun4i-mmc", }, > + { .compatible = "allwinner,sun5i-mmc", }, Please use sun5i-a13-mmc as your compatible. > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); > + > +static struct mmc_host_ops sunxi_mmc_ops = { > + .request = sunxi_mmc_request, > + .set_ios = sunxi_mmc_set_ios, > + .get_ro = sunxi_mmc_get_ro, > + .get_cd = sunxi_mmc_card_present, > + .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, > + .hw_reset = sunxi_mmc_hw_reset, > +}; > + > +static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, > + struct platform_device *pdev) > +{ > + struct device_node *np = pdev->dev.of_node; > + int ret; > + > + if (of_device_is_compatible(np, "allwinner,sun4i-mmc")) > + host->idma_des_size_bits = 13; > + else > + host->idma_des_size_bits = 16; > + > + host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc"); > + if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER) > + return -EPROBE_DEFER; > + > + host->reg_base = devm_ioremap_resource(&pdev->dev, > + platform_get_resource(pdev, IORESOURCE_MEM, 0)); > + if (IS_ERR(host->reg_base)) > + return PTR_ERR(host->reg_base); > + > + host->irq = platform_get_irq(pdev, 0); > + ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0, > + "sunxi-mci", host); > + if (ret) > + return ret; > + disable_irq(host->irq); > + > + host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); > + if (IS_ERR(host->clk_ahb)) { > + dev_err(&pdev->dev, "Could not get ahb clock\n"); > + return PTR_ERR(host->clk_ahb); > + } > + > + host->clk_mod = devm_clk_get(&pdev->dev, "mod"); > + if (IS_ERR(host->clk_mod)) { > + dev_err(&pdev->dev, "Could not get mod clock\n"); > + return PTR_ERR(host->clk_mod); > + } > + > + of_property_read_u32(np, "bus-width", &host->bus_width); > + if (host->bus_width != 1 && host->bus_width != 4) { > + dev_err(&pdev->dev, "Invalid bus-width %d\n", host->bus_width); > + return -EINVAL; > + } > + > + of_property_read_u32(np, "cd-mode", &host->cd_mode); > + switch (host->cd_mode) { > + case CARD_DETECT_BY_GPIO_POLL: > + host->cd_pin = of_get_named_gpio(np, "cd-gpios", 0); > + if (!gpio_is_valid(host->cd_pin)) { > + dev_err(&pdev->dev, "Invalid cd-gpios\n"); > + return -EINVAL; > + } > + ret = devm_gpio_request(&pdev->dev, host->cd_pin, "mmc_cd"); > + if (ret) { > + dev_err(&pdev->dev, "Could not get cd-gpios\n"); > + return ret; > + } > + gpio_direction_input(host->cd_pin); > + break; > + case CARD_ALWAYS_PRESENT: > + break; > + default: > + dev_err(&pdev->dev, "Invalid cd-mode %d\n", host->cd_mode); > + return -EINVAL; > + } > + > + host->wp_pin = of_get_named_gpio(np, "wp-gpios", 0); > + if (gpio_is_valid(host->wp_pin)) { > + ret = devm_gpio_request(&pdev->dev, host->wp_pin, "mmc_wp"); > + if (ret) { > + dev_err(&pdev->dev, "Could not get wp-gpios\n"); > + return ret; > + } > + gpio_direction_input(host->wp_pin); > + } > + > + return 0; > +} > + > +static int sunxi_mmc_probe(struct platform_device *pdev) > +{ > + struct sunxi_mmc_host *host; > + struct mmc_host *mmc; > + int ret; > + > + mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); > + if (!mmc) { > + dev_err(&pdev->dev, "mmc alloc host failed\n"); > + return -ENOMEM; > + } > + > + host = mmc_priv(mmc); > + host->mmc = mmc; > + spin_lock_init(&host->lock); > + tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host); > + > + ret = sunxi_mmc_resource_request(host, pdev); > + if (ret) > + goto error_free_host; > + > + host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, > + &host->sg_dma, GFP_KERNEL); > + if (!host->sg_cpu) { > + dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n"); > + ret = -ENOMEM; > + goto error_free_host; > + } > + > + mmc->ops = &sunxi_mmc_ops; > + mmc->max_blk_count = 8192; > + mmc->max_blk_size = 4096; > + mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); > + mmc->max_seg_size = (1 << host->idma_des_size_bits); > + mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; > + /* 400kHz ~ 50MHz */ > + mmc->f_min = 400000; > + mmc->f_max = 50000000; Hmmm, the tables earlier seem to suggest it can do much more than that. > + /* available voltages */ > + if (!IS_ERR(host->vmmc)) > + mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc); > + else > + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; > + > + mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | > + MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | > + MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL | > + MMC_CAP_DRIVER_TYPE_A; Please add a newline. > + if (host->bus_width == 4) > + mmc->caps |= MMC_CAP_4_BIT_DATA; Please add a newline. > + mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP; > + > + ret = mmc_add_host(mmc); > + if (ret) > + goto error_free_dma; > + > + dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); > + platform_set_drvdata(pdev, mmc); > + return 0; > + > +error_free_dma: > + dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); > +error_free_host: > + mmc_free_host(mmc); > + return ret; > +} > + > +static int sunxi_mmc_remove(struct platform_device *pdev) > +{ > + struct mmc_host *mmc = platform_get_drvdata(pdev); > + struct sunxi_mmc_host *host = mmc_priv(mmc); > + > + mmc_remove_host(mmc); > + sunxi_mmc_exit_host(host); > + tasklet_disable(&host->tasklet); > + dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); > + mmc_free_host(mmc); > + > + return 0; > +} > + > +static struct platform_driver sunxi_mmc_driver = { > + .driver = { > + .name = "sunxi-mci", > + .owner = THIS_MODULE, > + .of_match_table = of_match_ptr(sunxi_mmc_of_match), > + }, > + .probe = sunxi_mmc_probe, > + .remove = sunxi_mmc_remove, > +}; > +module_platform_driver(sunxi_mmc_driver); > + > +MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver"); > +MODULE_LICENSE("GPL v2"); > +MODULE_AUTHOR("David Lanzend?rfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org>"); > +MODULE_ALIAS("platform:sunxi-mmc"); > diff --git a/drivers/mmc/host/sunxi-mci.h b/drivers/mmc/host/sunxi-mci.h > new file mode 100644 > index 0000000..332d3ae > --- /dev/null > +++ b/drivers/mmc/host/sunxi-mci.h > @@ -0,0 +1,246 @@ > +/* > + * Driver for sunxi SD/MMC host controllers > + * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. > + * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh-jFKXxz0WcGyYHARAtoI1EgC/G2K4zDHf@public.gmane.org> > + * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch> > + * (C) Copyright 2013-2013 David Lanzend?rfer <david.lanzendoerfer@o2s.ch> > + * (C) Copyright 2013-2013 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#ifndef __SUNXI_MCI_H__ > +#define __SUNXI_MCI_H__ > + > +/* register offset define */ > +#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */ > +#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */ > +#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */ > +#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */ > +#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */ > +#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */ > +#define SDXC_REG_CMDR (0x18) /* SMC Command Register */ > +#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */ > +#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */ > +#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */ > +#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */ > +#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */ > +#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */ > +#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ > +#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ > +#define SDXC_REG_STAS (0x3C) /* SMC Status Register */ > +#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ > +#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ > +#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ > +#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ > +#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ > +#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ > +#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ > +#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ > +#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ > +#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ > +#define SDXC_REG_CHDA (0x90) > +#define SDXC_REG_CBDA (0x94) > + > +#define mci_readl(host, reg) \ > + __raw_readl((host)->reg_base + SDXC_##reg) > +#define mci_writel(host, reg, value) \ > + __raw_writel((value), (host)->reg_base + SDXC_##reg) No barriers ? :( > +/* global control register bits */ > +#define SDXC_SoftReset BIT(0) > +#define SDXC_FIFOReset BIT(1) > +#define SDXC_DMAReset BIT(2) > +#define SDXC_HWReset (SDXC_SoftReset|SDXC_FIFOReset|SDXC_DMAReset) > +#define SDXC_INTEnb BIT(4) > +#define SDXC_DMAEnb BIT(5) > +#define SDXC_DebounceEnb BIT(8) > +#define SDXC_PosedgeLatchData BIT(9) > +#define SDXC_DDR_MODE BIT(10) > +#define SDXC_MemAccessDone BIT(29) > +#define SDXC_AccessDoneDirect BIT(30) > +#define SDXC_ACCESS_BY_AHB BIT(31) > +#define SDXC_ACCESS_BY_DMA (0U << 31) > +/* clock control bits */ > +#define SDXC_CardClkOn BIT(16) > +#define SDXC_LowPowerOn BIT(17) > +/* bus width */ > +#define SDXC_WIDTH1 (0) > +#define SDXC_WIDTH4 (1) > +#define SDXC_WIDTH8 (2) > +/* smc command bits */ > +#define SDXC_RspExp BIT(6) > +#define SDXC_LongRsp BIT(7) > +#define SDXC_CheckRspCRC BIT(8) > +#define SDXC_DataExp BIT(9) > +#define SDXC_Write BIT(10) > +#define SDXC_Seqmod BIT(11) > +#define SDXC_SendAutoStop BIT(12) > +#define SDXC_WaitPreOver BIT(13) > +#define SDXC_StopAbortCMD BIT(14) > +#define SDXC_SendInitSeq BIT(15) > +#define SDXC_UPCLKOnly BIT(21) > +#define SDXC_RdCEATADev BIT(22) > +#define SDXC_CCSExp BIT(23) > +#define SDXC_EnbBoot BIT(24) > +#define SDXC_AltBootOpt BIT(25) > +#define SDXC_BootACKExp BIT(26) > +#define SDXC_BootAbort BIT(27) > +#define SDXC_VolSwitch BIT(28) > +#define SDXC_UseHoldReg BIT(29) > +#define SDXC_Start BIT(31) > +/* interrupt bits */ > +#define SDXC_RespErr BIT(1) > +#define SDXC_CmdDone BIT(2) > +#define SDXC_DataOver BIT(3) > +#define SDXC_TxDataReq BIT(4) > +#define SDXC_RxDataReq BIT(5) > +#define SDXC_RespCRCErr BIT(6) > +#define SDXC_DataCRCErr BIT(7) > +#define SDXC_RespTimeout BIT(8) > +#define SDXC_DataTimeout BIT(9) > +#define SDXC_VolChgDone BIT(10) > +#define SDXC_FIFORunErr BIT(11) > +#define SDXC_HardWLocked BIT(12) > +#define SDXC_StartBitErr BIT(13) > +#define SDXC_AutoCMDDone BIT(14) > +#define SDXC_EndBitErr BIT(15) > +#define SDXC_SDIOInt BIT(16) > +#define SDXC_CardInsert BIT(30) > +#define SDXC_CardRemove BIT(31) > +#define SDXC_IntErrBit (SDXC_RespErr | SDXC_RespCRCErr | \ > + SDXC_DataCRCErr | SDXC_RespTimeout | \ > + SDXC_DataTimeout | SDXC_FIFORunErr | \ > + SDXC_HardWLocked | SDXC_StartBitErr | \ > + SDXC_EndBitErr) /* 0xbbc2 */ > +#define SDXC_IntDoneBit (SDXC_AutoCMDDone | SDXC_DataOver | \ > + SDXC_CmdDone | SDXC_VolChgDone) > +/* status */ > +#define SDXC_RXWLFlag BIT(0) > +#define SDXC_TXWLFlag BIT(1) > +#define SDXC_FIFOEmpty BIT(2) > +#define SDXC_FIFOFull BIT(3) > +#define SDXC_CardPresent BIT(8) > +#define SDXC_CardDataBusy BIT(9) > +#define SDXC_DataFSMBusy BIT(10) > +#define SDXC_DMAReq BIT(31) > +#define SDXC_FIFO_SIZE (16) > +/* Function select */ > +#define SDXC_CEATAOn (0xceaaU << 16) > +#define SDXC_SendIrqRsp BIT(0) > +#define SDXC_SDIORdWait BIT(1) > +#define SDXC_AbtRdData BIT(2) > +#define SDXC_SendCCSD BIT(8) > +#define SDXC_SendAutoStopCCSD BIT(9) > +#define SDXC_CEATADevIntEnb BIT(10) > +/* IDMA controller bus mod bit field */ > +#define SDXC_IDMACSoftRST BIT(0) > +#define SDXC_IDMACFixBurst BIT(1) > +#define SDXC_IDMACIDMAOn BIT(7) > +#define SDXC_IDMACRefetchDES BIT(31) > +/* IDMA status bit field */ > +#define SDXC_IDMACTransmitInt BIT(0) > +#define SDXC_IDMACReceiveInt BIT(1) > +#define SDXC_IDMACFatalBusErr BIT(2) > +#define SDXC_IDMACDesInvalid BIT(4) > +#define SDXC_IDMACCardErrSum BIT(5) > +#define SDXC_IDMACNormalIntSum BIT(8) > +#define SDXC_IDMACAbnormalIntSum BIT(9) > +#define SDXC_IDMACHostAbtInTx BIT(10) > +#define SDXC_IDMACHostAbtInRx BIT(10) > +#define SDXC_IDMACIdle (0U << 13) > +#define SDXC_IDMACSuspend (1U << 13) > +#define SDXC_IDMACDESCRd (2U << 13) > +#define SDXC_IDMACDESCCheck (3U << 13) > +#define SDXC_IDMACRdReqWait (4U << 13) > +#define SDXC_IDMACWrReqWait (5U << 13) > +#define SDXC_IDMACRd (6U << 13) > +#define SDXC_IDMACWr (7U << 13) > +#define SDXC_IDMACDESCClose (8U << 13) > + > +struct sunxi_idma_des { > + u32 config; > +#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */ > +#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */ > +#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */ > +#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */ > +#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */ > +#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ > +#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ > + > + /* > + * If the idma-des-size-bits of property is ie 13, bufsize bits are: > + * Bits 0-12: buf1 size > + * Bits 13-25: buf2 size > + * Bits 26-31: not used > + * Since we only ever set buf1 size, we can simply store it directly. > + */ > + u32 buf_size; > + u32 buf_addr_ptr1; > + u32 buf_addr_ptr2; > +}; > + > +struct sunxi_mmc_host { > + struct mmc_host *mmc; > + struct regulator *vmmc; > + > + /* IO mapping base */ > + void __iomem *reg_base; > + > + spinlock_t lock; > + struct tasklet_struct tasklet; > + > + /* clock management */ > + struct clk *clk_ahb; > + struct clk *clk_mod; > + > + /* indicator pins */ > + int wp_pin; > + int cd_pin; > + int cd_mode; > +#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */ > +#define CARD_ALWAYS_PRESENT (2) /* mmc always present */ Just a question here, have you tested to use the external interrupts? (Is that even possible on the pins that are used as card detect?) > + /* ios information */ > + u32 clk_mod_rate; > + u32 bus_width; > + u32 idma_des_size_bits; > + u32 ddr; > + u32 voltage_switching; > + > + /* irq */ > + int irq; > + u32 int_sum; > + u32 sdio_imask; > + > + /* flags */ > + u32 power_on:1; > + u32 io_flag:1; > + u32 wait_dma:1; > + > + dma_addr_t sg_dma; > + void *sg_cpu; > + > + struct mmc_request *mrq; > + u32 ferror; > +}; > + > +#define MMC_CLK_400K 0 > +#define MMC_CLK_25M 1 > +#define MMC_CLK_50M 2 > +#define MMC_CLK_50MDDR 3 > +#define MMC_CLK_50MDDR_8BIT 4 > +#define MMC_CLK_100M 5 > +#define MMC_CLK_200M 6 > +#define MMC_CLK_MOD_NUM 7 > + > +struct sunxi_mmc_clk_dly { > + u32 mode; > + u32 oclk_dly; > + u32 sclk_dly; > +}; > + > +#endif > diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h > new file mode 100644 > index 0000000..1ef5c89 > --- /dev/null > +++ b/include/linux/clk/sunxi.h > @@ -0,0 +1,22 @@ > +/* > + * Copyright 2013 - Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#ifndef __LINUX_CLK_SUNXI_H_ > +#define __LINUX_CLK_SUNXI_H_ > + > +#include <linux/clk.h> > + > +void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); > + > +#endif Hmmm, I see no implementation for this function. Didn't you forget a file here? (and it should probably be a separate patch anyway). Thanks a lot for this work, Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs 2013-12-15 13:44 ` Maxime Ripard @ 2013-12-15 14:20 ` Hans de Goede [not found] ` <52ADBAA3.7060507-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 22:01 ` Michal Suchanek 2014-02-05 13:33 ` David Lanzendörfer 2 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-15 14:20 UTC (permalink / raw) To: Maxime Ripard Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi, On 12/15/2013 02:44 PM, Maxime Ripard wrote: > Hi Hans, > > I won't comment on the MMC driver itself, and leave Chris comment on > that, but still, I have a few things. > > On Sat, Dec 14, 2013 at 10:58:11PM +0100, Hans de Goede wrote: >> From: David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org> >> >> This is based on the driver Allwinner ships in there Android kernel sources. >> >> Initial porting to upstream kernels done by David Lanzendörfer, additional >> fixes and cleanups by Hans de Goede. >> >> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > > Your commit log is a bit sparse. What capabilities this controller > has? Is it using DMA? If so, how? What SoCs are supported/it has been > tested on? etc. David, since you'll be doing v2 I guess you'll be filling in v2. FYI I've tested this on sun4i-a10, sun5i-a10s sun5i-a13 and sun7i-a20. It uses dma in bus-master mode using a built-in designware idmac controller, which is identical to the one found in the mmc-dw hosts. Note the rest of the host is not identical, I've looked into reusing the mmc-dw driver but that does not seem like a good idea (manual sending stop commands versus auto stop on sunxi, completely different registers, etc.). > > Also, you probably needs David's SoB here. The plan is for David to send v2 of this patch-set so that should take care of that :) > >> --- >> drivers/mmc/host/Kconfig | 8 + >> drivers/mmc/host/Makefile | 2 + >> drivers/mmc/host/sunxi-mci.c | 908 +++++++++++++++++++++++++++++++++++++++++++ >> drivers/mmc/host/sunxi-mci.h | 246 ++++++++++++ >> include/linux/clk/sunxi.h | 22 ++ > > Please add your dt bindings documentation in Documentation/devicetree/bindings > <snip> >> +#include "sunxi-mci.h" >> + >> +static void sunxi_mmc_init_host(struct mmc_host *mmc) >> +{ >> + u32 rval; >> + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); >> + >> + /* reset controller */ >> + rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset; >> + mci_writel(smc_host, REG_GCTRL, rval); >> + >> + mci_writel(smc_host, REG_FTRGL, 0x20070008); These set tx/rx FIFO thresholds, I think 7 is one, 8 is the other (no idea which is which) and the 2 is magic ... >> + mci_writel(smc_host, REG_TMOUT, 0xffffffff); >> + mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask); >> + mci_writel(smc_host, REG_RINTR, 0xffffffff); This simple clears any interrupt flags left set by uboot >> + mci_writel(smc_host, REG_DBGC, 0xdeb); Unknown >> + mci_writel(smc_host, REG_FUNS, 0xceaa0000); There actually is a define for this in the .h file called: "SDXC_CEATAOn" no idea what that means though, I guess we should use the define here. David can you fix this in v2 ? >> + mci_writel(smc_host, REG_DLBA, smc_host->sg_dma); > > I suppose we have no idea what these magics are all about ? :( See above, we have some idea, but not much. > >> + rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb; >> + rval &= ~SDXC_AccessDoneDirect; >> + mci_writel(smc_host, REG_GCTRL, rval); >> +} <snip> >> +static const struct of_device_id sunxi_mmc_of_match[] = { >> + { .compatible = "allwinner,sun4i-mmc", }, >> + { .compatible = "allwinner,sun5i-mmc", }, > > Please use sun5i-a13-mmc as your compatible. Can you explain a bit why? In essence currently we have 2 versions of the mmc controller, those found on sun4i and those found on sun5i and sun7i. I thought that the norm was to use the oldest soc version in which a revision of an ip-block first appears as the compatible string ? Note I've tested this with both a13 and a10s SOCs, if we add a sun5i-a13-mmc we should also add a sun5i-a10s-mmc and a sun5i-a20-mmc, or would that then be sun7i-a20-mmc? To me just having sun5i-mmc for sun5i+ socs seems simpler. <snip> >> + mmc->ops = &sunxi_mmc_ops; >> + mmc->max_blk_count = 8192; >> + mmc->max_blk_size = 4096; >> + mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); >> + mmc->max_seg_size = (1 << host->idma_des_size_bits); >> + mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; >> + /* 400kHz ~ 50MHz */ >> + mmc->f_min = 400000; >> + mmc->f_max = 50000000; > > Hmmm, the tables earlier seem to suggest it can do much more than that. I know, but this is what the allwinner android kernels are using, actually in case of sdc3 they are putting 200000000 in f_max (as that is often used for sdio cards) but then later in set_ios they clamp the passed in clock to 47000000 Mhz, so I seriously doubt that 200Mhz has actually worked. Hence I've simply gone for a safe range for now. If someone has cards capable of doing 200 MHz we could certainly run various tests and try to improve this, but for now this seems a sane range to start with. <snip> >> + /* indicator pins */ >> + int wp_pin; >> + int cd_pin; >> + int cd_mode; >> +#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */ >> +#define CARD_ALWAYS_PRESENT (2) /* mmc always present */ > > Just a question here, have you tested to use the external interrupts? > (Is that even possible on the pins that are used as card detect?) > No I've not tried that, there was code for this in the original allwinner driver, but no boards were actually using it. As for it being possible on the pins being used, it is possible on (most) port H pins and the cubie* and a20-olinuxino-micro boards are using PH pins for cd. Others are not. One thing which worries me about this is debouncing, using polling is automatically debounced, using an external interrupt won't be. Ideally there would be some common code somewhere to deal with gpio connected buttons (which this in essence is) which does debouncing ... Again I think this is something best left as a future enhancement. <snip> >> diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h >> new file mode 100644 >> index 0000000..1ef5c89 >> --- /dev/null >> +++ b/include/linux/clk/sunxi.h >> @@ -0,0 +1,22 @@ >> +/* >> + * Copyright 2013 - Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + */ >> + >> +#ifndef __LINUX_CLK_SUNXI_H_ >> +#define __LINUX_CLK_SUNXI_H_ >> + >> +#include <linux/clk.h> >> + >> +void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); >> + >> +#endif > > Hmmm, I see no implementation for this function. Didn't you forget > a file here? (and it should probably be a separate patch anyway). The implementation is part of Emilio's clk branch, but he forgot to add a header for it, so I'm fixing that up here, I guess this should go through Emlio's tree as a separate patch. > Thanks a lot for this work, You're welcome. I think it is great to see how far along upstream sunxi support has come thanks to work of all involved. It is really becoming usable now :) Regards, Hans -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out. ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <52ADBAA3.7060507-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <52ADBAA3.7060507-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-15 16:21 ` Maxime Ripard 2013-12-15 18:41 ` Hans de Goede 2013-12-15 16:33 ` David Lanzendörfer 1 sibling, 1 reply; 31+ messages in thread From: Maxime Ripard @ 2013-12-15 16:21 UTC (permalink / raw) To: Hans de Goede Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 6784 bytes --] On Sun, Dec 15, 2013 at 03:20:19PM +0100, Hans de Goede wrote: > On 12/15/2013 02:44 PM, Maxime Ripard wrote: > >Hi Hans, > > > >I won't comment on the MMC driver itself, and leave Chris comment on > >that, but still, I have a few things. > > > >On Sat, Dec 14, 2013 at 10:58:11PM +0100, Hans de Goede wrote: > >>From: David Lanzendörfer <david.lanzendoerfer-Z7Kmv9EsliU@public.gmane.org> > >> > >>This is based on the driver Allwinner ships in there Android kernel sources. > >> > >>Initial porting to upstream kernels done by David Lanzendörfer, additional > >>fixes and cleanups by Hans de Goede. > >> > >>Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > > > >Your commit log is a bit sparse. What capabilities this controller > >has? Is it using DMA? If so, how? What SoCs are supported/it has been > >tested on? etc. > > David, since you'll be doing v2 I guess you'll be filling in v2. FYI > I've tested this on sun4i-a10, sun5i-a10s sun5i-a13 and sun7i-a20. > > It uses dma in bus-master mode using a built-in designware idmac controller, > which is identical to the one found in the mmc-dw hosts. Note the rest of > the host is not identical, I've looked into reusing the mmc-dw driver but > that does not seem like a good idea (manual sending stop commands > versus auto stop on sunxi, completely different registers, etc.). Thanks :) This is exactly what I expect from a commit log of such driver ;) > >>+static const struct of_device_id sunxi_mmc_of_match[] = { > >>+ { .compatible = "allwinner,sun4i-mmc", }, > >>+ { .compatible = "allwinner,sun5i-mmc", }, > > > >Please use sun5i-a13-mmc as your compatible. > > Can you explain a bit why? In essence currently we have > 2 versions of the mmc controller, those found on sun4i > and those found on sun5i and sun7i. I thought that the > norm was to use the oldest soc version in which a revision > of an ip-block first appears as the compatible string ? Indeed. > Note I've tested this with both a13 and a10s SOCs, if we > add a sun5i-a13-mmc we should also add a sun5i-a10s-mmc > and a sun5i-a20-mmc, or would that then be sun7i-a20-mmc? And the A13 has been the first SoC in the sun5i family, hence why we should use sun5i-a13 as the prefix here. If the A10s and A20 would not have been compatible with the A13 MMC controller, we would have used sun5i-a10s-mmc and sun7i-a20-mmc, respectively. > To me just having sun5i-mmc for sun5i+ socs seems simpler. And if we ever find out that A10s or A13 differs in some way, we will end up introducing a compatible that will be sun5i-a10s-mmc, along with the sun5i-mmc we already have, which is not really the more consistent thing we would have done. > <snip> > > >>+ mmc->ops = &sunxi_mmc_ops; > >>+ mmc->max_blk_count = 8192; > >>+ mmc->max_blk_size = 4096; > >>+ mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); > >>+ mmc->max_seg_size = (1 << host->idma_des_size_bits); > >>+ mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; > >>+ /* 400kHz ~ 50MHz */ > >>+ mmc->f_min = 400000; > >>+ mmc->f_max = 50000000; > > > >Hmmm, the tables earlier seem to suggest it can do much more than that. > > I know, but this is what the allwinner android kernels are using, actually > in case of sdc3 they are putting 200000000 in f_max (as that is often > used for sdio cards) but then later in set_ios they clamp the passed > in clock to 47000000 Mhz, so I seriously doubt that 200Mhz has actually > worked. Hence I've simply gone for a safe range for now. If someone has > cards capable of doing 200 MHz we could certainly run various tests and > try to improve this, but for now this seems a sane range to start with. That's probably something that you should mention in your comment then :) > <snip> > > >> + /* indicator pins */ > >> + int wp_pin; > >> + int cd_pin; > >> + int cd_mode; > >> +#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */ > >> +#define CARD_ALWAYS_PRESENT (2) /* mmc always present */ > > > > Just a question here, have you tested to use the external interrupts? > > (Is that even possible on the pins that are used as card detect?) > > > > No I've not tried that, there was code for this in the original allwinner > driver, but no boards were actually using it. > > As for it being possible on the pins being used, it is possible on (most) > port H pins and the cubie* and a20-olinuxino-micro boards are using PH pins > for cd. Others are not. One thing which worries me about this is debouncing, > using polling is automatically debounced, using an external interrupt won't > be. Ideally there would be some common code somewhere to deal with gpio > connected buttons (which this in essence is) which does debouncing ... > > Again I think this is something best left as a future enhancement. Yep, definitely, I was just being curious :) > >>diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h > >>new file mode 100644 > >>index 0000000..1ef5c89 > >>--- /dev/null > >>+++ b/include/linux/clk/sunxi.h > >>@@ -0,0 +1,22 @@ > >>+/* > >>+ * Copyright 2013 - Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > >>+ * > >>+ * This program is free software; you can redistribute it and/or modify > >>+ * it under the terms of the GNU General Public License as published by > >>+ * the Free Software Foundation; either version 2 of the License, or > >>+ * (at your option) any later version. > >>+ * > >>+ * This program is distributed in the hope that it will be useful, > >>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of > >>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > >>+ * GNU General Public License for more details. > >>+ */ > >>+ > >>+#ifndef __LINUX_CLK_SUNXI_H_ > >>+#define __LINUX_CLK_SUNXI_H_ > >>+ > >>+#include <linux/clk.h> > >>+ > >>+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); > >>+ > >>+#endif > > > >Hmmm, I see no implementation for this function. Didn't you forget > >a file here? (and it should probably be a separate patch anyway). > > The implementation is part of Emilio's clk branch, but he forgot > to add a header for it, so I'm fixing that up here, I guess this > should go through Emlio's tree as a separate patch. As far as I know, this work has never been posted, let alone merged. Anyway, the dependencies you have is something that you should mention in your cover letter, so that we know what to merge, in which order, and when to merge it. Thanks! Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs 2013-12-15 16:21 ` Maxime Ripard @ 2013-12-15 18:41 ` Hans de Goede [not found] ` <52ADF7D8.2010900-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-15 18:41 UTC (permalink / raw) To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi, On 12/15/2013 05:21 PM, Maxime Ripard wrote: > On Sun, Dec 15, 2013 at 03:20:19PM +0100, Hans de Goede wrote: <snip> >>>> +static const struct of_device_id sunxi_mmc_of_match[] = { >>>> + { .compatible = "allwinner,sun4i-mmc", }, >>>> + { .compatible = "allwinner,sun5i-mmc", }, >>> >>> Please use sun5i-a13-mmc as your compatible. >> >> Can you explain a bit why? In essence currently we have >> 2 versions of the mmc controller, those found on sun4i >> and those found on sun5i and sun7i. I thought that the >> norm was to use the oldest soc version in which a revision >> of an ip-block first appears as the compatible string ? > > Indeed. > >> Note I've tested this with both a13 and a10s SOCs, if we >> add a sun5i-a13-mmc we should also add a sun5i-a10s-mmc >> and a sun5i-a20-mmc, or would that then be sun7i-a20-mmc? > > And the A13 has been the first SoC in the sun5i family, hence why we > should use sun5i-a13 as the prefix here. If the A10s and A20 would not > have been compatible with the A13 MMC controller, we would have used > sun5i-a10s-mmc and sun7i-a20-mmc, respectively. Ah I see, you meant s/allwinner,sun5i-mmc/allwinner,sun5i-a13-mmc/ I interpreted your remark as adding an extra allwinner,sun5i-a13-mmc compatible string. Using allwinner,sun5i-a13-mmc instead of allwinner,sun5i-mmc makes sense. David having us both editing the driver at the same time seems counter-productive, can you take care of this too? > >> To me just having sun5i-mmc for sun5i+ socs seems simpler. > > And if we ever find out that A10s or A13 differs in some way, we will > end up introducing a compatible that will be sun5i-a10s-mmc, along > with the sun5i-mmc we already have, which is not really the more > consistent thing we would have done. > >> <snip> >> >>>> + mmc->ops = &sunxi_mmc_ops; >>>> + mmc->max_blk_count = 8192; >>>> + mmc->max_blk_size = 4096; >>>> + mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); >>>> + mmc->max_seg_size = (1 << host->idma_des_size_bits); >>>> + mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; >>>> + /* 400kHz ~ 50MHz */ >>>> + mmc->f_min = 400000; >>>> + mmc->f_max = 50000000; >>> >>> Hmmm, the tables earlier seem to suggest it can do much more than that. >> >> I know, but this is what the allwinner android kernels are using, actually >> in case of sdc3 they are putting 200000000 in f_max (as that is often >> used for sdio cards) but then later in set_ios they clamp the passed >> in clock to 47000000 Mhz, so I seriously doubt that 200Mhz has actually >> worked. Hence I've simply gone for a safe range for now. If someone has >> cards capable of doing 200 MHz we could certainly run various tests and >> try to improve this, but for now this seems a sane range to start with. > > That's probably something that you should mention in your comment then :) Good point, David ? <snip> >>> Hmmm, I see no implementation for this function. Didn't you forget >>> a file here? (and it should probably be a separate patch anyway). >> >> The implementation is part of Emilio's clk branch, but he forgot >> to add a header for it, so I'm fixing that up here, I guess this >> should go through Emlio's tree as a separate patch. > > As far as I know, this work has never been posted, let alone > merged. I don't know if it has been posted, but it has been in his tree for a while now. Anyways I'll send him a standalone patch for the clk/sunxi.h file. > Anyway, the dependencies you have is something that you should > mention in your cover letter, so that we know what to merge, in which > order, and when to merge it. Right, my bad, sorry. I was so happy I was finally ready to send the patch upstream (I finally had fixed everything on my todo list), I rushed the cover letter a bit. I was planning on putting things like this in there, as well as why we didn't try to extend the mmc-dw driver, but I forgot. Thanks & Regards, Hans ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <52ADF7D8.2010900-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <52ADF7D8.2010900-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-15 19:35 ` David Lanzendörfer [not found] ` <2378731.6b9MyH8v8A-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: David Lanzendörfer @ 2013-12-15 19:35 UTC (permalink / raw) To: Hans de Goede Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 1337 bytes --] Hi > >>>> [...] > >>>> + mmc->f_max = 50000000; > >>>> [...] > >> [...] > >> in case of sdc3 they are putting 200000000 in f_max (as that is often > >> used for sdio cards) but then later in set_ios they clamp the passed > >> in clock to 47000000 Mhz, so I seriously doubt that 200Mhz has actually > >> worked. Hence I've simply gone for a safe range for now. If someone has > >> cards capable of doing 200 MHz we could certainly run various tests and > >> try to improve this, but for now this seems a sane range to start with. > > That's probably something that you should mention in your comment then :) > Good point, David ? Yes. a) We should mention any reason why we did what. b) If there is room for optimization we should mention that as well since: i) we won't remember every single detail in half a year ii) someone else might need to follow our considerations > Right, my bad, sorry. I was so happy I was finally ready to send the patch > upstream (I finally had fixed everything on my todo list), I rushed the > cover letter a bit. I was planning on putting things like this in there, > as well as why we didn't try to extend the mmc-dw driver, but I forgot. Do you have something like this in mind? -> drivers/mmc/host/dw_mmc-exynos.c Might actually be working if it actually is the same IDMAC controller. cheers David [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <2378731.6b9MyH8v8A-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <2378731.6b9MyH8v8A-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org> @ 2013-12-15 20:18 ` Hans de Goede [not found] ` <52AE0E87.2040304-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-15 20:18 UTC (permalink / raw) To: David Lanzendörfer Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi, On 12/15/2013 08:35 PM, David Lanzendörfer wrote: > Hi > >>>>>> [...] >>>>>> + mmc->f_max = 50000000; >>>>>> [...] >>>> [...] >>>> in case of sdc3 they are putting 200000000 in f_max (as that is often >>>> used for sdio cards) but then later in set_ios they clamp the passed >>>> in clock to 47000000 Mhz, so I seriously doubt that 200Mhz has actually >>>> worked. Hence I've simply gone for a safe range for now. If someone has >>>> cards capable of doing 200 MHz we could certainly run various tests and >>>> try to improve this, but for now this seems a sane range to start with. >>> That's probably something that you should mention in your comment then :) >> Good point, David ? > Yes. > a) We should mention any reason why we did what. > b) If there is room for optimization we should mention that as well since: > i) we won't remember every single detail in half a year > ii) someone else might need to follow our considerations > >> Right, my bad, sorry. I was so happy I was finally ready to send the patch >> upstream (I finally had fixed everything on my todo list), I rushed the >> cover letter a bit. I was planning on putting things like this in there, >> as well as why we didn't try to extend the mmc-dw driver, but I forgot. > Do you have something like this in mind? -> drivers/mmc/host/dw_mmc-exynos.c No, as explained in my previous mail the idmac being shared seemed to be the only 2 things the dw-mmc controller and the sunxi-mmc controller have in common. Looking at dw_mmc-exynos.c it still pretty much is the classic dw-mmc controller with some extra bits, where as the sunxi controller is significantly different (which allows us to write a significant simpler driver). Regards, Hans -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out. ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <52AE0E87.2040304-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <52AE0E87.2040304-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-15 21:19 ` David Lanzendörfer [not found] ` <1743952.noztKtcF2Y-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: David Lanzendörfer @ 2013-12-15 21:19 UTC (permalink / raw) To: Hans de Goede Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 703 bytes --] > > [...] > > Do you have something like this in mind? -> > > drivers/mmc/host/dw_mmc-exynos.c > No, as explained in my previous mail the idmac being shared seemed to be the > only 2 things the dw-mmc controller and the sunxi-mmc controller have in > common. Ok. > Looking at dw_mmc-exynos.c it still pretty much is the classic dw-mmc > controller with some extra bits, where as the sunxi controller is > significantly different (which allows us to write a significant simpler > driver). Do you have an outline for such a driver as you imagine it? I'd be interested into some "experiments". Maybe you have a repository where you could push a dedicated tree for some colaboration on this? regards David [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <1743952.noztKtcF2Y-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <1743952.noztKtcF2Y-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org> @ 2013-12-16 12:21 ` Hans de Goede [not found] ` <52AEF060.6000405-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-16 12:21 UTC (permalink / raw) To: David Lanzendörfer Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi, On 12/15/2013 10:19 PM, David Lanzendörfer wrote: >>> [...] >>> Do you have something like this in mind? -> >>> drivers/mmc/host/dw_mmc-exynos.c >> No, as explained in my previous mail the idmac being shared seemed to be the >> only 2 things the dw-mmc controller and the sunxi-mmc controller have in >> common. > Ok. > >> Looking at dw_mmc-exynos.c it still pretty much is the classic dw-mmc >> controller with some extra bits, where as the sunxi controller is >> significantly different (which allows us to write a significant simpler >> driver). > Do you have an outline for such a driver as you imagine it? > I'd be interested into some "experiments". > Maybe you have a repository where you could push a dedicated tree > for some colaboration on this? I think that we're miss-communicating a bit here. What I'm trying to say is that trying to extend the dw_mmc driver to support sunxi is a bad idea because the sunxi hardware is quite different. And that the sunxi hardware having autostop allows the existing sunxi-mci driver to be much simpler then the dw-mmc driver. IOW the much simpler driver already exists and it is the sunxi-mci driver. Regards, Hans -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out. ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <52AEF060.6000405-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <52AEF060.6000405-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-23 10:36 ` David Lanzendörfer 0 siblings, 0 replies; 31+ messages in thread From: David Lanzendörfer @ 2013-12-23 10:36 UTC (permalink / raw) To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Cc: Hans de Goede, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, linux-mmc-u79uwXL29TY76Z2rM5mHXA [-- Attachment #1: Type: text/plain, Size: 862 bytes --] > I think that we're miss-communicating a bit here. What I'm trying to say > is that trying to extend the dw_mmc driver to support sunxi is a bad > idea because the sunxi hardware is quite different. And that the > sunxi hardware having autostop allows the existing sunxi-mci driver to > be much simpler then the dw-mmc driver. > IOW the much simpler driver already exists and it is the sunxi-mci > driver. Ah! Ok. Now I get it. Well then. I'll try to incorporate all the changes within this endless thread until I can get together a patchset v2 I can hand in. Now that the lectures have ended for this semester I won't be too tired for straight thinking on daily basis and will be able to create such a patchset. And please excuse my contentless answers onto the last few questions but I really wasn't myself - so to say - at this time (half asleep) -david [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <52ADBAA3.7060507-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 16:21 ` Maxime Ripard @ 2013-12-15 16:33 ` David Lanzendörfer 1 sibling, 0 replies; 31+ messages in thread From: David Lanzendörfer @ 2013-12-15 16:33 UTC (permalink / raw) To: Hans de Goede Cc: Maxime Ripard, Chris Ball, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 876 bytes --] Hi > David, since you'll be doing v2 I guess you'll be filling in v2. FYI > I've tested this on sun4i-a10, sun5i-a10s sun5i-a13 and sun7i-a20. Yeah. I'll take care of it. I'll work out a V2 which incorporates all the comments made on the first patch set you've handed in. > It uses dma in bus-master mode using a built-in designware idmac controller, > which is identical to the one found in the mmc-dw hosts. Note the rest of > the host is not identical, I've looked into reusing the mmc-dw driver but > that does not seem like a good idea (manual sending stop commands > versus auto stop on sunxi, completely different registers, etc.). It's already a good thing, that I know now what the command set of the IDMAC controller is, since I had no idea how to configure it exactly. > The plan is for David to send v2 of this patch-set so that should take care > of that :) ok [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs 2013-12-15 13:44 ` Maxime Ripard 2013-12-15 14:20 ` Hans de Goede @ 2013-12-15 22:01 ` Michal Suchanek [not found] ` <CAOMqctRspBPmNsyXye_gpfwGoZ=gMcCzEjM+hD3g+ZfQix7G6Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2014-02-05 13:33 ` David Lanzendörfer 2 siblings, 1 reply; 31+ messages in thread From: Michal Suchanek @ 2013-12-15 22:01 UTC (permalink / raw) To: linux-sunxi Cc: Hans de Goede, Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On 15 December 2013 14:44, Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: >> --- a/drivers/mmc/host/Kconfig >> +++ b/drivers/mmc/host/Kconfig >> @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI >> help >> Say Y here to include driver code to support SD/MMC card interface >> of Realtek PCI-E card reader >> + >> +config MMC_SUNXI >> + tristate "Allwinner sunxi SD/MMC Host Controller support" >> + depends on ARCH_SUNXI >> + default y > > I'm not that fond of these "default y" patterns. It forces the driver > down to every user of the multiplatform kernels. I'd suggest removing > the default and adding the driver to the defconfigs we have. And why would you build support for sunxi without building support for sunxi mmc? Like 90%+ sunxi devices actually have a SD slot or an eMMC or a SDIO card connected so what's the point of supporting sunxi without sunxi mmc? Thanks Michal ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <CAOMqctRspBPmNsyXye_gpfwGoZ=gMcCzEjM+hD3g+ZfQix7G6Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <CAOMqctRspBPmNsyXye_gpfwGoZ=gMcCzEjM+hD3g+ZfQix7G6Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2013-12-16 10:05 ` Maxime Ripard 2013-12-16 11:59 ` Michal Suchanek 0 siblings, 1 reply; 31+ messages in thread From: Maxime Ripard @ 2013-12-16 10:05 UTC (permalink / raw) To: Michal Suchanek Cc: linux-sunxi, Hans de Goede, Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 1359 bytes --] On Sun, Dec 15, 2013 at 11:01:17PM +0100, Michal Suchanek wrote: > On 15 December 2013 14:44, Maxime Ripard > <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: > >> --- a/drivers/mmc/host/Kconfig > >> +++ b/drivers/mmc/host/Kconfig > >> @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI > >> help > >> Say Y here to include driver code to support SD/MMC card interface > >> of Realtek PCI-E card reader > >> + > >> +config MMC_SUNXI > >> + tristate "Allwinner sunxi SD/MMC Host Controller support" > >> + depends on ARCH_SUNXI > >> + default y > > > > I'm not that fond of these "default y" patterns. It forces the driver > > down to every user of the multiplatform kernels. I'd suggest removing > > the default and adding the driver to the defconfigs we have. > > And why would you build support for sunxi without building support for > sunxi mmc? Because you can? And where am I actually suggesting to do so? > Like 90%+ sunxi devices actually have a SD slot or an eMMC or a SDIO > card connected so what's the point of supporting sunxi without sunxi > mmc? And does your assumption still stand if you take into account all the other ARM boards? Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs 2013-12-16 10:05 ` Maxime Ripard @ 2013-12-16 11:59 ` Michal Suchanek [not found] ` <CAOMqctTdasLxJki0xu4aq_sEgujDt3Jdu=BXy9WvQeji282_Rg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 31+ messages in thread From: Michal Suchanek @ 2013-12-16 11:59 UTC (permalink / raw) To: Maxime Ripard Cc: linux-sunxi, Hans de Goede, Chris Ball, David Lanzendörfer, linux-mmc, devicetree, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On 16 December 2013 11:05, Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: > On Sun, Dec 15, 2013 at 11:01:17PM +0100, Michal Suchanek wrote: >> On 15 December 2013 14:44, Maxime Ripard >> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: >> >> --- a/drivers/mmc/host/Kconfig >> >> +++ b/drivers/mmc/host/Kconfig >> >> @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI >> >> help >> >> Say Y here to include driver code to support SD/MMC card interface >> >> of Realtek PCI-E card reader >> >> + >> >> +config MMC_SUNXI >> >> + tristate "Allwinner sunxi SD/MMC Host Controller support" >> >> + depends on ARCH_SUNXI >> >> + default y >> > >> > I'm not that fond of these "default y" patterns. It forces the driver >> > down to every user of the multiplatform kernels. I'd suggest removing >> > the default and adding the driver to the defconfigs we have. >> >> And why would you build support for sunxi without building support for >> sunxi mmc? > > Because you can? But does that need to be the default? And is that sane default? > > And where am I actually suggesting to do so? Just a few lines above. You suggest it should not be built by default. > >> Like 90%+ sunxi devices actually have a SD slot or an eMMC or a SDIO >> card connected so what's the point of supporting sunxi without sunxi >> mmc? > > And does your assumption still stand if you take into account all the > other ARM boards? Sure. It depends on sunxi platform so if you compile in support for that 90%+ boards you just added have something connected to a mmc controller so the sane thing is to also add the mmc controller. Thanks Michal ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <CAOMqctTdasLxJki0xu4aq_sEgujDt3Jdu=BXy9WvQeji282_Rg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <CAOMqctTdasLxJki0xu4aq_sEgujDt3Jdu=BXy9WvQeji282_Rg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2013-12-16 12:49 ` Ian Campbell 2013-12-16 12:53 ` Maxime Ripard 1 sibling, 0 replies; 31+ messages in thread From: Ian Campbell @ 2013-12-16 12:49 UTC (permalink / raw) To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Cc: Maxime Ripard, Hans de Goede, Chris Ball, David Lanzendörfer, linux-mmc, devicetree, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On Mon, 2013-12-16 at 12:59 +0100, Michal Suchanek wrote: > On 16 December 2013 11:05, Maxime Ripard > <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: > > On Sun, Dec 15, 2013 at 11:01:17PM +0100, Michal Suchanek wrote: > >> On 15 December 2013 14:44, Maxime Ripard > >> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: > >> >> --- a/drivers/mmc/host/Kconfig > >> >> +++ b/drivers/mmc/host/Kconfig > >> >> @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI > >> >> help > >> >> Say Y here to include driver code to support SD/MMC card interface > >> >> of Realtek PCI-E card reader > >> >> + > >> >> +config MMC_SUNXI > >> >> + tristate "Allwinner sunxi SD/MMC Host Controller support" > >> >> + depends on ARCH_SUNXI > >> >> + default y > >> > > >> > I'm not that fond of these "default y" patterns. It forces the driver > >> > down to every user of the multiplatform kernels. I'd suggest removing > >> > the default and adding the driver to the defconfigs we have. > >> > >> And why would you build support for sunxi without building support for > >> sunxi mmc? > > > > Because you can? > > But does that need to be the default? And is that sane default? > > > > > And where am I actually suggesting to do so? > > Just a few lines above. You suggest it should not be built by default. I'm pretty sure this isn't specific to sunxi, in the past Linus has complained about the inappropriate use of "default y". Apparently it should only be used rarely. Note that default in the Kconfig is different to the defconfig file. Ian. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs [not found] ` <CAOMqctTdasLxJki0xu4aq_sEgujDt3Jdu=BXy9WvQeji282_Rg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2013-12-16 12:49 ` Ian Campbell @ 2013-12-16 12:53 ` Maxime Ripard 1 sibling, 0 replies; 31+ messages in thread From: Maxime Ripard @ 2013-12-16 12:53 UTC (permalink / raw) To: Michal Suchanek Cc: linux-sunxi, Hans de Goede, Chris Ball, David Lanzendörfer, linux-mmc, devicetree, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 1658 bytes --] On Mon, Dec 16, 2013 at 12:59:31PM +0100, Michal Suchanek wrote: > On 16 December 2013 11:05, Maxime Ripard > <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: > > On Sun, Dec 15, 2013 at 11:01:17PM +0100, Michal Suchanek wrote: > >> On 15 December 2013 14:44, Maxime Ripard > >> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote: > >> >> --- a/drivers/mmc/host/Kconfig > >> >> +++ b/drivers/mmc/host/Kconfig > >> >> @@ -665,3 +665,11 @@ config MMC_REALTEK_PCI > >> >> help > >> >> Say Y here to include driver code to support SD/MMC card interface > >> >> of Realtek PCI-E card reader > >> >> + > >> >> +config MMC_SUNXI > >> >> + tristate "Allwinner sunxi SD/MMC Host Controller support" > >> >> + depends on ARCH_SUNXI > >> >> + default y > >> > > >> > I'm not that fond of these "default y" patterns. It forces the driver > >> > down to every user of the multiplatform kernels. I'd suggest removing > >> > the default and adding the driver to the defconfigs we have. > >> > >> And why would you build support for sunxi without building support for > >> sunxi mmc? > > > > Because you can? > > But does that need to be the default? And is that sane default? > > > > > And where am I actually suggesting to do so? > > Just a few lines above. You suggest it should not be built by default. No, this is not what I'm saying. I'm saying that this default should be enforced at the defconfig level, and not at the Kconfig level. -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs 2013-12-15 13:44 ` Maxime Ripard 2013-12-15 14:20 ` Hans de Goede 2013-12-15 22:01 ` Michal Suchanek @ 2014-02-05 13:33 ` David Lanzendörfer 2 siblings, 0 replies; 31+ messages in thread From: David Lanzendörfer @ 2014-02-05 13:33 UTC (permalink / raw) To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Cc: Maxime Ripard, Hans de Goede, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-mmc-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball [-- Attachment #1: Type: text/plain, Size: 858 bytes --] Hi > I'm not that fond of these "default y" patterns. It forces the driver > down to every user of the multiplatform kernels. I'd suggest removing > the default and adding the driver to the defconfigs we have. Ok. Removed it. > > +static void sunxi_mmc_init_host(struct mmc_host *mmc) > > +{ > > [...] > > + mci_writel(smc_host, REG_FUNS, 0xceaa0000); > > + mci_writel(smc_host, REG_DLBA, smc_host->sg_dma); > I suppose we have no idea what these magics are all about ? :( That's the parameters I could extract from the Chinese code. Without proper documentation it will always stay magic what exactly these values are meaning. > > +#define mci_readl(host, reg) \ > > + __raw_readl((host)->reg_base + SDXC_##reg) > > +#define mci_writel(host, reg, value) \ > > + __raw_writel((value), (host)->reg_base + SDXC_##reg) > No barriers ? :( Fixed that... cheers [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs 2013-12-14 21:58 ` [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs Hans de Goede [not found] ` <1387058295-20641-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-17 13:43 ` Mark Brown 1 sibling, 0 replies; 31+ messages in thread From: Mark Brown @ 2013-12-17 13:43 UTC (permalink / raw) To: Hans de Goede Cc: Chris Ball, Maxime Ripard, devicetree, linux-mmc, linux-sunxi, David Lanzendörfer, linux-arm-kernel [-- Attachment #1: Type: text/plain, Size: 397 bytes --] On Sat, Dec 14, 2013 at 10:58:11PM +0100, Hans de Goede wrote: > +config MMC_SUNXI > + tristate "Allwinner sunxi SD/MMC Host Controller support" > + depends on ARCH_SUNXI This should be ARCH_SUNXI || COMPILE_TEST to increase build coverage especially for people doing subsystem or kernel global work. > + default y As others pointed out this shouldn't be here, consider multiplatform kernels. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 2/5] ARM: dts: sun4i: Add support for mmc [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-14 21:58 ` [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs Hans de Goede @ 2013-12-14 21:58 ` Hans de Goede [not found] ` <1387058295-20641-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-14 21:58 ` [PATCH 3/5] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board Hans de Goede ` (2 subsequent siblings) 4 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-14 21:58 UTC (permalink / raw) To: Chris Ball, Maxime Ripard Cc: David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hans de Goede Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> --- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 16 ++++++++++++++++ arch/arm/boot/dts/sun4i-a10.dtsi | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts index 425a7db..d193937 100644 --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts @@ -42,7 +42,23 @@ }; }; + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_cubieboard>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_cubieboard: led_pins@0 { allwinner,pins = "PH20", "PH21"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 4dccdb0..13bccd5 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -306,6 +306,15 @@ #size-cells = <0>; }; + sdc0: sdc@01c0f000 { + compatible = "allwinner,sun4i-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&ahb_gates 8>, <&mmc0>; + interrupts = <32>; + bus-width = <4>; + status = "disabled"; + }; + intc: interrupt-controller@01c20400 { compatible = "allwinner,sun4i-ic"; reg = <0x01c20400 0x400>; @@ -376,6 +385,13 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; + + sdc0_pins_a: sdc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; + allwinner,drive = <3>; + allwinner,pull = <1>; + }; }; timer@01c20c00 { -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 31+ messages in thread
[parent not found: <1387058295-20641-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc [not found] ` <1387058295-20641-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-15 13:58 ` Maxime Ripard 2013-12-15 14:31 ` Hans de Goede 0 siblings, 1 reply; 31+ messages in thread From: Maxime Ripard @ 2013-12-15 13:58 UTC (permalink / raw) To: Hans de Goede Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 2834 bytes --] Hi Hans, On Sat, Dec 14, 2013 at 10:58:12PM +0100, Hans de Goede wrote: > Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> Commit-log :) > --- > arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 16 ++++++++++++++++ > arch/arm/boot/dts/sun4i-a10.dtsi | 16 ++++++++++++++++ > 2 files changed, 32 insertions(+) > > diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts > index 425a7db..d193937 100644 > --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts > +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts > @@ -42,7 +42,23 @@ > }; > }; > > + sdc0: sdc@01c0f000 { > + pinctrl-names = "default"; > + pinctrl-0 = <&sdc0_pins_a>; > + pinctrl-1 = <&mmc0_cd_pin_cubieboard>; > + cd-gpios = <&pio 7 1 0>; /* PH1 */ > + cd-mode = <1>; > + status = "okay"; > + }; > + > pinctrl@01c20800 { > + mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 { > + allwinner,pins = "PH1"; > + allwinner,function = "gpio_in"; > + allwinner,drive = <0>; > + allwinner,pull = <0>; > + }; > + You seem to be using mmc and sdc without any real distinction. Please try to be consistent and use only one of the two (and I have a slight preference for mmc :)) > led_pins_cubieboard: led_pins@0 { > allwinner,pins = "PH20", "PH21"; > allwinner,function = "gpio_out"; > diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi > index 4dccdb0..13bccd5 100644 > --- a/arch/arm/boot/dts/sun4i-a10.dtsi > +++ b/arch/arm/boot/dts/sun4i-a10.dtsi > @@ -306,6 +306,15 @@ > #size-cells = <0>; > }; > > + sdc0: sdc@01c0f000 { > + compatible = "allwinner,sun4i-mmc"; > + reg = <0x01c0f000 0x1000>; > + clocks = <&ahb_gates 8>, <&mmc0>; > + interrupts = <32>; > + bus-width = <4>; > + status = "disabled"; > + }; > + The A10 has much more mmc controller doesn't it? Could you add all of them in the DT ? > intc: interrupt-controller@01c20400 { > compatible = "allwinner,sun4i-ic"; > reg = <0x01c20400 0x400>; > @@ -376,6 +385,13 @@ > allwinner,drive = <0>; > allwinner,pull = <0>; > }; > + > + sdc0_pins_a: sdc0@0 { > + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; > + allwinner,function = "mmc0"; > + allwinner,drive = <3>; > + allwinner,pull = <1>; Wow, you need both the pullups and a 40mA output? Ideally, I'd like this patch to be splitted into three: - One that adds the MMC controller nodes to the DTSI - One that adds the muxing options you need to the pinctrl node - One that enables the controller on the boards Thanks, Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc 2013-12-15 13:58 ` Maxime Ripard @ 2013-12-15 14:31 ` Hans de Goede 2013-12-15 21:44 ` [linux-sunxi] " Henrik Nordström [not found] ` <52ADBD41.4050104-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 0 siblings, 2 replies; 31+ messages in thread From: Hans de Goede @ 2013-12-15 14:31 UTC (permalink / raw) To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi, On 12/15/2013 02:58 PM, Maxime Ripard wrote: > Hi Hans, > > On Sat, Dec 14, 2013 at 10:58:12PM +0100, Hans de Goede wrote: >> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> > > Commit-log :) Heh. Note as said before I expect David to take things from here. > >> --- >> arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 16 ++++++++++++++++ >> arch/arm/boot/dts/sun4i-a10.dtsi | 16 ++++++++++++++++ >> 2 files changed, 32 insertions(+) >> >> diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts >> index 425a7db..d193937 100644 >> --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts >> +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts >> @@ -42,7 +42,23 @@ >> }; >> }; >> >> + sdc0: sdc@01c0f000 { >> + pinctrl-names = "default"; >> + pinctrl-0 = <&sdc0_pins_a>; >> + pinctrl-1 = <&mmc0_cd_pin_cubieboard>; >> + cd-gpios = <&pio 7 1 0>; /* PH1 */ >> + cd-mode = <1>; >> + status = "okay"; >> + }; >> + >> pinctrl@01c20800 { >> + mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 { >> + allwinner,pins = "PH1"; >> + allwinner,function = "gpio_in"; >> + allwinner,drive = <0>; >> + allwinner,pull = <0>; >> + }; >> + > > You seem to be using mmc and sdc without any real distinction. Please > try to be consistent and use only one of the two (and I have a slight > preference for mmc :)) I just took what David was using. I agree picking one and staying with it would be better. > >> led_pins_cubieboard: led_pins@0 { >> allwinner,pins = "PH20", "PH21"; >> allwinner,function = "gpio_out"; >> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi >> index 4dccdb0..13bccd5 100644 >> --- a/arch/arm/boot/dts/sun4i-a10.dtsi >> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi >> @@ -306,6 +306,15 @@ >> #size-cells = <0>; >> }; >> >> + sdc0: sdc@01c0f000 { >> + compatible = "allwinner,sun4i-mmc"; >> + reg = <0x01c0f000 0x1000>; >> + clocks = <&ahb_gates 8>, <&mmc0>; >> + interrupts = <32>; >> + bus-width = <4>; >> + status = "disabled"; >> + }; >> + > > The A10 has much more mmc controller doesn't it? Yes 4 of them. > Could you add all of them in the DT ? > >> intc: interrupt-controller@01c20400 { >> compatible = "allwinner,sun4i-ic"; >> reg = <0x01c20400 0x400>; >> @@ -376,6 +385,13 @@ >> allwinner,drive = <0>; >> allwinner,pull = <0>; >> }; >> + >> + sdc0_pins_a: sdc0@0 { >> + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; >> + allwinner,function = "mmc0"; >> + allwinner,drive = <3>; >> + allwinner,pull = <1>; > > Wow, you need both the pullups and a 40mA output? Yes and no. The pullups are enabled by uboot and the allwinner sources, most of my testing has been done without them, which seems to work fine. I've enabled them to be consisten with the allwinner sources and u-boot. As for drive = <3>, we need drive = <2> for normal modes, and drive = <3> for ddr mode. I simply picked <3> to keep things KISS. It should not matter much in power usage, as it will only make the flanks of the signal more steep. Once the desired output level is reached the current will drop off. It will use more current when changing the level, but for half the time, so the effective power usage (current * time) is the same. > Ideally, I'd like this patch to be splitted into three: > - One that adds the MMC controller nodes to the DTSI > - One that adds the muxing options you need to the pinctrl node > - One that enables the controller on the boards Sounds like a good job for David. Note I've a lot more boards for which I would like to add mmc support or dts files in general (will do so as time permits). For those boards which already have a dts I'll send mmc adding dts patches to David for now so he can add the changes to the patch-set. How do you want to deal with new boards ? Send the addition of the base board to you (and CC David as he will need them in his tree too), and then send a patch to add mmc to the dts to David ? Or should I simply make it one big patch including mmc in the initial commit ? Regards, Hans ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [linux-sunxi] Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc 2013-12-15 14:31 ` Hans de Goede @ 2013-12-15 21:44 ` Henrik Nordström [not found] ` <52ADBD41.4050104-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 1 sibling, 0 replies; 31+ messages in thread From: Henrik Nordström @ 2013-12-15 21:44 UTC (permalink / raw) To: linux-sunxi Cc: linux-mmc, Chris Ball, David Lanzendörfer, linux-arm-kernel, devicetree sön 2013-12-15 klockan 15:31 +0100 skrev Hans de Goede: > Yes and no. The pullups are enabled by uboot and the allwinner > sources, most of my testing has been done without them, which > seems to work fine. I've enabled them to be consisten with the > allwinner sources and u-boot. Many boards have external pullups where needed for the MMC bus. On such boards it's likely not a good idea to enable internal pullups. Regards Henrik _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <52ADBD41.4050104-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc [not found] ` <52ADBD41.4050104-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-16 9:04 ` David Lanzendörfer [not found] ` <11015171.YHkHMOrD9M-pgFh0Jf6HD9Xzn/AsuzBOg@public.gmane.org> 2013-12-16 10:02 ` Maxime Ripard 1 sibling, 1 reply; 31+ messages in thread From: David Lanzendörfer @ 2013-12-16 9:04 UTC (permalink / raw) To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Cc: Hans de Goede, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-mmc-u79uwXL29TY76Z2rM5mHXA, Chris Ball, devicetree-u79uwXL29TY76Z2rM5mHXA [-- Attachment #1: Type: text/plain, Size: 2291 bytes --] Hi > Note as said before I expect David to take things from here. I will start working on it this evening. > I just took what David was using. I agree picking one and staying with > it would be better. There is a reason why my working branch was called "plsdsif" (short for "Please don't shout at me in Finnish") > Yes and no. The pullups are enabled by uboot and the allwinner > sources, most of my testing has been done without them, which > seems to work fine. I've enabled them to be consisten with the > allwinner sources and u-boot. Ok > As for drive = <3>, we need drive = <2> for normal modes, > and drive = <3> for ddr mode. I simply picked <3> to keep > things KISS. It should not matter much in power usage, as > it will only make the flanks of the signal more steep. Once the > desired output level is reached the current will drop off. It will > use more current when changing the level, but for half the time, > so the effective power usage (current * time) is the same. In this case lets implement a switch which enables the pull ups for DDR mode and lets disable it by default in turn. This way we can make sure that we don't have doubled pull up, since this could actually mess up some circuitry. > > Ideally, I'd like this patch to be splitted into three: > > - One that adds the MMC controller nodes to the DTSI > > - One that adds the muxing options you need to the pinctrl node > > - One that enables the controller on the boards > Sounds like a good job for David. Note I've a lot more boards for > which I would like to add mmc support or dts files in general > (will do so as time permits). Ok. I will work on it this evening. > For those boards which already have a dts I'll send mmc adding dts > patches to David for now so he can add the changes to the patch-set. Ok. I will create another branch and will incorporate your DTS files. > How do you want to deal with new boards ? Send the addition of the > base board to you (and CC David as he will need them in his tree too), > and then send a patch to add mmc to the dts to David ? Sounds good to me... > Or should I simply make it one big patch including mmc in the initial > commit ? I imagine that a messy approach. Especially if I'm supposed to refactor the patchset into a new one... cheers [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <11015171.YHkHMOrD9M-pgFh0Jf6HD9Xzn/AsuzBOg@public.gmane.org>]
* Re: Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc [not found] ` <11015171.YHkHMOrD9M-pgFh0Jf6HD9Xzn/AsuzBOg@public.gmane.org> @ 2013-12-16 12:32 ` Hans de Goede 0 siblings, 0 replies; 31+ messages in thread From: Hans de Goede @ 2013-12-16 12:32 UTC (permalink / raw) To: David Lanzendörfer, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-mmc-u79uwXL29TY76Z2rM5mHXA, Chris Ball, devicetree-u79uwXL29TY76Z2rM5mHXA Hi, On 12/16/2013 10:04 AM, David Lanzendörfer wrote: <snip> >> Yes and no. The pullups are enabled by uboot and the allwinner >> sources, most of my testing has been done without them, which >> seems to work fine. I've enabled them to be consisten with the >> allwinner sources and u-boot. > Ok > >> As for drive = <3>, we need drive = <2> for normal modes, >> and drive = <3> for ddr mode. I simply picked <3> to keep >> things KISS. It should not matter much in power usage, as >> it will only make the flanks of the signal more steep. Once the >> desired output level is reached the current will drop off. It will >> use more current when changing the level, but for half the time, >> so the effective power usage (current * time) is the same. > In this case lets implement a switch which enables the pull ups for DDR > mode and lets disable it by default in turn. I assume you mean enable drive = <3> mode and use drive = <2> mode by default? Changing drive level at runtime, rather the at dts configure time seems to be non trivial. Also see Maxime's mail further down in this thread where he says he is fine with keeping drive level at <3> but suggest disabling the pull-ups by default. I'm fine with disabling the pull-ups by default, so lets disable the pull-ups and keep the drive level at 3. > This way we can make sure that we don't have doubled pull up, > since this could actually mess up some circuitry. > >>> Ideally, I'd like this patch to be splitted into three: >>> - One that adds the MMC controller nodes to the DTSI >>> - One that adds the muxing options you need to the pinctrl node >>> - One that enables the controller on the boards >> Sounds like a good job for David. Note I've a lot more boards for >> which I would like to add mmc support or dts files in general >> (will do so as time permits). > Ok. I will work on it this evening. > >> For those boards which already have a dts I'll send mmc adding dts >> patches to David for now so he can add the changes to the patch-set. > Ok. I will create another branch and will incorporate your DTS files. > >> How do you want to deal with new boards ? Send the addition of the >> base board to you (and CC David as he will need them in his tree too), >> and then send a patch to add mmc to the dts to David ? > Sounds good to me... In Maxime's reply I was talking about above he suggests to simply send complete dts files with the new mmc node present to him, so I'll do that instead if / when I add dts files for new boards. Regards, Hans -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/groups/opt_out. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc [not found] ` <52ADBD41.4050104-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-16 9:04 ` David Lanzendörfer @ 2013-12-16 10:02 ` Maxime Ripard 2013-12-16 12:34 ` Hans de Goede 1 sibling, 1 reply; 31+ messages in thread From: Maxime Ripard @ 2013-12-16 10:02 UTC (permalink / raw) To: Hans de Goede Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 2857 bytes --] Hi Hans, Damn google-groups removed me from Cc :) On Sun, Dec 15, 2013 at 03:31:29PM +0100, Hans de Goede wrote: > >>@@ -376,6 +385,13 @@ > >> allwinner,drive = <0>; > >> allwinner,pull = <0>; > >> }; > >>+ > >>+ sdc0_pins_a: sdc0@0 { > >>+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; > >>+ allwinner,function = "mmc0"; > >>+ allwinner,drive = <3>; > >>+ allwinner,pull = <1>; > > > >Wow, you need both the pullups and a 40mA output? > > Yes and no. The pullups are enabled by uboot and the allwinner > sources, most of my testing has been done without them, which > seems to work fine. I've enabled them to be consisten with the > allwinner sources and u-boot. Henrik was suggesting that in most boards it's not required to set up the internal pullups. Maybe we can just disable them by default, and we will always be able to enable them at the board level if needed. > As for drive = <3>, we need drive = <2> for normal modes, > and drive = <3> for ddr mode. I simply picked <3> to keep > things KISS. It should not matter much in power usage, as > it will only make the flanks of the signal more steep. Once the > desired output level is reached the current will drop off. It will > use more current when changing the level, but for half the time, > so the effective power usage (current * time) is the same. Ok, let's keep it to 40mA then. It will indeed be simpler :) > >Ideally, I'd like this patch to be splitted into three: > > - One that adds the MMC controller nodes to the DTSI > > - One that adds the muxing options you need to the pinctrl node > > - One that enables the controller on the boards > > Sounds like a good job for David. Note I've a lot more boards for > which I would like to add mmc support or dts files in general > (will do so as time permits). > > For those boards which already have a dts I'll send mmc adding dts > patches to David for now so he can add the changes to the patch-set. > > How do you want to deal with new boards ? Send the addition of the > base board to you (and CC David as he will need them in his tree too), > and then send a patch to add mmc to the dts to David ? I don't really like having a variable-sweep patch serie. Just send your DT additions to me, saying that you depend on the MMC serie from David. I'm pretty happy with the DT bindings so far, so we can even merge these DT patches before the MMC driver has been merged > Or should I simply make it one big patch including mmc in the initial > commit ? I really prefer to have patches as small as possible (while being reasonable). It's much easier to merge and allows to have a cleaner history. Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Re: [PATCH 2/5] ARM: dts: sun4i: Add support for mmc 2013-12-16 10:02 ` Maxime Ripard @ 2013-12-16 12:34 ` Hans de Goede 0 siblings, 0 replies; 31+ messages in thread From: Hans de Goede @ 2013-12-16 12:34 UTC (permalink / raw) To: Maxime Ripard Cc: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r Hi, On 12/16/2013 11:02 AM, Maxime Ripard wrote: > Hi Hans, > > Damn google-groups removed me from Cc :) > > On Sun, Dec 15, 2013 at 03:31:29PM +0100, Hans de Goede wrote: >>>> @@ -376,6 +385,13 @@ >>>> allwinner,drive = <0>; >>>> allwinner,pull = <0>; >>>> }; >>>> + >>>> + sdc0_pins_a: sdc0@0 { >>>> + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; >>>> + allwinner,function = "mmc0"; >>>> + allwinner,drive = <3>; >>>> + allwinner,pull = <1>; >>> >>> Wow, you need both the pullups and a 40mA output? >> >> Yes and no. The pullups are enabled by uboot and the allwinner >> sources, most of my testing has been done without them, which >> seems to work fine. I've enabled them to be consisten with the >> allwinner sources and u-boot. > > Henrik was suggesting that in most boards it's not required to set up > the internal pullups. Maybe we can just disable them by default, and > we will always be able to enable them at the board level if needed. Ok, I'm fine with disabling the pull-ups by default. >> As for drive = <3>, we need drive = <2> for normal modes, >> and drive = <3> for ddr mode. I simply picked <3> to keep >> things KISS. It should not matter much in power usage, as >> it will only make the flanks of the signal more steep. Once the >> desired output level is reached the current will drop off. It will >> use more current when changing the level, but for half the time, >> so the effective power usage (current * time) is the same. > > Ok, let's keep it to 40mA then. It will indeed be simpler :) Ack. > >>> Ideally, I'd like this patch to be splitted into three: >>> - One that adds the MMC controller nodes to the DTSI >>> - One that adds the muxing options you need to the pinctrl node >>> - One that enables the controller on the boards >> >> Sounds like a good job for David. Note I've a lot more boards for >> which I would like to add mmc support or dts files in general >> (will do so as time permits). >> >> For those boards which already have a dts I'll send mmc adding dts >> patches to David for now so he can add the changes to the patch-set. >> >> How do you want to deal with new boards ? Send the addition of the >> base board to you (and CC David as he will need them in his tree too), >> and then send a patch to add mmc to the dts to David ? > > I don't really like having a variable-sweep patch serie. Just send > your DT additions to me, saying that you depend on the MMC serie from > David. Ok will do if / when I've dts files for new boards. Regards, Hans ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 3/5] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-14 21:58 ` [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs Hans de Goede 2013-12-14 21:58 ` [PATCH 2/5] ARM: dts: sun4i: Add support for mmc Hans de Goede @ 2013-12-14 21:58 ` Hans de Goede [not found] ` <1387058295-20641-4-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-14 21:58 ` [PATCH 4/5] ARM: dts: sun5i: add mmc support Hans de Goede 2013-12-14 21:58 ` [PATCH 5/5] ARM: dts: sun7i: Add support for mmc Hans de Goede 4 siblings, 1 reply; 31+ messages in thread From: Hans de Goede @ 2013-12-14 21:58 UTC (permalink / raw) To: Chris Ball, Maxime Ripard Cc: David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hans de Goede Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 66 +++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d57c1a6..b663ed7 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -255,6 +255,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \ sun4i-a10-hackberry.dtb \ sun5i-a10s-olinuxino-micro.dtb \ sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb \ sun6i-a31-colombus.dtb \ sun7i-a20-cubieboard2.dtb \ sun7i-a20-cubietruck.dtb \ diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts new file mode 100644 index 0000000..26df7e8 --- /dev/null +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts @@ -0,0 +1,66 @@ +/* + * Copyright 2012 Maxime Ripard + * + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "sun5i-a13.dtsi" + +/ { + model = "Olimex A13-Olinuxino Micro"; + compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13"; + + soc@01c00000 { + pinctrl@01c20800 { + led_pins_olinuxinom: led_pins@0 { + allwinner,pins = "PG9"; + allwinner,function = "gpio_out"; + allwinner,drive = <1>; + allwinner,pull = <0>; + }; + }; + + uart1: serial@01c28400 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; + status = "okay"; + }; + + i2c0: i2c@01c2ac00 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + }; + + i2c1: i2c@01c2b000 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; + }; + + i2c2: i2c@01c2b400 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_olinuxinom>; + + power { + gpios = <&pio 6 9 0>; + default-state = "on"; + }; + }; +}; -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 31+ messages in thread
[parent not found: <1387058295-20641-4-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>]
* Re: [PATCH 3/5] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board [not found] ` <1387058295-20641-4-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> @ 2013-12-15 14:04 ` Maxime Ripard 0 siblings, 0 replies; 31+ messages in thread From: Maxime Ripard @ 2013-12-15 14:04 UTC (permalink / raw) To: Hans de Goede Cc: Chris Ball, David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r [-- Attachment #1: Type: text/plain, Size: 3345 bytes --] On Sat, Dec 14, 2013 at 10:58:13PM +0100, Hans de Goede wrote: > Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> Commit log :) Please detail what the board is, what features it has, etc. Other than that, I'm mostly ok with this patch (except that you can also probably add your copyright, but that's your call :)) Could you send it as a single patch, separate from this serie (since it's not really related in the end). Thanks! Maxime > --- > arch/arm/boot/dts/Makefile | 1 + > arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 66 +++++++++++++++++++++++++ > 2 files changed, 67 insertions(+) > create mode 100644 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts > > diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile > index d57c1a6..b663ed7 100644 > --- a/arch/arm/boot/dts/Makefile > +++ b/arch/arm/boot/dts/Makefile > @@ -255,6 +255,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \ > sun4i-a10-hackberry.dtb \ > sun5i-a10s-olinuxino-micro.dtb \ > sun5i-a13-olinuxino.dtb \ > + sun5i-a13-olinuxino-micro.dtb \ > sun6i-a31-colombus.dtb \ > sun7i-a20-cubieboard2.dtb \ > sun7i-a20-cubietruck.dtb \ > diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts > new file mode 100644 > index 0000000..26df7e8 > --- /dev/null > +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts > @@ -0,0 +1,66 @@ > +/* > + * Copyright 2012 Maxime Ripard > + * > + * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> > + * > + * The code contained herein is licensed under the GNU General Public > + * License. You may obtain a copy of the GNU General Public License > + * Version 2 or later at the following locations: > + * > + * http://www.opensource.org/licenses/gpl-license.html > + * http://www.gnu.org/copyleft/gpl.html > + */ > + > +/dts-v1/; > +/include/ "sun5i-a13.dtsi" > + > +/ { > + model = "Olimex A13-Olinuxino Micro"; > + compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13"; > + > + soc@01c00000 { > + pinctrl@01c20800 { > + led_pins_olinuxinom: led_pins@0 { > + allwinner,pins = "PG9"; > + allwinner,function = "gpio_out"; > + allwinner,drive = <1>; > + allwinner,pull = <0>; > + }; > + }; > + > + uart1: serial@01c28400 { > + pinctrl-names = "default"; > + pinctrl-0 = <&uart1_pins_b>; > + status = "okay"; > + }; > + > + i2c0: i2c@01c2ac00 { > + pinctrl-names = "default"; > + pinctrl-0 = <&i2c0_pins_a>; > + status = "okay"; > + }; > + > + i2c1: i2c@01c2b000 { > + pinctrl-names = "default"; > + pinctrl-0 = <&i2c1_pins_a>; > + status = "okay"; > + }; > + > + i2c2: i2c@01c2b400 { > + pinctrl-names = "default"; > + pinctrl-0 = <&i2c2_pins_a>; > + status = "okay"; > + }; > + }; > + > + leds { > + compatible = "gpio-leds"; > + pinctrl-names = "default"; > + pinctrl-0 = <&led_pins_olinuxinom>; > + > + power { Could you add a label here? Something like a13-olinuxino-micro:green:power ? > + gpios = <&pio 6 9 0>; > + default-state = "on"; > + }; > + }; > +}; Thanks! Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 4/5] ARM: dts: sun5i: add mmc support [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> ` (2 preceding siblings ...) 2013-12-14 21:58 ` [PATCH 3/5] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board Hans de Goede @ 2013-12-14 21:58 ` Hans de Goede 2013-12-14 21:58 ` [PATCH 5/5] ARM: dts: sun7i: Add support for mmc Hans de Goede 4 siblings, 0 replies; 31+ messages in thread From: Hans de Goede @ 2013-12-14 21:58 UTC (permalink / raw) To: Chris Ball, Maxime Ripard Cc: David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hans de Goede Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> --- arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 32 ++++++++++++++++++++++ arch/arm/boot/dts/sun5i-a10s.dtsi | 34 ++++++++++++++++++++++++ arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 16 +++++++++++ arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 16 +++++++++++ arch/arm/boot/dts/sun5i-a13.dtsi | 17 ++++++++++++ 5 files changed, 115 insertions(+) diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts index 3c9f8b3..e53fb12 100644 --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts @@ -34,7 +34,39 @@ }; }; + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxino_micro>; + cd-gpios = <&pio 6 1 0>; /* PG1 */ + cd-mode = <1>; + status = "okay"; + }; + + sdc1: sdc@01c10000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc1_pins_a>; + pinctrl-1 = <&mmc1_cd_pin_olinuxino_micro>; + cd-gpios = <&pio 6 13 0>; /* PG13 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_olinuxino_micro: mmc0_cd_pin@0 { + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 { + allwinner,pins = "PG13"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_olinuxino: led_pins@0 { allwinner,pins = "PE3"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 83e183c..fdbc290 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -274,6 +274,26 @@ #size-cells = <0>; }; + sdc0: sdc@01c0f000 { + compatible = "allwinner,sun5i-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&ahb_gates 8>, <&mmc0>; + clock-names = "ahb", "mod"; + interrupts = <32>; + bus-width = <4>; + status = "disabled"; + }; + + sdc1: sdc@01c10000 { + compatible = "allwinner,sun5i-mmc"; + reg = <0x01c10000 0x1000>; + clocks = <&ahb_gates 9>, <&mmc1>; + clock-names = "ahb", "mod"; + interrupts = <33>; + bus-width = <4>; + status = "disabled"; + }; + intc: interrupt-controller@01c20400 { compatible = "allwinner,sun4i-ic"; reg = <0x01c20400 0x400>; @@ -344,6 +364,20 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; + + sdc0_pins_a: sdc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; + allwinner,drive = <3>; + allwinner,pull = <1>; + }; + + sdc1_pins_a: sdc1@0 { + allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8"; + allwinner,function = "mmc1"; + allwinner,drive = <3>; + allwinner,pull = <1>; + }; }; timer@01c20c00 { diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts index 26df7e8..247cd79 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts @@ -19,7 +19,23 @@ compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13"; soc@01c00000 { + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxinom>; + cd-gpios = <&pio 6 0 0>; /* PG0 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_olinuxinom: led_pins@0 { allwinner,pins = "PG9"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts index 9e508dc..ce22c81 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts @@ -23,7 +23,23 @@ }; soc@01c00000 { + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxino>; + cd-gpios = <&pio 6 0 0>; /* PG0 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_olinuxino: led_pins@0 { allwinner,pins = "PG9"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index 0bb4300..0ca0819 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -255,6 +255,16 @@ #size-cells = <1>; ranges; + sdc0: sdc@01c0f000 { + compatible = "allwinner,sun5i-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&ahb_gates 8>, <&mmc0>; + clock-names = "ahb", "mod"; + interrupts = <32>; + bus-width = <4>; + status = "disabled"; + }; + intc: interrupt-controller@01c20400 { compatible = "allwinner,sun4i-ic"; reg = <0x01c20400 0x400>; @@ -307,6 +317,13 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; + + sdc0_pins_a: sdc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; + allwinner,drive = <3>; + allwinner,pull = <1>; + }; }; timer@01c20c00 { -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 5/5] ARM: dts: sun7i: Add support for mmc [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> ` (3 preceding siblings ...) 2013-12-14 21:58 ` [PATCH 4/5] ARM: dts: sun5i: add mmc support Hans de Goede @ 2013-12-14 21:58 ` Hans de Goede 4 siblings, 0 replies; 31+ messages in thread From: Hans de Goede @ 2013-12-14 21:58 UTC (permalink / raw) To: Chris Ball, Maxime Ripard Cc: David Lanzendörfer, linux-mmc-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Hans de Goede Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> --- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 16 ++++++++++++ arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 16 ++++++++++++ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 32 +++++++++++++++++++++++ arch/arm/boot/dts/sun7i-a20.dtsi | 34 +++++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts index 5c51cb8..6aef299 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -34,7 +34,23 @@ }; }; + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_cubieboard2>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_cubieboard2: led_pins@0 { allwinner,pins = "PH20", "PH21"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 8a1009d..302c785 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -19,7 +19,23 @@ compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; soc@01c00000 { + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_cubietruck>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_cubietruck: led_pins@0 { allwinner,pins = "PH7", "PH11", "PH20", "PH21"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts index ead3013..f271db9 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -34,7 +34,39 @@ }; }; + sdc0: sdc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxinom>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-mode = <1>; + status = "okay"; + }; + + sdc3: sdc@01c12000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdc3_pins_a>; + pinctrl-1 = <&mmc3_cd_pin_olinuxinom>; + cd-gpios = <&pio 7 11 0>; /* PH11 */ + cd-mode = <1>; + status = "okay"; + }; + pinctrl@01c20800 { + mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 { + allwinner,pins = "PH11"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + led_pins_olinuxino: led_pins@0 { allwinner,pins = "PH2"; allwinner,function = "gpio_out"; diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 0552a64..4416cac 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -303,6 +303,26 @@ #size-cells = <0>; }; + sdc0: sdc@01c0f000 { + compatible = "allwinner,sun5i-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&ahb_gates 8>, <&mmc0>; + clock-names = "ahb", "mod"; + interrupts = <0 32 4>; + bus-width = <4>; + status = "disabled"; + }; + + sdc3: sdc@01c12000 { + compatible = "allwinner,sun5i-mmc"; + reg = <0x01c12000 0x1000>; + clocks = <&ahb_gates 11>, <&mmc3>; + clock-names = "ahb", "mod"; + interrupts = <0 35 4>; + bus-width = <4>; + status = "disabled"; + }; + pio: pinctrl@01c20800 { compatible = "allwinner,sun7i-a20-pinctrl"; reg = <0x01c20800 0x400>; @@ -366,6 +386,20 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; + + sdc0_pins_a: sdc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; + allwinner,drive = <3>; + allwinner,pull = <1>; + }; + + sdc3_pins_a: sdc3@0 { + allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9"; + allwinner,function = "mmc3"; + allwinner,drive = <3>; + allwinner,pull = <1>; + }; }; timer@01c20c00 { -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 31+ messages in thread
end of thread, other threads:[~2014-02-05 13:33 UTC | newest] Thread overview: 31+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-12-14 21:58 [PATCH 0/5] ARM: sunxi: Add driver for SD/MMC hosts found on allwinner sunxi SOCs Hans de Goede [not found] ` <1387058295-20641-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-14 21:58 ` [PATCH 1/5] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs Hans de Goede [not found] ` <1387058295-20641-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 13:44 ` Maxime Ripard 2013-12-15 14:20 ` Hans de Goede [not found] ` <52ADBAA3.7060507-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 16:21 ` Maxime Ripard 2013-12-15 18:41 ` Hans de Goede [not found] ` <52ADF7D8.2010900-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 19:35 ` David Lanzendörfer [not found] ` <2378731.6b9MyH8v8A-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org> 2013-12-15 20:18 ` Hans de Goede [not found] ` <52AE0E87.2040304-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 21:19 ` David Lanzendörfer [not found] ` <1743952.noztKtcF2Y-GPtPHOohwlnjSbz6xCtQhw@public.gmane.org> 2013-12-16 12:21 ` Hans de Goede [not found] ` <52AEF060.6000405-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-23 10:36 ` David Lanzendörfer 2013-12-15 16:33 ` David Lanzendörfer 2013-12-15 22:01 ` Michal Suchanek [not found] ` <CAOMqctRspBPmNsyXye_gpfwGoZ=gMcCzEjM+hD3g+ZfQix7G6Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2013-12-16 10:05 ` Maxime Ripard 2013-12-16 11:59 ` Michal Suchanek [not found] ` <CAOMqctTdasLxJki0xu4aq_sEgujDt3Jdu=BXy9WvQeji282_Rg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2013-12-16 12:49 ` Ian Campbell 2013-12-16 12:53 ` Maxime Ripard 2014-02-05 13:33 ` David Lanzendörfer 2013-12-17 13:43 ` Mark Brown 2013-12-14 21:58 ` [PATCH 2/5] ARM: dts: sun4i: Add support for mmc Hans de Goede [not found] ` <1387058295-20641-3-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 13:58 ` Maxime Ripard 2013-12-15 14:31 ` Hans de Goede 2013-12-15 21:44 ` [linux-sunxi] " Henrik Nordström [not found] ` <52ADBD41.4050104-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-16 9:04 ` David Lanzendörfer [not found] ` <11015171.YHkHMOrD9M-pgFh0Jf6HD9Xzn/AsuzBOg@public.gmane.org> 2013-12-16 12:32 ` Hans de Goede 2013-12-16 10:02 ` Maxime Ripard 2013-12-16 12:34 ` Hans de Goede 2013-12-14 21:58 ` [PATCH 3/5] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board Hans de Goede [not found] ` <1387058295-20641-4-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2013-12-15 14:04 ` Maxime Ripard 2013-12-14 21:58 ` [PATCH 4/5] ARM: dts: sun5i: add mmc support Hans de Goede 2013-12-14 21:58 ` [PATCH 5/5] ARM: dts: sun7i: Add support for mmc Hans de Goede
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).