* [PATCH 0/4] BCM283x sdhost driver @ 2019-04-27 18:36 Lucas Stach 2019-04-27 18:36 ` [PATCH 1/4] mci: add driver for BCM283x sdhost core Lucas Stach ` (3 more replies) 0 siblings, 4 replies; 7+ messages in thread From: Lucas Stach @ 2019-04-27 18:36 UTC (permalink / raw) To: barebox It's a rainy day and someone asked for it on the mailing list, so here it is: This series adds the driver for the BCM283x sdhost controller, ported from U-Boot, and enables it on the Raspberry Pi 3. Have fun, Lucas Lucas Stach (4): mci: add driver for BCM283x sdhost core ARM: rpi: add clock for sdhost ARM: rpi: enable sdhost driver in defconfig ARM: rpi3: remove swapped sdhci and sdhost arch/arm/boards/raspberry-pi/rpi-common.c | 8 + arch/arm/configs/rpi_defconfig | 2 +- arch/arm/dts/bcm2837-rpi-3.dts | 5 - drivers/mci/Kconfig | 4 + drivers/mci/Makefile | 1 + drivers/mci/bcm2835-sdhost.c | 657 ++++++++++++++++++++++ 6 files changed, 671 insertions(+), 6 deletions(-) create mode 100644 drivers/mci/bcm2835-sdhost.c -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] mci: add driver for BCM283x sdhost core 2019-04-27 18:36 [PATCH 0/4] BCM283x sdhost driver Lucas Stach @ 2019-04-27 18:36 ` Lucas Stach 2019-04-29 7:42 ` Sascha Hauer 2019-04-27 18:36 ` [PATCH 2/4] ARM: rpi: add clock for sdhost Lucas Stach ` (2 subsequent siblings) 3 siblings, 1 reply; 7+ messages in thread From: Lucas Stach @ 2019-04-27 18:36 UTC (permalink / raw) To: barebox The sdhost is a simple MMC controller found on the Broadcom BCM283x line of SoCs. The driver code was ported from U-Boot and then simplified a bit, by dropping a lot of the state tracking. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> --- drivers/mci/Kconfig | 4 + drivers/mci/Makefile | 1 + drivers/mci/bcm2835-sdhost.c | 657 +++++++++++++++++++++++++++++++++++ 3 files changed, 662 insertions(+) create mode 100644 drivers/mci/bcm2835-sdhost.c diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 911cc0cb1e..08c8c84e8c 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -66,6 +66,10 @@ config MCI_BCM283X bool "MCI support for BCM283X" depends on ARCH_BCM283X +config MCI_BCM283X_SDHOST + bool "BCM283X sdhost" + depends on ARCH_BCM283X + config MCI_DOVE bool "Marvell Dove SDHCI" depends on ARCH_DOVE diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index f6214c0cbb..25a1d073dc 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_MCI) += mci-core.o obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o +obj-$(CONFIG_MCI_BCM283X_SDHOST) += bcm2835-sdhost.o obj-$(CONFIG_MCI_DOVE) += dove-sdhci.o obj-$(CONFIG_MCI_IMX) += imx.o obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o diff --git a/drivers/mci/bcm2835-sdhost.c b/drivers/mci/bcm2835-sdhost.c new file mode 100644 index 0000000000..bad155e07d --- /dev/null +++ b/drivers/mci/bcm2835-sdhost.c @@ -0,0 +1,657 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This code is ported from U-Boot by Lucas Stach <l.stach@pengutronix.de> and + * has the following contributors listed in the original license header: + * Alexander Graf <agraf@suse.de> + * Phil Elwell <phil@raspberrypi.org> + * Gellert Weisz + * Stephen Warren + * Oleksandr Tymoshenko + */ + +#include <clock.h> +#include <common.h> +#include <driver.h> +#include <init.h> +#include <linux/clk.h> +#include <linux/iopoll.h> +#include <linux/log2.h> +#include <mci.h> + +#define SDCMD 0x00 /* Command to SD card - 16 R/W */ +#define SDARG 0x04 /* Argument to SD card - 32 R/W */ +#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ +#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ +#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ +#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */ +#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */ +#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ +#define SDHSTS 0x20 /* SD host status - 11 R/W */ +#define SDVDD 0x30 /* SD card power control - 1 R/W */ +#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ +#define SDHCFG 0x38 /* Host configuration - 2 R/W */ +#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ +#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ +#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ + +#define SDCMD_NEW_FLAG 0x8000 +#define SDCMD_FAIL_FLAG 0x4000 +#define SDCMD_BUSYWAIT 0x800 +#define SDCMD_NO_RESPONSE 0x400 +#define SDCMD_LONG_RESPONSE 0x200 +#define SDCMD_WRITE_CMD 0x80 +#define SDCMD_READ_CMD 0x40 +#define SDCMD_CMD_MASK 0x3f + +#define SDCDIV_MAX_CDIV 0x7ff + +#define SDHSTS_BUSY_IRPT 0x400 +#define SDHSTS_BLOCK_IRPT 0x200 +#define SDHSTS_SDIO_IRPT 0x100 +#define SDHSTS_REW_TIME_OUT 0x80 +#define SDHSTS_CMD_TIME_OUT 0x40 +#define SDHSTS_CRC16_ERROR 0x20 +#define SDHSTS_CRC7_ERROR 0x10 +#define SDHSTS_FIFO_ERROR 0x08 +#define SDHSTS_DATA_FLAG 0x01 + +#define SDHSTS_CLEAR_MASK (SDHSTS_BUSY_IRPT | \ + SDHSTS_BLOCK_IRPT | \ + SDHSTS_SDIO_IRPT | \ + SDHSTS_REW_TIME_OUT | \ + SDHSTS_CMD_TIME_OUT | \ + SDHSTS_CRC16_ERROR | \ + SDHSTS_CRC7_ERROR | \ + SDHSTS_FIFO_ERROR) + +#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC7_ERROR | \ + SDHSTS_CRC16_ERROR | \ + SDHSTS_REW_TIME_OUT | \ + SDHSTS_FIFO_ERROR) + +#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT | \ + SDHSTS_TRANSFER_ERROR_MASK) + +#define SDHCFG_BUSY_IRPT_EN BIT(10) +#define SDHCFG_BLOCK_IRPT_EN BIT(8) +#define SDHCFG_SDIO_IRPT_EN BIT(5) +#define SDHCFG_DATA_IRPT_EN BIT(4) +#define SDHCFG_SLOW_CARD BIT(3) +#define SDHCFG_WIDE_EXT_BUS BIT(2) +#define SDHCFG_WIDE_INT_BUS BIT(1) +#define SDHCFG_REL_CMD_LINE BIT(0) + +#define SDVDD_POWER_OFF 0 +#define SDVDD_POWER_ON 1 + +#define SDEDM_FORCE_DATA_MODE BIT(19) +#define SDEDM_CLOCK_PULSE BIT(20) +#define SDEDM_BYPASS BIT(21) + +#define SDEDM_FIFO_FILL_SHIFT 4 +#define SDEDM_FIFO_FILL_MASK 0x1f +static u32 edm_fifo_fill(u32 edm) +{ + return (edm >> SDEDM_FIFO_FILL_SHIFT) & SDEDM_FIFO_FILL_MASK; +} + +#define SDEDM_WRITE_THRESHOLD_SHIFT 9 +#define SDEDM_READ_THRESHOLD_SHIFT 14 +#define SDEDM_THRESHOLD_MASK 0x1f + +#define SDEDM_FSM_MASK 0xf +#define SDEDM_FSM_IDENTMODE 0x0 +#define SDEDM_FSM_DATAMODE 0x1 +#define SDEDM_FSM_READDATA 0x2 +#define SDEDM_FSM_WRITEDATA 0x3 +#define SDEDM_FSM_READWAIT 0x4 +#define SDEDM_FSM_READCRC 0x5 +#define SDEDM_FSM_WRITECRC 0x6 +#define SDEDM_FSM_WRITEWAIT1 0x7 +#define SDEDM_FSM_POWERDOWN 0x8 +#define SDEDM_FSM_POWERUP 0x9 +#define SDEDM_FSM_WRITESTART1 0xa +#define SDEDM_FSM_WRITESTART2 0xb +#define SDEDM_FSM_GENPULSES 0xc +#define SDEDM_FSM_WRITEWAIT2 0xd +#define SDEDM_FSM_STARTPOWDOWN 0xf + +#define SDDATA_FIFO_WORDS 16 + +#define FIFO_READ_THRESHOLD 4 +#define FIFO_WRITE_THRESHOLD 4 +#define SDDATA_FIFO_PIO_BURST 8 + +#define SDHST_TIMEOUT_MAX_USEC 100000 + +struct bcm2835_host { + struct mci_host mci; + void __iomem *regs; + struct clk *clk; +}; +#define to_bcm2835_host(mci) container_of(mci, struct bcm2835_host, mci) + +static int bcm2835_sdhost_init(struct mci_host *mci, struct device_d *dev) +{ + struct bcm2835_host *host = to_bcm2835_host(mci); + u32 temp; + + writel(SDVDD_POWER_OFF, host->regs + SDVDD); + writel(0, host->regs + SDCMD); + writel(0, host->regs + SDARG); + /* Set timeout to a big enough value so we don't hit it */ + writel(0xf00000, host->regs + SDTOUT); + writel(0, host->regs + SDCDIV); + /* Clear status register */ + writel(SDHSTS_CLEAR_MASK, host->regs + SDHSTS); + writel(0, host->regs + SDHCFG); + writel(0, host->regs + SDHBCT); + writel(0, host->regs + SDHBLC); + + /* Limit fifo usage due to silicon bug */ + temp = readl(host->regs + SDEDM); + temp &= ~((SDEDM_THRESHOLD_MASK << SDEDM_READ_THRESHOLD_SHIFT) | + (SDEDM_THRESHOLD_MASK << SDEDM_WRITE_THRESHOLD_SHIFT)); + temp |= (FIFO_READ_THRESHOLD << SDEDM_READ_THRESHOLD_SHIFT) | + (FIFO_WRITE_THRESHOLD << SDEDM_WRITE_THRESHOLD_SHIFT); + writel(temp, host->regs + SDEDM); + /* Wait for FIFO threshold to populate */ + mdelay(20); + writel(SDVDD_POWER_ON, host->regs + SDVDD); + /* Wait for all components to go through power on cycle */ + mdelay(20); + writel(0, host->regs + SDHCFG); + writel(0, host->regs + SDCDIV); + + return 0; +} + +static int bcm2835_wait_transfer_complete(struct bcm2835_host *host) +{ + uint64_t start = get_time_ns(); + + while (1) { + u32 edm, fsm; + + edm = readl(host->regs + SDEDM); + fsm = edm & SDEDM_FSM_MASK; + + if ((fsm == SDEDM_FSM_IDENTMODE) || + (fsm == SDEDM_FSM_DATAMODE)) + break; + + if ((fsm == SDEDM_FSM_READWAIT) || + (fsm == SDEDM_FSM_WRITESTART1) || + (fsm == SDEDM_FSM_READDATA)) { + writel(edm | SDEDM_FORCE_DATA_MODE, + host->regs + SDEDM); + break; + } + + /* Error out after 1 second */ + if (is_timeout(start, 1 * SECOND)) { + dev_err(host->mci.hw_dev, + "wait_transfer_complete - still waiting 1s\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int bcm2835_transfer_block_pio(struct bcm2835_host *host, + struct mci_data *data, bool is_read) +{ + size_t blksize = data->blocksize; + int copy_words; + u32 hsts = 0; + u32 *buf; + + if (blksize % sizeof(u32)) + return -EINVAL; + + buf = is_read ? (u32 *)data->dest : (u32 *)data->src; + + if (is_read) + data->dest += blksize; + else + data->src += blksize; + + copy_words = blksize / sizeof(u32); + + /* + * Copy all contents from/to the FIFO as far as it reaches, + * then wait for it to fill/empty again and rewind. + */ + while (copy_words) { + int burst_words, words; + u32 edm; + + burst_words = min(SDDATA_FIFO_PIO_BURST, copy_words); + edm = readl(host->regs + SDEDM); + if (is_read) + words = edm_fifo_fill(edm); + else + words = SDDATA_FIFO_WORDS - edm_fifo_fill(edm); + + if (words < burst_words) { + int fsm_state = (edm & SDEDM_FSM_MASK); + + if ((is_read && + (fsm_state != SDEDM_FSM_READDATA && + fsm_state != SDEDM_FSM_READWAIT && + fsm_state != SDEDM_FSM_READCRC)) || + (!is_read && + (fsm_state != SDEDM_FSM_WRITEDATA && + fsm_state != SDEDM_FSM_WRITEWAIT1 && + fsm_state != SDEDM_FSM_WRITEWAIT2 && + fsm_state != SDEDM_FSM_WRITECRC && + fsm_state != SDEDM_FSM_WRITESTART1 && + fsm_state != SDEDM_FSM_WRITESTART2))) { + hsts = readl(host->regs + SDHSTS); + printf("fsm %x, hsts %08x\n", fsm_state, hsts); + if (hsts & SDHSTS_ERROR_MASK) + break; + } + + continue; + } else if (words > copy_words) { + words = copy_words; + } + + copy_words -= words; + + /* Copy current chunk to/from the FIFO */ + while (words) { + if (is_read) + *(buf++) = readl(host->regs + SDDATA); + else + writel(*(buf++), host->regs + SDDATA); + words--; + } + } + + return 0; +} + +static int bcm2835_transfer_pio(struct bcm2835_host *host, + struct mci_data *data) +{ + u32 sdhsts; + bool is_read = !!(data->flags & MMC_DATA_READ); + int ret = 0; + + ret = bcm2835_transfer_block_pio(host, data, is_read); + if (ret) + return ret; + + sdhsts = readl(host->regs + SDHSTS); + if (sdhsts & (SDHSTS_CRC16_ERROR | + SDHSTS_CRC7_ERROR | + SDHSTS_FIFO_ERROR)) { + printf("%s transfer error - HSTS %08x\n", + is_read ? "read" : "write", sdhsts); + ret = -EILSEQ; + } else if ((sdhsts & (SDHSTS_CMD_TIME_OUT | + SDHSTS_REW_TIME_OUT))) { + printf("%s timeout error - HSTS %08x\n", + is_read ? "read" : "write", sdhsts); + ret = -ETIMEDOUT; + } + + return ret; +} + +static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host) +{ + u32 value; + int ret; + int timeout_us = SDHST_TIMEOUT_MAX_USEC; + + ret = readl_poll_timeout(host->regs + SDCMD, value, + !(value & SDCMD_NEW_FLAG), timeout_us); + if (ret == -ETIMEDOUT) + printf("%s: timeout (%d us)\n", __func__, timeout_us); + + return value; +} + +static int bcm2835_send_command(struct bcm2835_host *host, struct mci_cmd *cmd, + struct mci_data *data) +{ + u32 sdcmd, sdhsts; + + if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) { + printf("unsupported response type!\n"); + return -EINVAL; + } + + sdcmd = bcm2835_read_wait_sdcmd(host); + if (sdcmd & SDCMD_NEW_FLAG) { + printf("previous command never completed.\n"); + return -EBUSY; + } + + /* Clear any error flags */ + sdhsts = readl(host->regs + SDHSTS); + if (sdhsts & SDHSTS_ERROR_MASK) + writel(sdhsts, host->regs + SDHSTS); + + if (data) { + writel(data->blocksize, host->regs + SDHBCT); + writel(data->blocks, host->regs + SDHBLC); + } + + writel(cmd->cmdarg, host->regs + SDARG); + + sdcmd = cmd->cmdidx & SDCMD_CMD_MASK; + + if (!(cmd->resp_type & MMC_RSP_PRESENT)) { + sdcmd |= SDCMD_NO_RESPONSE; + } else { + if (cmd->resp_type & MMC_RSP_136) + sdcmd |= SDCMD_LONG_RESPONSE; + if (cmd->resp_type & MMC_RSP_BUSY) { + sdcmd |= SDCMD_BUSYWAIT; + } + } + + if (data) { + if (data->flags & MMC_DATA_WRITE) + sdcmd |= SDCMD_WRITE_CMD; + if (data->flags & MMC_DATA_READ) + sdcmd |= SDCMD_READ_CMD; + } + + writel(sdcmd | SDCMD_NEW_FLAG, host->regs + SDCMD); + + return 0; +} + +static int bcm2835_finish_command(struct bcm2835_host *host, + struct mci_cmd *cmd) +{ + u32 sdcmd; + int ret = 0; + + sdcmd = bcm2835_read_wait_sdcmd(host); + + /* Check for errors */ + if (sdcmd & SDCMD_NEW_FLAG) { + printf("command never completed.\n"); + return -EIO; + } else if (sdcmd & SDCMD_FAIL_FLAG) { + u32 sdhsts = readl(host->regs + SDHSTS); + + /* Clear the errors */ + writel(SDHSTS_ERROR_MASK, host->regs + SDHSTS); + + if (!(sdhsts & SDHSTS_CRC7_ERROR) || + (cmd->cmdidx != MMC_CMD_SEND_OP_COND)) { + if (sdhsts & SDHSTS_CMD_TIME_OUT) { + ret = -ETIMEDOUT; + } else { + printf("unexpected command %d error\n", + cmd->cmdidx); + ret = -EILSEQ; + } + + return ret; + } + } + + if (cmd->resp_type & MMC_RSP_PRESENT) { + if (cmd->resp_type & MMC_RSP_136) { + int i; + + for (i = 0; i < 4; i++) { + cmd->response[3 - i] = + readl(host->regs + SDRSP0 + i * 4); + } + } else { + cmd->response[0] = readl(host->regs + SDRSP0); + } + } + + return ret; +} + +static int bcm2835_check_cmd_error(struct bcm2835_host *host, u32 intmask) +{ + int ret = -EINVAL; + + if (!(intmask & SDHSTS_ERROR_MASK)) + return 0; + + printf("sdhost_busy_irq: intmask %08x\n", intmask); + if (intmask & SDHSTS_CRC7_ERROR) { + ret = -EILSEQ; + } else if (intmask & (SDHSTS_CRC16_ERROR | + SDHSTS_FIFO_ERROR)) { + ret = -EILSEQ; + } else if (intmask & (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT)) { + ret = -ETIMEDOUT; + } + + return ret; +} + +static int bcm2835_check_data_error(struct bcm2835_host *host, u32 intmask) +{ + int ret = 0; + + if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_FIFO_ERROR)) + ret = -EILSEQ; + if (intmask & SDHSTS_REW_TIME_OUT) + ret = -ETIMEDOUT; + + if (ret) + printf("%s:%d %d\n", __func__, __LINE__, ret); + + return ret; +} + +static int bcm2835_transmit(struct bcm2835_host *host, struct mci_cmd *cmd, + struct mci_data *data) +{ + u32 intmask = readl(host->regs + SDHSTS); + int ret; + + /* Check for errors */ + if (data) { + ret = bcm2835_check_data_error(host, intmask); + if (ret) + return ret; + } + + ret = bcm2835_check_cmd_error(host, intmask); + if (ret) + return ret; + + /* Handle wait for busy end */ + if ((cmd && (cmd->resp_type & MMC_RSP_BUSY)) && + (intmask & SDHSTS_BUSY_IRPT)) { + writel(SDHSTS_BUSY_IRPT, host->regs + SDHSTS); + bcm2835_finish_command(host, cmd); + } + + /* Handle PIO data transfer */ + while (data && data->blocks) { + ret = bcm2835_transfer_pio(host, data); + if (ret) + break; + data->blocks--; + } + + /* Transfer successful: wait for command to complete for real */ + if (!ret) + ret = bcm2835_wait_transfer_complete(host); + + return ret; +} + +static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) +{ + int div; + + /* The SDCDIV register has 11 bits, and holds (div - 2). But + * in data mode the max is 50MHz wihout a minimum, and only + * the bottom 3 bits are used. Since the switch over is + * automatic (unless we have marked the card as slow...), + * chosen values have to make sense in both modes. Ident mode + * must be 100-400KHz, so can range check the requested + * clock. CMD15 must be used to return to data mode, so this + * can be monitored. + * + * clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz + * 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz + * + * 623->400KHz/27.8MHz + * reset value (507)->491159/50MHz + * + * BUT, the 3-bit clock divisor in data mode is too small if + * the core clock is higher than 250MHz, so instead use the + * SLOW_CARD configuration bit to force the use of the ident + * clock divisor at all times. + */ + + if (clock < 100000) { + /* Can't stop the clock, but make it as slow as possible + * to show willing + */ + writel(SDCDIV_MAX_CDIV, host->regs + SDCDIV); + return; + } + + div = host->mci.f_max / clock; + if (div < 2) + div = 2; + if ((host->mci.f_max / div) > clock) + div++; + div -= 2; + + if (div > SDCDIV_MAX_CDIV) + div = SDCDIV_MAX_CDIV; + + clock = host->mci.f_max / (div + 2); + + writel(div, host->regs + SDCDIV); + + /* Set the timeout to 500ms */ + writel(clock / 2, host->regs + SDTOUT); +} + +static int bcm2835_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, + struct mci_data *data) +{ + struct bcm2835_host *host = to_bcm2835_host(mci); + u32 edm, fsm; + int ret = 0; + + if (data && !is_power_of_2(data->blocksize)) { + printf("unsupported block size (%d bytes)\n", data->blocksize); + + if (cmd) + return -EINVAL; + } + + edm = readl(host->regs + SDEDM); + fsm = edm & SDEDM_FSM_MASK; + + if ((fsm != SDEDM_FSM_IDENTMODE) && + (fsm != SDEDM_FSM_DATAMODE) && + (cmd && cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) { + printf("previous command (%d) not complete (EDM %08x)\n", + readl(host->regs + SDCMD) & SDCMD_CMD_MASK, edm); + + if (cmd) + return -EILSEQ; + + return 0; + } + + if (cmd) { + ret = bcm2835_send_command(host, cmd, data); + if (!ret && !(cmd->resp_type & MMC_RSP_BUSY)) + ret = bcm2835_finish_command(host, cmd); + } + + /* Wait for completion of busy signal or data transfer */ + if ((cmd && (cmd->resp_type & MMC_RSP_BUSY)) || data) + ret = bcm2835_transmit(host, cmd, data); + + return ret; +} + +static void bcm2835_set_ios(struct mci_host *mci, struct mci_ios *ios) +{ + struct bcm2835_host *host = to_bcm2835_host(mci); + u32 hcfg = SDHCFG_WIDE_INT_BUS | SDHCFG_SLOW_CARD; + + if (ios->clock) + bcm2835_set_clock(host, ios->clock); + + /* set bus width */ + if (ios->bus_width == MMC_BUS_WIDTH_4) + hcfg |= SDHCFG_WIDE_EXT_BUS; + + writel(hcfg, host->regs + SDHCFG); +} + +static int bcm2835_sdhost_detect(struct device_d *dev) +{ + struct bcm2835_host *host = dev->priv; + + return mci_detect_card(&host->mci); +} + +static int bcm2835_sdhost_probe(struct device_d *dev) +{ + struct bcm2835_host *host; + struct resource *iores; + struct mci_host *mci; + + host = xzalloc(sizeof(*host)); + mci = &host->mci; + + host->clk = clk_get(dev, NULL); + if (IS_ERR(host->clk)) + return PTR_ERR(host->clk); + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) { + dev_err(dev, "could not get iomem region\n"); + return PTR_ERR(iores); + } + host->regs = IOMEM(iores->start); + + mci->hw_dev = dev; + mci->f_max = clk_get_rate(host->clk); + mci->f_min = mci->f_max / SDCDIV_MAX_CDIV; + mci->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + mci->host_caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED_52MHZ | + MMC_CAP_SD_HIGHSPEED; + + mci->init = bcm2835_sdhost_init; + mci->set_ios = bcm2835_set_ios; + mci->send_cmd = bcm2835_send_cmd; + + dev->priv = host; + dev->detect = bcm2835_sdhost_detect, + + mci_of_parse(mci); + + return mci_register(mci); +} + +static __maybe_unused struct of_device_id bcm2835_sdhost_compatible[] = { + { .compatible = "brcm,bcm2835-sdhost" }, + { /* sentinel */ } +}; + +static struct driver_d bcm2835_sdhost_driver = { + .name = "bcm2835-sdhost", + .probe = bcm2835_sdhost_probe, + .of_compatible = DRV_OF_COMPAT(bcm2835_sdhost_compatible), +}; +device_platform_driver(bcm2835_sdhost_driver); -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/4] mci: add driver for BCM283x sdhost core 2019-04-27 18:36 ` [PATCH 1/4] mci: add driver for BCM283x sdhost core Lucas Stach @ 2019-04-29 7:42 ` Sascha Hauer 0 siblings, 0 replies; 7+ messages in thread From: Sascha Hauer @ 2019-04-29 7:42 UTC (permalink / raw) To: Lucas Stach; +Cc: barebox On Sat, Apr 27, 2019 at 08:36:24PM +0200, Lucas Stach wrote: > The sdhost is a simple MMC controller found on the Broadcom > BCM283x line of SoCs. The driver code was ported from U-Boot > and then simplified a bit, by dropping a lot of the state > tracking. > > Signed-off-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/mci/Kconfig | 4 + > drivers/mci/Makefile | 1 + > drivers/mci/bcm2835-sdhost.c | 657 +++++++++++++++++++++++++++++++++++ > 3 files changed, 662 insertions(+) > create mode 100644 drivers/mci/bcm2835-sdhost.c > > diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig > index 911cc0cb1e..08c8c84e8c 100644 > --- a/drivers/mci/Kconfig > +++ b/drivers/mci/Kconfig > @@ -66,6 +66,10 @@ config MCI_BCM283X > bool "MCI support for BCM283X" > depends on ARCH_BCM283X > > +config MCI_BCM283X_SDHOST > + bool "BCM283X sdhost" > + depends on ARCH_BCM283X > + > config MCI_DOVE > bool "Marvell Dove SDHCI" > depends on ARCH_DOVE > diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile > index f6214c0cbb..25a1d073dc 100644 > --- a/drivers/mci/Makefile > +++ b/drivers/mci/Makefile > @@ -1,6 +1,7 @@ > obj-$(CONFIG_MCI) += mci-core.o > obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o > obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o > +obj-$(CONFIG_MCI_BCM283X_SDHOST) += bcm2835-sdhost.o > obj-$(CONFIG_MCI_DOVE) += dove-sdhci.o > obj-$(CONFIG_MCI_IMX) += imx.o > obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o > diff --git a/drivers/mci/bcm2835-sdhost.c b/drivers/mci/bcm2835-sdhost.c > new file mode 100644 > index 0000000000..bad155e07d > --- /dev/null > +++ b/drivers/mci/bcm2835-sdhost.c > @@ -0,0 +1,657 @@ > +#define to_bcm2835_host(mci) container_of(mci, struct bcm2835_host, mci) A static inline function is nicer here. It makes the expected types clear. > +static int bcm2835_transfer_block_pio(struct bcm2835_host *host, > + struct mci_data *data, bool is_read) > +{ > + size_t blksize = data->blocksize; > + int copy_words; > + u32 hsts = 0; > + u32 *buf; > + > + if (blksize % sizeof(u32)) > + return -EINVAL; > + > + buf = is_read ? (u32 *)data->dest : (u32 *)data->src; Use a const * for the write case? > + > + if (is_read) > + data->dest += blksize; > + else > + data->src += blksize; I think data->dest and data->src shouldn't be changed by a driver. > + > + copy_words = blksize / sizeof(u32); > + > + /* > + * Copy all contents from/to the FIFO as far as it reaches, > + * then wait for it to fill/empty again and rewind. > + */ > + while (copy_words) { > + int burst_words, words; > + u32 edm; > + > + burst_words = min(SDDATA_FIFO_PIO_BURST, copy_words); > + edm = readl(host->regs + SDEDM); > + if (is_read) > + words = edm_fifo_fill(edm); > + else > + words = SDDATA_FIFO_WORDS - edm_fifo_fill(edm); > + > + if (words < burst_words) { > + int fsm_state = (edm & SDEDM_FSM_MASK); > + > + if ((is_read && > + (fsm_state != SDEDM_FSM_READDATA && > + fsm_state != SDEDM_FSM_READWAIT && > + fsm_state != SDEDM_FSM_READCRC)) || > + (!is_read && > + (fsm_state != SDEDM_FSM_WRITEDATA && > + fsm_state != SDEDM_FSM_WRITEWAIT1 && > + fsm_state != SDEDM_FSM_WRITEWAIT2 && > + fsm_state != SDEDM_FSM_WRITECRC && > + fsm_state != SDEDM_FSM_WRITESTART1 && > + fsm_state != SDEDM_FSM_WRITESTART2))) { > + hsts = readl(host->regs + SDHSTS); > + printf("fsm %x, hsts %08x\n", fsm_state, hsts); > + if (hsts & SDHSTS_ERROR_MASK) > + break; > + } > + > + continue; > + } else if (words > copy_words) { > + words = copy_words; > + } This code waits until the FIFO is filled to a certain amount and then reads/writes this amount of data. This resembles what a DMA engine would do, but as this is PIO wouldn't it be possible to just read once a word is available and write once space for a word is available? > + > + copy_words -= words; > + > + /* Copy current chunk to/from the FIFO */ > + while (words) { > + if (is_read) > + *(buf++) = readl(host->regs + SDDATA); > + else > + writel(*(buf++), host->regs + SDDATA); > + words--; > + } > + } > + > + return 0; > +} > + > +static int bcm2835_transfer_pio(struct bcm2835_host *host, > + struct mci_data *data) > +{ > + u32 sdhsts; > + bool is_read = !!(data->flags & MMC_DATA_READ); > + int ret = 0; > + > + ret = bcm2835_transfer_block_pio(host, data, is_read); > + if (ret) > + return ret; > + > + sdhsts = readl(host->regs + SDHSTS); > + if (sdhsts & (SDHSTS_CRC16_ERROR | > + SDHSTS_CRC7_ERROR | > + SDHSTS_FIFO_ERROR)) { > + printf("%s transfer error - HSTS %08x\n", > + is_read ? "read" : "write", sdhsts); please use dev_* functions consistently. > + ret = -EILSEQ; > + } else if ((sdhsts & (SDHSTS_CMD_TIME_OUT | > + SDHSTS_REW_TIME_OUT))) { > + printf("%s timeout error - HSTS %08x\n", > + is_read ? "read" : "write", sdhsts); > + ret = -ETIMEDOUT; > + } > + > + return ret; > +} > + > +static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host) > +{ > + u32 value; > + int ret; > + int timeout_us = SDHST_TIMEOUT_MAX_USEC; > + > + ret = readl_poll_timeout(host->regs + SDCMD, value, > + !(value & SDCMD_NEW_FLAG), timeout_us); > + if (ret == -ETIMEDOUT) > + printf("%s: timeout (%d us)\n", __func__, timeout_us); > + > + return value; > +} > + > +static int bcm2835_send_command(struct bcm2835_host *host, struct mci_cmd *cmd, > + struct mci_data *data) > +{ > + u32 sdcmd, sdhsts; > + > + if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) { > + printf("unsupported response type!\n"); > + return -EINVAL; > + } > + > + sdcmd = bcm2835_read_wait_sdcmd(host); > + if (sdcmd & SDCMD_NEW_FLAG) { > + printf("previous command never completed.\n"); > + return -EBUSY; > + } > + > + /* Clear any error flags */ > + sdhsts = readl(host->regs + SDHSTS); > + if (sdhsts & SDHSTS_ERROR_MASK) > + writel(sdhsts, host->regs + SDHSTS); > + > + if (data) { > + writel(data->blocksize, host->regs + SDHBCT); > + writel(data->blocks, host->regs + SDHBLC); > + } > + > + writel(cmd->cmdarg, host->regs + SDARG); > + > + sdcmd = cmd->cmdidx & SDCMD_CMD_MASK; > + > + if (!(cmd->resp_type & MMC_RSP_PRESENT)) { > + sdcmd |= SDCMD_NO_RESPONSE; > + } else { > + if (cmd->resp_type & MMC_RSP_136) > + sdcmd |= SDCMD_LONG_RESPONSE; > + if (cmd->resp_type & MMC_RSP_BUSY) { > + sdcmd |= SDCMD_BUSYWAIT; > + } > + } > + > + if (data) { > + if (data->flags & MMC_DATA_WRITE) > + sdcmd |= SDCMD_WRITE_CMD; > + if (data->flags & MMC_DATA_READ) > + sdcmd |= SDCMD_READ_CMD; > + } > + > + writel(sdcmd | SDCMD_NEW_FLAG, host->regs + SDCMD); > + > + return 0; > +} > + > +static int bcm2835_finish_command(struct bcm2835_host *host, > + struct mci_cmd *cmd) > +{ > + u32 sdcmd; > + int ret = 0; > + > + sdcmd = bcm2835_read_wait_sdcmd(host); > + > + /* Check for errors */ > + if (sdcmd & SDCMD_NEW_FLAG) { > + printf("command never completed.\n"); > + return -EIO; > + } else if (sdcmd & SDCMD_FAIL_FLAG) { The 'else' is unnecessary here. > + u32 sdhsts = readl(host->regs + SDHSTS); > + > + /* Clear the errors */ > + writel(SDHSTS_ERROR_MASK, host->regs + SDHSTS); > + > + if (!(sdhsts & SDHSTS_CRC7_ERROR) || > + (cmd->cmdidx != MMC_CMD_SEND_OP_COND)) { > + if (sdhsts & SDHSTS_CMD_TIME_OUT) { > + ret = -ETIMEDOUT; > + } else { > + printf("unexpected command %d error\n", > + cmd->cmdidx); > + ret = -EILSEQ; > + } > + > + return ret; > + } > + } > + > + if (cmd->resp_type & MMC_RSP_PRESENT) { > + if (cmd->resp_type & MMC_RSP_136) { > + int i; > + > + for (i = 0; i < 4; i++) { > + cmd->response[3 - i] = > + readl(host->regs + SDRSP0 + i * 4); > + } > + } else { > + cmd->response[0] = readl(host->regs + SDRSP0); > + } > + } > + > + return ret; > +} > + > +static int bcm2835_check_cmd_error(struct bcm2835_host *host, u32 intmask) > +{ > + int ret = -EINVAL; > + > + if (!(intmask & SDHSTS_ERROR_MASK)) > + return 0; > + > + printf("sdhost_busy_irq: intmask %08x\n", intmask); > + if (intmask & SDHSTS_CRC7_ERROR) { > + ret = -EILSEQ; > + } else if (intmask & (SDHSTS_CRC16_ERROR | > + SDHSTS_FIFO_ERROR)) { > + ret = -EILSEQ; > + } else if (intmask & (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT)) { > + ret = -ETIMEDOUT; > + } > + > + return ret; > +} > + > +static int bcm2835_check_data_error(struct bcm2835_host *host, u32 intmask) > +{ > + int ret = 0; > + > + if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_FIFO_ERROR)) > + ret = -EILSEQ; > + if (intmask & SDHSTS_REW_TIME_OUT) > + ret = -ETIMEDOUT; > + > + if (ret) > + printf("%s:%d %d\n", __func__, __LINE__, ret); > + > + return ret; > +} > + > +static int bcm2835_transmit(struct bcm2835_host *host, struct mci_cmd *cmd, > + struct mci_data *data) > +{ > + u32 intmask = readl(host->regs + SDHSTS); > + int ret; > + > + /* Check for errors */ > + if (data) { > + ret = bcm2835_check_data_error(host, intmask); > + if (ret) > + return ret; > + } > + > + ret = bcm2835_check_cmd_error(host, intmask); > + if (ret) > + return ret; > + > + /* Handle wait for busy end */ > + if ((cmd && (cmd->resp_type & MMC_RSP_BUSY)) && > + (intmask & SDHSTS_BUSY_IRPT)) { > + writel(SDHSTS_BUSY_IRPT, host->regs + SDHSTS); > + bcm2835_finish_command(host, cmd); > + } > + > + /* Handle PIO data transfer */ > + while (data && data->blocks) { > + ret = bcm2835_transfer_pio(host, data); > + if (ret) > + break; > + data->blocks--; > + } > + > + /* Transfer successful: wait for command to complete for real */ > + if (!ret) > + ret = bcm2835_wait_transfer_complete(host); > + > + return ret; > +} > + > +static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) > +{ > + int div; > + > + /* The SDCDIV register has 11 bits, and holds (div - 2). But > + * in data mode the max is 50MHz wihout a minimum, and only s/wihout/without/ > + * the bottom 3 bits are used. Since the switch over is > + * automatic (unless we have marked the card as slow...), > + * chosen values have to make sense in both modes. Ident mode > + * must be 100-400KHz, so can range check the requested > + * clock. CMD15 must be used to return to data mode, so this > + * can be monitored. > + * > + * clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz > + * 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz > + * > + * 623->400KHz/27.8MHz > + * reset value (507)->491159/50MHz > + * > + * BUT, the 3-bit clock divisor in data mode is too small if > + * the core clock is higher than 250MHz, so instead use the > + * SLOW_CARD configuration bit to force the use of the ident > + * clock divisor at all times. > + */ > + > + if (clock < 100000) { > + /* Can't stop the clock, but make it as slow as possible > + * to show willing > + */ > + writel(SDCDIV_MAX_CDIV, host->regs + SDCDIV); > + return; > + } > + > + div = host->mci.f_max / clock; > + if (div < 2) > + div = 2; > + if ((host->mci.f_max / div) > clock) > + div++; > + div -= 2; > + > + if (div > SDCDIV_MAX_CDIV) > + div = SDCDIV_MAX_CDIV; > + > + clock = host->mci.f_max / (div + 2); > + > + writel(div, host->regs + SDCDIV); > + > + /* Set the timeout to 500ms */ > + writel(clock / 2, host->regs + SDTOUT); > +} > + > +static int bcm2835_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, > + struct mci_data *data) > +{ > + struct bcm2835_host *host = to_bcm2835_host(mci); > + u32 edm, fsm; > + int ret = 0; > + > + if (data && !is_power_of_2(data->blocksize)) { > + printf("unsupported block size (%d bytes)\n", data->blocksize); > + > + if (cmd) > + return -EINVAL; cmd is never NULL here. Please drop all the tests. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/4] ARM: rpi: add clock for sdhost 2019-04-27 18:36 [PATCH 0/4] BCM283x sdhost driver Lucas Stach 2019-04-27 18:36 ` [PATCH 1/4] mci: add driver for BCM283x sdhost core Lucas Stach @ 2019-04-27 18:36 ` Lucas Stach 2019-04-27 19:28 ` Sam Ravnborg 2019-04-27 18:36 ` [PATCH 3/4] ARM: rpi: enable sdhost driver in defconfig Lucas Stach 2019-04-27 18:36 ` [PATCH 4/4] ARM: rpi3: remove swapped sdhci and sdhost Lucas Stach 3 siblings, 1 reply; 7+ messages in thread From: Lucas Stach @ 2019-04-27 18:36 UTC (permalink / raw) To: barebox The sdhost is driven by the core clock. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> --- arch/arm/boards/raspberry-pi/rpi-common.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boards/raspberry-pi/rpi-common.c b/arch/arm/boards/raspberry-pi/rpi-common.c index bc877f853a..00ae49b686 100644 --- a/arch/arm/boards/raspberry-pi/rpi-common.c +++ b/arch/arm/boards/raspberry-pi/rpi-common.c @@ -319,6 +319,14 @@ static int rpi_clock_init(void) clkdev_add_physbase(clk, 0x20300000, NULL); clkdev_add_physbase(clk, 0x3f300000, NULL); + clk = rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_CORE, + "bcm2835_sdhost"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clkdev_add_physbase(clk, 0x20202000, NULL); + clkdev_add_physbase(clk, 0x3f202000, NULL); + return 0; } postconsole_initcall(rpi_clock_init); -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/4] ARM: rpi: add clock for sdhost 2019-04-27 18:36 ` [PATCH 2/4] ARM: rpi: add clock for sdhost Lucas Stach @ 2019-04-27 19:28 ` Sam Ravnborg 0 siblings, 0 replies; 7+ messages in thread From: Sam Ravnborg @ 2019-04-27 19:28 UTC (permalink / raw) To: Lucas Stach; +Cc: barebox Hi Lucas. On Sat, Apr 27, 2019 at 08:36:25PM +0200, Lucas Stach wrote: > The sdhost is driven by the core clock. > > Signed-off-by: Lucas Stach <l.stach@pengutronix.de> > --- > arch/arm/boards/raspberry-pi/rpi-common.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/arch/arm/boards/raspberry-pi/rpi-common.c b/arch/arm/boards/raspberry-pi/rpi-common.c > index bc877f853a..00ae49b686 100644 > --- a/arch/arm/boards/raspberry-pi/rpi-common.c > +++ b/arch/arm/boards/raspberry-pi/rpi-common.c > @@ -319,6 +319,14 @@ static int rpi_clock_init(void) > clkdev_add_physbase(clk, 0x20300000, NULL); > clkdev_add_physbase(clk, 0x3f300000, NULL); > > + clk = rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_CORE, > + "bcm2835_sdhost"); > + if (IS_ERR(clk)) > + return PTR_ERR(clk); Extra tab.. > + > + clkdev_add_physbase(clk, 0x20202000, NULL); > + clkdev_add_physbase(clk, 0x3f202000, NULL); > + > return 0; > } > postconsole_initcall(rpi_clock_init); > -- > 2.20.1 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/4] ARM: rpi: enable sdhost driver in defconfig 2019-04-27 18:36 [PATCH 0/4] BCM283x sdhost driver Lucas Stach 2019-04-27 18:36 ` [PATCH 1/4] mci: add driver for BCM283x sdhost core Lucas Stach 2019-04-27 18:36 ` [PATCH 2/4] ARM: rpi: add clock for sdhost Lucas Stach @ 2019-04-27 18:36 ` Lucas Stach 2019-04-27 18:36 ` [PATCH 4/4] ARM: rpi3: remove swapped sdhci and sdhost Lucas Stach 3 siblings, 0 replies; 7+ messages in thread From: Lucas Stach @ 2019-04-27 18:36 UTC (permalink / raw) To: barebox Signed-off-by: Lucas Stach <l.stach@pengutronix.de> --- arch/arm/configs/rpi_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig index f167625c96..0ae0c42b12 100644 --- a/arch/arm/configs/rpi_defconfig +++ b/arch/arm/configs/rpi_defconfig @@ -66,12 +66,12 @@ CONFIG_SERIAL_AMBA_PL011=y CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_MCI=y CONFIG_MCI_BCM283X=y +CONFIG_MCI_BCM283X_SDHOST=y CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_LED_TRIGGERS=y CONFIG_WATCHDOG=y CONFIG_WATCHDOG_BCM2835=y -CONFIG_PINCTRL=y CONFIG_PINCTRL_BCM283X=y CONFIG_REGULATOR=y CONFIG_FS_EXT4=y -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/4] ARM: rpi3: remove swapped sdhci and sdhost 2019-04-27 18:36 [PATCH 0/4] BCM283x sdhost driver Lucas Stach ` (2 preceding siblings ...) 2019-04-27 18:36 ` [PATCH 3/4] ARM: rpi: enable sdhost driver in defconfig Lucas Stach @ 2019-04-27 18:36 ` Lucas Stach 3 siblings, 0 replies; 7+ messages in thread From: Lucas Stach @ 2019-04-27 18:36 UTC (permalink / raw) To: barebox Now that we have a sdhost driver there is no need to swap those peripherals. As the sdhci peripheral is only used for SDIO, which isn't supported in Barebox disable it. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> --- arch/arm/dts/bcm2837-rpi-3.dts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/dts/bcm2837-rpi-3.dts b/arch/arm/dts/bcm2837-rpi-3.dts index 51883613ce..420525b9e8 100644 --- a/arch/arm/dts/bcm2837-rpi-3.dts +++ b/arch/arm/dts/bcm2837-rpi-3.dts @@ -11,10 +11,5 @@ }; &sdhci { - pinctrl-0 = <&emmc_gpio48>; - /delete-node/ wifi@1; -}; - -&sdhost { status = "disabled"; }; -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2019-04-29 7:42 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-04-27 18:36 [PATCH 0/4] BCM283x sdhost driver Lucas Stach 2019-04-27 18:36 ` [PATCH 1/4] mci: add driver for BCM283x sdhost core Lucas Stach 2019-04-29 7:42 ` Sascha Hauer 2019-04-27 18:36 ` [PATCH 2/4] ARM: rpi: add clock for sdhost Lucas Stach 2019-04-27 19:28 ` Sam Ravnborg 2019-04-27 18:36 ` [PATCH 3/4] ARM: rpi: enable sdhost driver in defconfig Lucas Stach 2019-04-27 18:36 ` [PATCH 4/4] ARM: rpi3: remove swapped sdhci and sdhost Lucas Stach
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox