138cf0d46SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 251c5d844SKevin Hilman /* 351c5d844SKevin Hilman * Amlogic SD/eMMC driver for the GX/S905 family SoCs 451c5d844SKevin Hilman * 551c5d844SKevin Hilman * Copyright (c) 2016 BayLibre, SAS. 651c5d844SKevin Hilman * Author: Kevin Hilman <khilman@baylibre.com> 751c5d844SKevin Hilman */ 851c5d844SKevin Hilman #include <linux/kernel.h> 951c5d844SKevin Hilman #include <linux/module.h> 1051c5d844SKevin Hilman #include <linux/init.h> 1118f92bc0SJerome Brunet #include <linux/delay.h> 1251c5d844SKevin Hilman #include <linux/device.h> 1398849da6SJerome Brunet #include <linux/iopoll.h> 1451c5d844SKevin Hilman #include <linux/of_device.h> 1551c5d844SKevin Hilman #include <linux/platform_device.h> 1651c5d844SKevin Hilman #include <linux/ioport.h> 1751c5d844SKevin Hilman #include <linux/dma-mapping.h> 1851c5d844SKevin Hilman #include <linux/mmc/host.h> 1951c5d844SKevin Hilman #include <linux/mmc/mmc.h> 2051c5d844SKevin Hilman #include <linux/mmc/sdio.h> 2151c5d844SKevin Hilman #include <linux/mmc/slot-gpio.h> 2251c5d844SKevin Hilman #include <linux/io.h> 2351c5d844SKevin Hilman #include <linux/clk.h> 2451c5d844SKevin Hilman #include <linux/clk-provider.h> 2551c5d844SKevin Hilman #include <linux/regulator/consumer.h> 2619c6beaaSJerome Brunet #include <linux/reset.h> 27b8789ec4SUlf Hansson #include <linux/interrupt.h> 281231e7ebSHeiner Kallweit #include <linux/bitfield.h> 298fb572acSThierry Reding #include <linux/pinctrl/consumer.h> 3051c5d844SKevin Hilman 3151c5d844SKevin Hilman #define DRIVER_NAME "meson-gx-mmc" 3251c5d844SKevin Hilman 3351c5d844SKevin Hilman #define SD_EMMC_CLOCK 0x0 341231e7ebSHeiner Kallweit #define CLK_DIV_MASK GENMASK(5, 0) 351231e7ebSHeiner Kallweit #define CLK_SRC_MASK GENMASK(7, 6) 361231e7ebSHeiner Kallweit #define CLK_CORE_PHASE_MASK GENMASK(9, 8) 37c08bcb6cSHeiner Kallweit #define CLK_TX_PHASE_MASK GENMASK(11, 10) 38c08bcb6cSHeiner Kallweit #define CLK_RX_PHASE_MASK GENMASK(13, 12) 395e6f75f4SJerome Brunet #define CLK_PHASE_0 0 405e6f75f4SJerome Brunet #define CLK_PHASE_180 2 41df069815SNan Li #define CLK_V2_TX_DELAY_MASK GENMASK(19, 16) 42df069815SNan Li #define CLK_V2_RX_DELAY_MASK GENMASK(23, 20) 43df069815SNan Li #define CLK_V2_ALWAYS_ON BIT(24) 44df069815SNan Li 45df069815SNan Li #define CLK_V3_TX_DELAY_MASK GENMASK(21, 16) 46df069815SNan Li #define CLK_V3_RX_DELAY_MASK GENMASK(27, 22) 47df069815SNan Li #define CLK_V3_ALWAYS_ON BIT(28) 48df069815SNan Li 49df069815SNan Li #define CLK_TX_DELAY_MASK(h) (h->data->tx_delay_mask) 50df069815SNan Li #define CLK_RX_DELAY_MASK(h) (h->data->rx_delay_mask) 51df069815SNan Li #define CLK_ALWAYS_ON(h) (h->data->always_on) 5251c5d844SKevin Hilman 5352899b99SJerome Brunet #define SD_EMMC_DELAY 0x4 5451c5d844SKevin Hilman #define SD_EMMC_ADJUST 0x8 5571645e65SJerome Brunet #define ADJUST_ADJ_DELAY_MASK GENMASK(21, 16) 5671645e65SJerome Brunet #define ADJUST_DS_EN BIT(15) 5771645e65SJerome Brunet #define ADJUST_ADJ_EN BIT(13) 58df069815SNan Li 59df069815SNan Li #define SD_EMMC_DELAY1 0x4 60df069815SNan Li #define SD_EMMC_DELAY2 0x8 61df069815SNan Li #define SD_EMMC_V3_ADJUST 0xc 62df069815SNan Li 6351c5d844SKevin Hilman #define SD_EMMC_CALOUT 0x10 6451c5d844SKevin Hilman #define SD_EMMC_START 0x40 6551c5d844SKevin Hilman #define START_DESC_INIT BIT(0) 6651c5d844SKevin Hilman #define START_DESC_BUSY BIT(1) 671231e7ebSHeiner Kallweit #define START_DESC_ADDR_MASK GENMASK(31, 2) 6851c5d844SKevin Hilman 6951c5d844SKevin Hilman #define SD_EMMC_CFG 0x44 701231e7ebSHeiner Kallweit #define CFG_BUS_WIDTH_MASK GENMASK(1, 0) 7151c5d844SKevin Hilman #define CFG_BUS_WIDTH_1 0x0 7251c5d844SKevin Hilman #define CFG_BUS_WIDTH_4 0x1 7351c5d844SKevin Hilman #define CFG_BUS_WIDTH_8 0x2 7451c5d844SKevin Hilman #define CFG_DDR BIT(2) 751231e7ebSHeiner Kallweit #define CFG_BLK_LEN_MASK GENMASK(7, 4) 761231e7ebSHeiner Kallweit #define CFG_RESP_TIMEOUT_MASK GENMASK(11, 8) 771231e7ebSHeiner Kallweit #define CFG_RC_CC_MASK GENMASK(15, 12) 7851c5d844SKevin Hilman #define CFG_STOP_CLOCK BIT(22) 7951c5d844SKevin Hilman #define CFG_CLK_ALWAYS_ON BIT(18) 80e21e6fddSHeiner Kallweit #define CFG_CHK_DS BIT(20) 8151c5d844SKevin Hilman #define CFG_AUTO_CLK BIT(23) 8218f92bc0SJerome Brunet #define CFG_ERR_ABORT BIT(27) 8351c5d844SKevin Hilman 8451c5d844SKevin Hilman #define SD_EMMC_STATUS 0x48 8551c5d844SKevin Hilman #define STATUS_BUSY BIT(31) 8618f92bc0SJerome Brunet #define STATUS_DESC_BUSY BIT(30) 87186cd8b7SJerome Brunet #define STATUS_DATI GENMASK(23, 16) 8851c5d844SKevin Hilman 8951c5d844SKevin Hilman #define SD_EMMC_IRQ_EN 0x4c 901231e7ebSHeiner Kallweit #define IRQ_RXD_ERR_MASK GENMASK(7, 0) 9151c5d844SKevin Hilman #define IRQ_TXD_ERR BIT(8) 9251c5d844SKevin Hilman #define IRQ_DESC_ERR BIT(9) 9351c5d844SKevin Hilman #define IRQ_RESP_ERR BIT(10) 9474858655SJerome Brunet #define IRQ_CRC_ERR \ 9574858655SJerome Brunet (IRQ_RXD_ERR_MASK | IRQ_TXD_ERR | IRQ_DESC_ERR | IRQ_RESP_ERR) 9651c5d844SKevin Hilman #define IRQ_RESP_TIMEOUT BIT(11) 9751c5d844SKevin Hilman #define IRQ_DESC_TIMEOUT BIT(12) 9874858655SJerome Brunet #define IRQ_TIMEOUTS \ 9974858655SJerome Brunet (IRQ_RESP_TIMEOUT | IRQ_DESC_TIMEOUT) 10051c5d844SKevin Hilman #define IRQ_END_OF_CHAIN BIT(13) 10151c5d844SKevin Hilman #define IRQ_RESP_STATUS BIT(14) 10251c5d844SKevin Hilman #define IRQ_SDIO BIT(15) 10374858655SJerome Brunet #define IRQ_EN_MASK \ 10474858655SJerome Brunet (IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN | IRQ_RESP_STATUS |\ 10574858655SJerome Brunet IRQ_SDIO) 10651c5d844SKevin Hilman 10751c5d844SKevin Hilman #define SD_EMMC_CMD_CFG 0x50 10851c5d844SKevin Hilman #define SD_EMMC_CMD_ARG 0x54 10951c5d844SKevin Hilman #define SD_EMMC_CMD_DAT 0x58 11051c5d844SKevin Hilman #define SD_EMMC_CMD_RSP 0x5c 11151c5d844SKevin Hilman #define SD_EMMC_CMD_RSP1 0x60 11251c5d844SKevin Hilman #define SD_EMMC_CMD_RSP2 0x64 11351c5d844SKevin Hilman #define SD_EMMC_CMD_RSP3 0x68 11451c5d844SKevin Hilman 11551c5d844SKevin Hilman #define SD_EMMC_RXD 0x94 11651c5d844SKevin Hilman #define SD_EMMC_TXD 0x94 11751c5d844SKevin Hilman #define SD_EMMC_LAST_REG SD_EMMC_TXD 11851c5d844SKevin Hilman 119acdc8e71SNeil Armstrong #define SD_EMMC_SRAM_DATA_BUF_LEN 1536 120acdc8e71SNeil Armstrong #define SD_EMMC_SRAM_DATA_BUF_OFF 0x200 121acdc8e71SNeil Armstrong 12251c5d844SKevin Hilman #define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */ 12351c5d844SKevin Hilman #define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */ 124bb11eff1SHeiner Kallweit #define SD_EMMC_CMD_TIMEOUT 1024 /* in ms */ 125bb11eff1SHeiner Kallweit #define SD_EMMC_CMD_TIMEOUT_DATA 4096 /* in ms */ 12651c5d844SKevin Hilman #define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */ 12779ed05e3SHeiner Kallweit #define SD_EMMC_DESC_BUF_LEN PAGE_SIZE 12879ed05e3SHeiner Kallweit 12979ed05e3SHeiner Kallweit #define SD_EMMC_PRE_REQ_DONE BIT(0) 13079ed05e3SHeiner Kallweit #define SD_EMMC_DESC_CHAIN_MODE BIT(1) 13179ed05e3SHeiner Kallweit 13251c5d844SKevin Hilman #define MUX_CLK_NUM_PARENTS 2 13351c5d844SKevin Hilman 134df069815SNan Li struct meson_mmc_data { 135df069815SNan Li unsigned int tx_delay_mask; 136df069815SNan Li unsigned int rx_delay_mask; 137df069815SNan Li unsigned int always_on; 13871645e65SJerome Brunet unsigned int adjust; 139df069815SNan Li }; 140df069815SNan Li 14179ed05e3SHeiner Kallweit struct sd_emmc_desc { 14279ed05e3SHeiner Kallweit u32 cmd_cfg; 14379ed05e3SHeiner Kallweit u32 cmd_arg; 14479ed05e3SHeiner Kallweit u32 cmd_data; 14579ed05e3SHeiner Kallweit u32 cmd_resp; 14679ed05e3SHeiner Kallweit }; 14779ed05e3SHeiner Kallweit 14851c5d844SKevin Hilman struct meson_host { 14951c5d844SKevin Hilman struct device *dev; 150df069815SNan Li struct meson_mmc_data *data; 15151c5d844SKevin Hilman struct mmc_host *mmc; 15251c5d844SKevin Hilman struct mmc_command *cmd; 15351c5d844SKevin Hilman 15451c5d844SKevin Hilman void __iomem *regs; 15551c5d844SKevin Hilman struct clk *core_clk; 1565e6f75f4SJerome Brunet struct clk *mux_clk; 157bd911ec4SJerome Brunet struct clk *mmc_clk; 158f89f55dfSJerome Brunet unsigned long req_rate; 159dc38ac81SJerome Brunet bool ddr; 16051c5d844SKevin Hilman 161acdc8e71SNeil Armstrong bool dram_access_quirk; 162acdc8e71SNeil Armstrong 1631e03331dSJerome Brunet struct pinctrl *pinctrl; 1641e03331dSJerome Brunet struct pinctrl_state *pins_clk_gate; 1651e03331dSJerome Brunet 16651c5d844SKevin Hilman unsigned int bounce_buf_size; 16751c5d844SKevin Hilman void *bounce_buf; 16851c5d844SKevin Hilman dma_addr_t bounce_dma_addr; 16979ed05e3SHeiner Kallweit struct sd_emmc_desc *descs; 17079ed05e3SHeiner Kallweit dma_addr_t descs_dma_addr; 17151c5d844SKevin Hilman 172bb364890SRemi Pommarel int irq; 173bb364890SRemi Pommarel 17451c5d844SKevin Hilman bool vqmmc_enabled; 17551c5d844SKevin Hilman }; 17651c5d844SKevin Hilman 1771231e7ebSHeiner Kallweit #define CMD_CFG_LENGTH_MASK GENMASK(8, 0) 17851c5d844SKevin Hilman #define CMD_CFG_BLOCK_MODE BIT(9) 17951c5d844SKevin Hilman #define CMD_CFG_R1B BIT(10) 18051c5d844SKevin Hilman #define CMD_CFG_END_OF_CHAIN BIT(11) 1811231e7ebSHeiner Kallweit #define CMD_CFG_TIMEOUT_MASK GENMASK(15, 12) 18251c5d844SKevin Hilman #define CMD_CFG_NO_RESP BIT(16) 18351c5d844SKevin Hilman #define CMD_CFG_NO_CMD BIT(17) 18451c5d844SKevin Hilman #define CMD_CFG_DATA_IO BIT(18) 18551c5d844SKevin Hilman #define CMD_CFG_DATA_WR BIT(19) 18651c5d844SKevin Hilman #define CMD_CFG_RESP_NOCRC BIT(20) 18751c5d844SKevin Hilman #define CMD_CFG_RESP_128 BIT(21) 18851c5d844SKevin Hilman #define CMD_CFG_RESP_NUM BIT(22) 18951c5d844SKevin Hilman #define CMD_CFG_DATA_NUM BIT(23) 1901231e7ebSHeiner Kallweit #define CMD_CFG_CMD_INDEX_MASK GENMASK(29, 24) 19151c5d844SKevin Hilman #define CMD_CFG_ERROR BIT(30) 19251c5d844SKevin Hilman #define CMD_CFG_OWNER BIT(31) 19351c5d844SKevin Hilman 1941231e7ebSHeiner Kallweit #define CMD_DATA_MASK GENMASK(31, 2) 19551c5d844SKevin Hilman #define CMD_DATA_BIG_ENDIAN BIT(1) 19651c5d844SKevin Hilman #define CMD_DATA_SRAM BIT(0) 1971231e7ebSHeiner Kallweit #define CMD_RESP_MASK GENMASK(31, 1) 19851c5d844SKevin Hilman #define CMD_RESP_SRAM BIT(0) 19951c5d844SKevin Hilman 2004eee86c3SHeiner Kallweit static unsigned int meson_mmc_get_timeout_msecs(struct mmc_data *data) 2014eee86c3SHeiner Kallweit { 2024eee86c3SHeiner Kallweit unsigned int timeout = data->timeout_ns / NSEC_PER_MSEC; 2034eee86c3SHeiner Kallweit 2044eee86c3SHeiner Kallweit if (!timeout) 2054eee86c3SHeiner Kallweit return SD_EMMC_CMD_TIMEOUT_DATA; 2064eee86c3SHeiner Kallweit 2074eee86c3SHeiner Kallweit timeout = roundup_pow_of_two(timeout); 2084eee86c3SHeiner Kallweit 2094eee86c3SHeiner Kallweit return min(timeout, 32768U); /* max. 2^15 ms */ 2104eee86c3SHeiner Kallweit } 2114eee86c3SHeiner Kallweit 212e5e4a3ebSHeiner Kallweit static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd) 213e5e4a3ebSHeiner Kallweit { 214e5e4a3ebSHeiner Kallweit if (cmd->opcode == MMC_SET_BLOCK_COUNT && !cmd->error) 215e5e4a3ebSHeiner Kallweit return cmd->mrq->cmd; 216e5e4a3ebSHeiner Kallweit else if (mmc_op_multi(cmd->opcode) && 217e5e4a3ebSHeiner Kallweit (!cmd->mrq->sbc || cmd->error || cmd->data->error)) 218e5e4a3ebSHeiner Kallweit return cmd->mrq->stop; 219e5e4a3ebSHeiner Kallweit else 220e5e4a3ebSHeiner Kallweit return NULL; 221e5e4a3ebSHeiner Kallweit } 222e5e4a3ebSHeiner Kallweit 22379ed05e3SHeiner Kallweit static void meson_mmc_get_transfer_mode(struct mmc_host *mmc, 22479ed05e3SHeiner Kallweit struct mmc_request *mrq) 22579ed05e3SHeiner Kallweit { 226acdc8e71SNeil Armstrong struct meson_host *host = mmc_priv(mmc); 22779ed05e3SHeiner Kallweit struct mmc_data *data = mrq->data; 22879ed05e3SHeiner Kallweit struct scatterlist *sg; 22979ed05e3SHeiner Kallweit int i; 23079ed05e3SHeiner Kallweit bool use_desc_chain_mode = true; 23179ed05e3SHeiner Kallweit 23224835611SHeiner Kallweit /* 233acdc8e71SNeil Armstrong * When Controller DMA cannot directly access DDR memory, disable 234acdc8e71SNeil Armstrong * support for Chain Mode to directly use the internal SRAM using 235acdc8e71SNeil Armstrong * the bounce buffer mode. 236acdc8e71SNeil Armstrong */ 237acdc8e71SNeil Armstrong if (host->dram_access_quirk) 238acdc8e71SNeil Armstrong return; 239acdc8e71SNeil Armstrong 240acdc8e71SNeil Armstrong /* 24124835611SHeiner Kallweit * Broken SDIO with AP6255-based WiFi on Khadas VIM Pro has been 24224835611SHeiner Kallweit * reported. For some strange reason this occurs in descriptor 24324835611SHeiner Kallweit * chain mode only. So let's fall back to bounce buffer mode 24424835611SHeiner Kallweit * for command SD_IO_RW_EXTENDED. 24524835611SHeiner Kallweit */ 24624835611SHeiner Kallweit if (mrq->cmd->opcode == SD_IO_RW_EXTENDED) 24724835611SHeiner Kallweit return; 24824835611SHeiner Kallweit 24979ed05e3SHeiner Kallweit for_each_sg(data->sg, sg, data->sg_len, i) 25079ed05e3SHeiner Kallweit /* check for 8 byte alignment */ 25179ed05e3SHeiner Kallweit if (sg->offset & 7) { 25279ed05e3SHeiner Kallweit WARN_ONCE(1, "unaligned scatterlist buffer\n"); 25379ed05e3SHeiner Kallweit use_desc_chain_mode = false; 25479ed05e3SHeiner Kallweit break; 25579ed05e3SHeiner Kallweit } 25679ed05e3SHeiner Kallweit 25779ed05e3SHeiner Kallweit if (use_desc_chain_mode) 25879ed05e3SHeiner Kallweit data->host_cookie |= SD_EMMC_DESC_CHAIN_MODE; 25979ed05e3SHeiner Kallweit } 26079ed05e3SHeiner Kallweit 26179ed05e3SHeiner Kallweit static inline bool meson_mmc_desc_chain_mode(const struct mmc_data *data) 26279ed05e3SHeiner Kallweit { 26379ed05e3SHeiner Kallweit return data->host_cookie & SD_EMMC_DESC_CHAIN_MODE; 26479ed05e3SHeiner Kallweit } 26579ed05e3SHeiner Kallweit 26679ed05e3SHeiner Kallweit static inline bool meson_mmc_bounce_buf_read(const struct mmc_data *data) 26779ed05e3SHeiner Kallweit { 26879ed05e3SHeiner Kallweit return data && data->flags & MMC_DATA_READ && 26979ed05e3SHeiner Kallweit !meson_mmc_desc_chain_mode(data); 27079ed05e3SHeiner Kallweit } 27179ed05e3SHeiner Kallweit 27279ed05e3SHeiner Kallweit static void meson_mmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 27379ed05e3SHeiner Kallweit { 27479ed05e3SHeiner Kallweit struct mmc_data *data = mrq->data; 27579ed05e3SHeiner Kallweit 27679ed05e3SHeiner Kallweit if (!data) 27779ed05e3SHeiner Kallweit return; 27879ed05e3SHeiner Kallweit 27979ed05e3SHeiner Kallweit meson_mmc_get_transfer_mode(mmc, mrq); 28079ed05e3SHeiner Kallweit data->host_cookie |= SD_EMMC_PRE_REQ_DONE; 28179ed05e3SHeiner Kallweit 28279ed05e3SHeiner Kallweit if (!meson_mmc_desc_chain_mode(data)) 28379ed05e3SHeiner Kallweit return; 28479ed05e3SHeiner Kallweit 28579ed05e3SHeiner Kallweit data->sg_count = dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, 28679ed05e3SHeiner Kallweit mmc_get_dma_dir(data)); 28779ed05e3SHeiner Kallweit if (!data->sg_count) 28879ed05e3SHeiner Kallweit dev_err(mmc_dev(mmc), "dma_map_sg failed"); 28979ed05e3SHeiner Kallweit } 29079ed05e3SHeiner Kallweit 29179ed05e3SHeiner Kallweit static void meson_mmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 29279ed05e3SHeiner Kallweit int err) 29379ed05e3SHeiner Kallweit { 29479ed05e3SHeiner Kallweit struct mmc_data *data = mrq->data; 29579ed05e3SHeiner Kallweit 29679ed05e3SHeiner Kallweit if (data && meson_mmc_desc_chain_mode(data) && data->sg_count) 29779ed05e3SHeiner Kallweit dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, 29879ed05e3SHeiner Kallweit mmc_get_dma_dir(data)); 29979ed05e3SHeiner Kallweit } 30079ed05e3SHeiner Kallweit 3011e03331dSJerome Brunet /* 3021e03331dSJerome Brunet * Gating the clock on this controller is tricky. It seems the mmc clock 3031e03331dSJerome Brunet * is also used by the controller. It may crash during some operation if the 3041e03331dSJerome Brunet * clock is stopped. The safest thing to do, whenever possible, is to keep 3051e03331dSJerome Brunet * clock running at stop it at the pad using the pinmux. 3061e03331dSJerome Brunet */ 3071e03331dSJerome Brunet static void meson_mmc_clk_gate(struct meson_host *host) 3081e03331dSJerome Brunet { 3091e03331dSJerome Brunet u32 cfg; 3101e03331dSJerome Brunet 3111e03331dSJerome Brunet if (host->pins_clk_gate) { 3121e03331dSJerome Brunet pinctrl_select_state(host->pinctrl, host->pins_clk_gate); 3131e03331dSJerome Brunet } else { 3141e03331dSJerome Brunet /* 3151e03331dSJerome Brunet * If the pinmux is not provided - default to the classic and 3161e03331dSJerome Brunet * unsafe method 3171e03331dSJerome Brunet */ 3181e03331dSJerome Brunet cfg = readl(host->regs + SD_EMMC_CFG); 3191e03331dSJerome Brunet cfg |= CFG_STOP_CLOCK; 3201e03331dSJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 3211e03331dSJerome Brunet } 3221e03331dSJerome Brunet } 3231e03331dSJerome Brunet 3241e03331dSJerome Brunet static void meson_mmc_clk_ungate(struct meson_host *host) 3251e03331dSJerome Brunet { 3261e03331dSJerome Brunet u32 cfg; 3271e03331dSJerome Brunet 3281e03331dSJerome Brunet if (host->pins_clk_gate) 329f9be7f9cSUlf Hansson pinctrl_select_default_state(host->dev); 3301e03331dSJerome Brunet 3311e03331dSJerome Brunet /* Make sure the clock is not stopped in the controller */ 3321e03331dSJerome Brunet cfg = readl(host->regs + SD_EMMC_CFG); 3331e03331dSJerome Brunet cfg &= ~CFG_STOP_CLOCK; 3341e03331dSJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 3351e03331dSJerome Brunet } 3361e03331dSJerome Brunet 337dc38ac81SJerome Brunet static int meson_mmc_clk_set(struct meson_host *host, unsigned long rate, 338dc38ac81SJerome Brunet bool ddr) 33951c5d844SKevin Hilman { 34051c5d844SKevin Hilman struct mmc_host *mmc = host->mmc; 3415da86887SHeiner Kallweit int ret; 34251c5d844SKevin Hilman u32 cfg; 34351c5d844SKevin Hilman 344f89f55dfSJerome Brunet /* Same request - bail-out */ 345dc38ac81SJerome Brunet if (host->ddr == ddr && host->req_rate == rate) 34651c5d844SKevin Hilman return 0; 34751c5d844SKevin Hilman 34851c5d844SKevin Hilman /* stop clock */ 3491e03331dSJerome Brunet meson_mmc_clk_gate(host); 350f89f55dfSJerome Brunet host->req_rate = 0; 35151c5d844SKevin Hilman mmc->actual_clock = 0; 352dc38ac81SJerome Brunet 3535da86887SHeiner Kallweit /* return with clock being stopped */ 354dc38ac81SJerome Brunet if (!rate) 35551c5d844SKevin Hilman return 0; 35651c5d844SKevin Hilman 3571e03331dSJerome Brunet /* Stop the clock during rate change to avoid glitches */ 3581e03331dSJerome Brunet cfg = readl(host->regs + SD_EMMC_CFG); 3591e03331dSJerome Brunet cfg |= CFG_STOP_CLOCK; 3601e03331dSJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 3611e03331dSJerome Brunet 362dc38ac81SJerome Brunet if (ddr) { 363dc38ac81SJerome Brunet /* DDR modes require higher module clock */ 364dc38ac81SJerome Brunet rate <<= 1; 365dc38ac81SJerome Brunet cfg |= CFG_DDR; 366dc38ac81SJerome Brunet } else { 367dc38ac81SJerome Brunet cfg &= ~CFG_DDR; 368dc38ac81SJerome Brunet } 369dc38ac81SJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 370dc38ac81SJerome Brunet host->ddr = ddr; 371dc38ac81SJerome Brunet 372844c8a75SJerome Brunet ret = clk_set_rate(host->mmc_clk, rate); 3735da86887SHeiner Kallweit if (ret) { 3745da86887SHeiner Kallweit dev_err(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n", 375844c8a75SJerome Brunet rate, ret); 3765da86887SHeiner Kallweit return ret; 3775da86887SHeiner Kallweit } 37851c5d844SKevin Hilman 379844c8a75SJerome Brunet host->req_rate = rate; 380bd911ec4SJerome Brunet mmc->actual_clock = clk_get_rate(host->mmc_clk); 3815da86887SHeiner Kallweit 382844c8a75SJerome Brunet /* We should report the real output frequency of the controller */ 383dc38ac81SJerome Brunet if (ddr) { 384dc38ac81SJerome Brunet host->req_rate >>= 1; 385844c8a75SJerome Brunet mmc->actual_clock >>= 1; 386dc38ac81SJerome Brunet } 387844c8a75SJerome Brunet 388f89f55dfSJerome Brunet dev_dbg(host->dev, "clk rate: %u Hz\n", mmc->actual_clock); 389dc38ac81SJerome Brunet if (rate != mmc->actual_clock) 390dc38ac81SJerome Brunet dev_dbg(host->dev, "requested rate was %lu\n", rate); 3915da86887SHeiner Kallweit 3925da86887SHeiner Kallweit /* (re)start clock */ 3931e03331dSJerome Brunet meson_mmc_clk_ungate(host); 39451c5d844SKevin Hilman 3955da86887SHeiner Kallweit return 0; 39651c5d844SKevin Hilman } 39751c5d844SKevin Hilman 39851c5d844SKevin Hilman /* 39951c5d844SKevin Hilman * The SD/eMMC IP block has an internal mux and divider used for 40051c5d844SKevin Hilman * generating the MMC clock. Use the clock framework to create and 40151c5d844SKevin Hilman * manage these clocks. 40251c5d844SKevin Hilman */ 40351c5d844SKevin Hilman static int meson_mmc_clk_init(struct meson_host *host) 40451c5d844SKevin Hilman { 40551c5d844SKevin Hilman struct clk_init_data init; 406bd911ec4SJerome Brunet struct clk_mux *mux; 407bd911ec4SJerome Brunet struct clk_divider *div; 40851c5d844SKevin Hilman char clk_name[32]; 40951c5d844SKevin Hilman int i, ret = 0; 41051c5d844SKevin Hilman const char *mux_parent_names[MUX_CLK_NUM_PARENTS]; 411bd911ec4SJerome Brunet const char *clk_parent[1]; 4123c39e2caSJerome Brunet u32 clk_reg; 41351c5d844SKevin Hilman 414ef5c4815SJerome Brunet /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ 4155e6f75f4SJerome Brunet clk_reg = CLK_ALWAYS_ON(host); 416ef5c4815SJerome Brunet clk_reg |= CLK_DIV_MASK; 4175e6f75f4SJerome Brunet clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180); 4185e6f75f4SJerome Brunet clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0); 4195e6f75f4SJerome Brunet clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0); 420ef5c4815SJerome Brunet writel(clk_reg, host->regs + SD_EMMC_CLOCK); 421ef5c4815SJerome Brunet 42251c5d844SKevin Hilman /* get the mux parents */ 42351c5d844SKevin Hilman for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) { 424e9883ef2SHeiner Kallweit struct clk *clk; 42551c5d844SKevin Hilman char name[16]; 42651c5d844SKevin Hilman 42751c5d844SKevin Hilman snprintf(name, sizeof(name), "clkin%d", i); 428e9883ef2SHeiner Kallweit clk = devm_clk_get(host->dev, name); 429e9883ef2SHeiner Kallweit if (IS_ERR(clk)) { 430e9883ef2SHeiner Kallweit if (clk != ERR_PTR(-EPROBE_DEFER)) 43151c5d844SKevin Hilman dev_err(host->dev, "Missing clock %s\n", name); 432e9883ef2SHeiner Kallweit return PTR_ERR(clk); 43351c5d844SKevin Hilman } 43451c5d844SKevin Hilman 435e9883ef2SHeiner Kallweit mux_parent_names[i] = __clk_get_name(clk); 43651c5d844SKevin Hilman } 43751c5d844SKevin Hilman 43851c5d844SKevin Hilman /* create the mux */ 439bd911ec4SJerome Brunet mux = devm_kzalloc(host->dev, sizeof(*mux), GFP_KERNEL); 440bd911ec4SJerome Brunet if (!mux) 441bd911ec4SJerome Brunet return -ENOMEM; 442bd911ec4SJerome Brunet 44351c5d844SKevin Hilman snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev)); 44451c5d844SKevin Hilman init.name = clk_name; 44551c5d844SKevin Hilman init.ops = &clk_mux_ops; 44651c5d844SKevin Hilman init.flags = 0; 44751c5d844SKevin Hilman init.parent_names = mux_parent_names; 4487558c113SHeiner Kallweit init.num_parents = MUX_CLK_NUM_PARENTS; 44951c5d844SKevin Hilman 450bd911ec4SJerome Brunet mux->reg = host->regs + SD_EMMC_CLOCK; 451795c633fSJerome Brunet mux->shift = __ffs(CLK_SRC_MASK); 452bd911ec4SJerome Brunet mux->mask = CLK_SRC_MASK >> mux->shift; 453bd911ec4SJerome Brunet mux->hw.init = &init; 454bd911ec4SJerome Brunet 4555e6f75f4SJerome Brunet host->mux_clk = devm_clk_register(host->dev, &mux->hw); 4565e6f75f4SJerome Brunet if (WARN_ON(IS_ERR(host->mux_clk))) 4575e6f75f4SJerome Brunet return PTR_ERR(host->mux_clk); 45851c5d844SKevin Hilman 45951c5d844SKevin Hilman /* create the divider */ 460bd911ec4SJerome Brunet div = devm_kzalloc(host->dev, sizeof(*div), GFP_KERNEL); 461bd911ec4SJerome Brunet if (!div) 462bd911ec4SJerome Brunet return -ENOMEM; 463bd911ec4SJerome Brunet 46451c5d844SKevin Hilman snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev)); 4657b9ebad3SHeiner Kallweit init.name = clk_name; 46651c5d844SKevin Hilman init.ops = &clk_divider_ops; 46751c5d844SKevin Hilman init.flags = CLK_SET_RATE_PARENT; 4685e6f75f4SJerome Brunet clk_parent[0] = __clk_get_name(host->mux_clk); 469bd911ec4SJerome Brunet init.parent_names = clk_parent; 470bd911ec4SJerome Brunet init.num_parents = 1; 47151c5d844SKevin Hilman 472bd911ec4SJerome Brunet div->reg = host->regs + SD_EMMC_CLOCK; 473795c633fSJerome Brunet div->shift = __ffs(CLK_DIV_MASK); 474bd911ec4SJerome Brunet div->width = __builtin_popcountl(CLK_DIV_MASK); 475bd911ec4SJerome Brunet div->hw.init = &init; 476ca3dcd3fSJerome Brunet div->flags = CLK_DIVIDER_ONE_BASED; 47751c5d844SKevin Hilman 4785e6f75f4SJerome Brunet host->mmc_clk = devm_clk_register(host->dev, &div->hw); 4795e6f75f4SJerome Brunet if (WARN_ON(IS_ERR(host->mmc_clk))) 480bd911ec4SJerome Brunet return PTR_ERR(host->mmc_clk); 48151c5d844SKevin Hilman 482bd911ec4SJerome Brunet /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ 483bd911ec4SJerome Brunet host->mmc->f_min = clk_round_rate(host->mmc_clk, 400000); 484bd911ec4SJerome Brunet ret = clk_set_rate(host->mmc_clk, host->mmc->f_min); 485a4c38c8dSUlf Hansson if (ret) 486a4c38c8dSUlf Hansson return ret; 48751c5d844SKevin Hilman 488bd911ec4SJerome Brunet return clk_prepare_enable(host->mmc_clk); 48951c5d844SKevin Hilman } 49051c5d844SKevin Hilman 491f50b7ac5SJerome Brunet static void meson_mmc_disable_resampling(struct meson_host *host) 492f50b7ac5SJerome Brunet { 493f50b7ac5SJerome Brunet unsigned int val = readl(host->regs + host->data->adjust); 494f50b7ac5SJerome Brunet 495f50b7ac5SJerome Brunet val &= ~ADJUST_ADJ_EN; 496f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 497f50b7ac5SJerome Brunet } 498f50b7ac5SJerome Brunet 499f50b7ac5SJerome Brunet static void meson_mmc_reset_resampling(struct meson_host *host) 500f50b7ac5SJerome Brunet { 501f50b7ac5SJerome Brunet unsigned int val; 502f50b7ac5SJerome Brunet 503f50b7ac5SJerome Brunet meson_mmc_disable_resampling(host); 504f50b7ac5SJerome Brunet 505f50b7ac5SJerome Brunet val = readl(host->regs + host->data->adjust); 506f50b7ac5SJerome Brunet val &= ~ADJUST_ADJ_DELAY_MASK; 507f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 508f50b7ac5SJerome Brunet } 509f50b7ac5SJerome Brunet 510f50b7ac5SJerome Brunet static int meson_mmc_resampling_tuning(struct mmc_host *mmc, u32 opcode) 511f50b7ac5SJerome Brunet { 512f50b7ac5SJerome Brunet struct meson_host *host = mmc_priv(mmc); 513f50b7ac5SJerome Brunet unsigned int val, dly, max_dly, i; 514f50b7ac5SJerome Brunet int ret; 515f50b7ac5SJerome Brunet 516f50b7ac5SJerome Brunet /* Resampling is done using the source clock */ 517f50b7ac5SJerome Brunet max_dly = DIV_ROUND_UP(clk_get_rate(host->mux_clk), 518f50b7ac5SJerome Brunet clk_get_rate(host->mmc_clk)); 519f50b7ac5SJerome Brunet 520f50b7ac5SJerome Brunet val = readl(host->regs + host->data->adjust); 521f50b7ac5SJerome Brunet val |= ADJUST_ADJ_EN; 522f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 523f50b7ac5SJerome Brunet 524f50b7ac5SJerome Brunet if (mmc->doing_retune) 525f50b7ac5SJerome Brunet dly = FIELD_GET(ADJUST_ADJ_DELAY_MASK, val) + 1; 526f50b7ac5SJerome Brunet else 527f50b7ac5SJerome Brunet dly = 0; 528f50b7ac5SJerome Brunet 529f50b7ac5SJerome Brunet for (i = 0; i < max_dly; i++) { 530f50b7ac5SJerome Brunet val &= ~ADJUST_ADJ_DELAY_MASK; 531f50b7ac5SJerome Brunet val |= FIELD_PREP(ADJUST_ADJ_DELAY_MASK, (dly + i) % max_dly); 532f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 533f50b7ac5SJerome Brunet 534f50b7ac5SJerome Brunet ret = mmc_send_tuning(mmc, opcode, NULL); 535f50b7ac5SJerome Brunet if (!ret) { 536f50b7ac5SJerome Brunet dev_dbg(mmc_dev(mmc), "resampling delay: %u\n", 537f50b7ac5SJerome Brunet (dly + i) % max_dly); 538f50b7ac5SJerome Brunet return 0; 539f50b7ac5SJerome Brunet } 540f50b7ac5SJerome Brunet } 541f50b7ac5SJerome Brunet 542f50b7ac5SJerome Brunet meson_mmc_reset_resampling(host); 543f50b7ac5SJerome Brunet return -EIO; 544f50b7ac5SJerome Brunet } 545f50b7ac5SJerome Brunet 546dc38ac81SJerome Brunet static int meson_mmc_prepare_ios_clock(struct meson_host *host, 547dc38ac81SJerome Brunet struct mmc_ios *ios) 548dc38ac81SJerome Brunet { 549dc38ac81SJerome Brunet bool ddr; 550dc38ac81SJerome Brunet 551dc38ac81SJerome Brunet switch (ios->timing) { 552dc38ac81SJerome Brunet case MMC_TIMING_MMC_DDR52: 553dc38ac81SJerome Brunet case MMC_TIMING_UHS_DDR50: 554dc38ac81SJerome Brunet ddr = true; 555dc38ac81SJerome Brunet break; 556dc38ac81SJerome Brunet 557dc38ac81SJerome Brunet default: 558dc38ac81SJerome Brunet ddr = false; 559dc38ac81SJerome Brunet break; 560dc38ac81SJerome Brunet } 561dc38ac81SJerome Brunet 562dc38ac81SJerome Brunet return meson_mmc_clk_set(host, ios->clock, ddr); 563dc38ac81SJerome Brunet } 564dc38ac81SJerome Brunet 565f50b7ac5SJerome Brunet static void meson_mmc_check_resampling(struct meson_host *host, 566f50b7ac5SJerome Brunet struct mmc_ios *ios) 567f50b7ac5SJerome Brunet { 568f50b7ac5SJerome Brunet switch (ios->timing) { 569f50b7ac5SJerome Brunet case MMC_TIMING_LEGACY: 570f50b7ac5SJerome Brunet case MMC_TIMING_MMC_HS: 571f50b7ac5SJerome Brunet case MMC_TIMING_SD_HS: 572f50b7ac5SJerome Brunet case MMC_TIMING_MMC_DDR52: 573f50b7ac5SJerome Brunet meson_mmc_disable_resampling(host); 574f50b7ac5SJerome Brunet break; 575f50b7ac5SJerome Brunet } 576f50b7ac5SJerome Brunet } 577f50b7ac5SJerome Brunet 57851c5d844SKevin Hilman static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 57951c5d844SKevin Hilman { 58051c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 581c36cf125SJerome Brunet u32 bus_width, val; 582c36cf125SJerome Brunet int err; 58351c5d844SKevin Hilman 58451c5d844SKevin Hilman /* 58551c5d844SKevin Hilman * GPIO regulator, only controls switching between 1v8 and 58651c5d844SKevin Hilman * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON. 58751c5d844SKevin Hilman */ 58851c5d844SKevin Hilman switch (ios->power_mode) { 58951c5d844SKevin Hilman case MMC_POWER_OFF: 59051c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vmmc)) 59151c5d844SKevin Hilman mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 59251c5d844SKevin Hilman 59351c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { 59451c5d844SKevin Hilman regulator_disable(mmc->supply.vqmmc); 59551c5d844SKevin Hilman host->vqmmc_enabled = false; 59651c5d844SKevin Hilman } 59751c5d844SKevin Hilman 59851c5d844SKevin Hilman break; 59951c5d844SKevin Hilman 60051c5d844SKevin Hilman case MMC_POWER_UP: 60151c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vmmc)) 60251c5d844SKevin Hilman mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); 6033e2b0af4SJerome Brunet 60451c5d844SKevin Hilman break; 60551c5d844SKevin Hilman 60651c5d844SKevin Hilman case MMC_POWER_ON: 60751c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { 60851c5d844SKevin Hilman int ret = regulator_enable(mmc->supply.vqmmc); 60951c5d844SKevin Hilman 61051c5d844SKevin Hilman if (ret < 0) 611c36cf125SJerome Brunet dev_err(host->dev, 61251c5d844SKevin Hilman "failed to enable vqmmc regulator\n"); 61351c5d844SKevin Hilman else 61451c5d844SKevin Hilman host->vqmmc_enabled = true; 61551c5d844SKevin Hilman } 61651c5d844SKevin Hilman 61751c5d844SKevin Hilman break; 61851c5d844SKevin Hilman } 61951c5d844SKevin Hilman 62051c5d844SKevin Hilman /* Bus width */ 62151c5d844SKevin Hilman switch (ios->bus_width) { 62251c5d844SKevin Hilman case MMC_BUS_WIDTH_1: 62351c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_1; 62451c5d844SKevin Hilman break; 62551c5d844SKevin Hilman case MMC_BUS_WIDTH_4: 62651c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_4; 62751c5d844SKevin Hilman break; 62851c5d844SKevin Hilman case MMC_BUS_WIDTH_8: 62951c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_8; 63051c5d844SKevin Hilman break; 63151c5d844SKevin Hilman default: 63251c5d844SKevin Hilman dev_err(host->dev, "Invalid ios->bus_width: %u. Setting to 4.\n", 63351c5d844SKevin Hilman ios->bus_width); 63451c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_4; 63551c5d844SKevin Hilman } 63651c5d844SKevin Hilman 63751c5d844SKevin Hilman val = readl(host->regs + SD_EMMC_CFG); 6381231e7ebSHeiner Kallweit val &= ~CFG_BUS_WIDTH_MASK; 6391231e7ebSHeiner Kallweit val |= FIELD_PREP(CFG_BUS_WIDTH_MASK, bus_width); 640dc38ac81SJerome Brunet writel(val, host->regs + SD_EMMC_CFG); 64151c5d844SKevin Hilman 642f50b7ac5SJerome Brunet meson_mmc_check_resampling(host, ios); 643dc38ac81SJerome Brunet err = meson_mmc_prepare_ios_clock(host, ios); 644c36cf125SJerome Brunet if (err) 645c36cf125SJerome Brunet dev_err(host->dev, "Failed to set clock: %d\n,", err); 646c36cf125SJerome Brunet 647c36cf125SJerome Brunet dev_dbg(host->dev, "SD_EMMC_CFG: 0x%08x\n", val); 648c01d1219SHeiner Kallweit } 64951c5d844SKevin Hilman 6503d6c991bSHeiner Kallweit static void meson_mmc_request_done(struct mmc_host *mmc, 6513d6c991bSHeiner Kallweit struct mmc_request *mrq) 65251c5d844SKevin Hilman { 65351c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 65451c5d844SKevin Hilman 65551c5d844SKevin Hilman host->cmd = NULL; 65651c5d844SKevin Hilman mmc_request_done(host->mmc, mrq); 65751c5d844SKevin Hilman } 65851c5d844SKevin Hilman 6593d03f6a9SHeiner Kallweit static void meson_mmc_set_blksz(struct mmc_host *mmc, unsigned int blksz) 6603d03f6a9SHeiner Kallweit { 6613d03f6a9SHeiner Kallweit struct meson_host *host = mmc_priv(mmc); 6623d03f6a9SHeiner Kallweit u32 cfg, blksz_old; 6633d03f6a9SHeiner Kallweit 6643d03f6a9SHeiner Kallweit cfg = readl(host->regs + SD_EMMC_CFG); 6653d03f6a9SHeiner Kallweit blksz_old = FIELD_GET(CFG_BLK_LEN_MASK, cfg); 6663d03f6a9SHeiner Kallweit 6673d03f6a9SHeiner Kallweit if (!is_power_of_2(blksz)) 6683d03f6a9SHeiner Kallweit dev_err(host->dev, "blksz %u is not a power of 2\n", blksz); 6693d03f6a9SHeiner Kallweit 6703d03f6a9SHeiner Kallweit blksz = ilog2(blksz); 6713d03f6a9SHeiner Kallweit 6723d03f6a9SHeiner Kallweit /* check if block-size matches, if not update */ 6733d03f6a9SHeiner Kallweit if (blksz == blksz_old) 6743d03f6a9SHeiner Kallweit return; 6753d03f6a9SHeiner Kallweit 6763d03f6a9SHeiner Kallweit dev_dbg(host->dev, "%s: update blk_len %d -> %d\n", __func__, 6773d03f6a9SHeiner Kallweit blksz_old, blksz); 6783d03f6a9SHeiner Kallweit 6793d03f6a9SHeiner Kallweit cfg &= ~CFG_BLK_LEN_MASK; 6803d03f6a9SHeiner Kallweit cfg |= FIELD_PREP(CFG_BLK_LEN_MASK, blksz); 6813d03f6a9SHeiner Kallweit writel(cfg, host->regs + SD_EMMC_CFG); 6823d03f6a9SHeiner Kallweit } 6833d03f6a9SHeiner Kallweit 68475c7fd96SHeiner Kallweit static void meson_mmc_set_response_bits(struct mmc_command *cmd, u32 *cmd_cfg) 68575c7fd96SHeiner Kallweit { 68675c7fd96SHeiner Kallweit if (cmd->flags & MMC_RSP_PRESENT) { 68775c7fd96SHeiner Kallweit if (cmd->flags & MMC_RSP_136) 68875c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_RESP_128; 68975c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_RESP_NUM; 69075c7fd96SHeiner Kallweit 69175c7fd96SHeiner Kallweit if (!(cmd->flags & MMC_RSP_CRC)) 69275c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_RESP_NOCRC; 69375c7fd96SHeiner Kallweit 69475c7fd96SHeiner Kallweit if (cmd->flags & MMC_RSP_BUSY) 69575c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_R1B; 69675c7fd96SHeiner Kallweit } else { 69775c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_NO_RESP; 69875c7fd96SHeiner Kallweit } 69975c7fd96SHeiner Kallweit } 70075c7fd96SHeiner Kallweit 70179ed05e3SHeiner Kallweit static void meson_mmc_desc_chain_transfer(struct mmc_host *mmc, u32 cmd_cfg) 70279ed05e3SHeiner Kallweit { 70379ed05e3SHeiner Kallweit struct meson_host *host = mmc_priv(mmc); 70479ed05e3SHeiner Kallweit struct sd_emmc_desc *desc = host->descs; 70579ed05e3SHeiner Kallweit struct mmc_data *data = host->cmd->data; 70679ed05e3SHeiner Kallweit struct scatterlist *sg; 70779ed05e3SHeiner Kallweit u32 start; 70879ed05e3SHeiner Kallweit int i; 70979ed05e3SHeiner Kallweit 71079ed05e3SHeiner Kallweit if (data->flags & MMC_DATA_WRITE) 71179ed05e3SHeiner Kallweit cmd_cfg |= CMD_CFG_DATA_WR; 71279ed05e3SHeiner Kallweit 71379ed05e3SHeiner Kallweit if (data->blocks > 1) { 71479ed05e3SHeiner Kallweit cmd_cfg |= CMD_CFG_BLOCK_MODE; 71579ed05e3SHeiner Kallweit meson_mmc_set_blksz(mmc, data->blksz); 71679ed05e3SHeiner Kallweit } 71779ed05e3SHeiner Kallweit 71879ed05e3SHeiner Kallweit for_each_sg(data->sg, sg, data->sg_count, i) { 71979ed05e3SHeiner Kallweit unsigned int len = sg_dma_len(sg); 72079ed05e3SHeiner Kallweit 72179ed05e3SHeiner Kallweit if (data->blocks > 1) 72279ed05e3SHeiner Kallweit len /= data->blksz; 72379ed05e3SHeiner Kallweit 72479ed05e3SHeiner Kallweit desc[i].cmd_cfg = cmd_cfg; 72579ed05e3SHeiner Kallweit desc[i].cmd_cfg |= FIELD_PREP(CMD_CFG_LENGTH_MASK, len); 72679ed05e3SHeiner Kallweit if (i > 0) 72779ed05e3SHeiner Kallweit desc[i].cmd_cfg |= CMD_CFG_NO_CMD; 72879ed05e3SHeiner Kallweit desc[i].cmd_arg = host->cmd->arg; 72979ed05e3SHeiner Kallweit desc[i].cmd_resp = 0; 73079ed05e3SHeiner Kallweit desc[i].cmd_data = sg_dma_address(sg); 73179ed05e3SHeiner Kallweit } 73279ed05e3SHeiner Kallweit desc[data->sg_count - 1].cmd_cfg |= CMD_CFG_END_OF_CHAIN; 73379ed05e3SHeiner Kallweit 73479ed05e3SHeiner Kallweit dma_wmb(); /* ensure descriptor is written before kicked */ 73579ed05e3SHeiner Kallweit start = host->descs_dma_addr | START_DESC_BUSY; 73679ed05e3SHeiner Kallweit writel(start, host->regs + SD_EMMC_START); 73779ed05e3SHeiner Kallweit } 73879ed05e3SHeiner Kallweit 73951c5d844SKevin Hilman static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) 74051c5d844SKevin Hilman { 74151c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 74200412ddcSHeiner Kallweit struct mmc_data *data = cmd->data; 7433d03f6a9SHeiner Kallweit u32 cmd_cfg = 0, cmd_data = 0; 74451c5d844SKevin Hilman unsigned int xfer_bytes = 0; 74551c5d844SKevin Hilman 74651c5d844SKevin Hilman /* Setup descriptors */ 74751c5d844SKevin Hilman dma_rmb(); 74851c5d844SKevin Hilman 74979ed05e3SHeiner Kallweit host->cmd = cmd; 75079ed05e3SHeiner Kallweit 7511231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_CMD_INDEX_MASK, cmd->opcode); 752a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */ 75318f92bc0SJerome Brunet cmd_cfg |= CMD_CFG_ERROR; /* stop in case of error */ 75451c5d844SKevin Hilman 75575c7fd96SHeiner Kallweit meson_mmc_set_response_bits(cmd, &cmd_cfg); 75651c5d844SKevin Hilman 75751c5d844SKevin Hilman /* data? */ 75800412ddcSHeiner Kallweit if (data) { 75979ed05e3SHeiner Kallweit data->bytes_xfered = 0; 760a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_DATA_IO; 7611231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_TIMEOUT_MASK, 7624eee86c3SHeiner Kallweit ilog2(meson_mmc_get_timeout_msecs(data))); 763a744c6feSHeiner Kallweit 76479ed05e3SHeiner Kallweit if (meson_mmc_desc_chain_mode(data)) { 76579ed05e3SHeiner Kallweit meson_mmc_desc_chain_transfer(mmc, cmd_cfg); 76679ed05e3SHeiner Kallweit return; 76779ed05e3SHeiner Kallweit } 76879ed05e3SHeiner Kallweit 76900412ddcSHeiner Kallweit if (data->blocks > 1) { 770a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_BLOCK_MODE; 7711231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_LENGTH_MASK, 7721231e7ebSHeiner Kallweit data->blocks); 7733d03f6a9SHeiner Kallweit meson_mmc_set_blksz(mmc, data->blksz); 77451c5d844SKevin Hilman } else { 7751231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_LENGTH_MASK, data->blksz); 77651c5d844SKevin Hilman } 77751c5d844SKevin Hilman 77800412ddcSHeiner Kallweit xfer_bytes = data->blksz * data->blocks; 77900412ddcSHeiner Kallweit if (data->flags & MMC_DATA_WRITE) { 780a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_DATA_WR; 78151c5d844SKevin Hilman WARN_ON(xfer_bytes > host->bounce_buf_size); 78200412ddcSHeiner Kallweit sg_copy_to_buffer(data->sg, data->sg_len, 78351c5d844SKevin Hilman host->bounce_buf, xfer_bytes); 78451c5d844SKevin Hilman dma_wmb(); 78551c5d844SKevin Hilman } 78651c5d844SKevin Hilman 787a322febeSHeiner Kallweit cmd_data = host->bounce_dma_addr & CMD_DATA_MASK; 78851c5d844SKevin Hilman } else { 7891231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_TIMEOUT_MASK, 7901231e7ebSHeiner Kallweit ilog2(SD_EMMC_CMD_TIMEOUT)); 79151c5d844SKevin Hilman } 79251c5d844SKevin Hilman 79351c5d844SKevin Hilman /* Last descriptor */ 794a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_END_OF_CHAIN; 795a322febeSHeiner Kallweit writel(cmd_cfg, host->regs + SD_EMMC_CMD_CFG); 796a322febeSHeiner Kallweit writel(cmd_data, host->regs + SD_EMMC_CMD_DAT); 797a322febeSHeiner Kallweit writel(0, host->regs + SD_EMMC_CMD_RSP); 79851c5d844SKevin Hilman wmb(); /* ensure descriptor is written before kicked */ 799a322febeSHeiner Kallweit writel(cmd->arg, host->regs + SD_EMMC_CMD_ARG); 80051c5d844SKevin Hilman } 80151c5d844SKevin Hilman 80251c5d844SKevin Hilman static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 80351c5d844SKevin Hilman { 80451c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 80579ed05e3SHeiner Kallweit bool needs_pre_post_req = mrq->data && 80679ed05e3SHeiner Kallweit !(mrq->data->host_cookie & SD_EMMC_PRE_REQ_DONE); 80779ed05e3SHeiner Kallweit 80879ed05e3SHeiner Kallweit if (needs_pre_post_req) { 80979ed05e3SHeiner Kallweit meson_mmc_get_transfer_mode(mmc, mrq); 81079ed05e3SHeiner Kallweit if (!meson_mmc_desc_chain_mode(mrq->data)) 81179ed05e3SHeiner Kallweit needs_pre_post_req = false; 81279ed05e3SHeiner Kallweit } 81379ed05e3SHeiner Kallweit 81479ed05e3SHeiner Kallweit if (needs_pre_post_req) 81579ed05e3SHeiner Kallweit meson_mmc_pre_req(mmc, mrq); 81651c5d844SKevin Hilman 81751c5d844SKevin Hilman /* Stop execution */ 81851c5d844SKevin Hilman writel(0, host->regs + SD_EMMC_START); 81951c5d844SKevin Hilman 82079ed05e3SHeiner Kallweit meson_mmc_start_cmd(mmc, mrq->sbc ?: mrq->cmd); 82179ed05e3SHeiner Kallweit 82279ed05e3SHeiner Kallweit if (needs_pre_post_req) 82379ed05e3SHeiner Kallweit meson_mmc_post_req(mmc, mrq, 0); 82451c5d844SKevin Hilman } 82551c5d844SKevin Hilman 8263d6c991bSHeiner Kallweit static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) 82751c5d844SKevin Hilman { 82851c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 82951c5d844SKevin Hilman 83051c5d844SKevin Hilman if (cmd->flags & MMC_RSP_136) { 83151c5d844SKevin Hilman cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP3); 83251c5d844SKevin Hilman cmd->resp[1] = readl(host->regs + SD_EMMC_CMD_RSP2); 83351c5d844SKevin Hilman cmd->resp[2] = readl(host->regs + SD_EMMC_CMD_RSP1); 83451c5d844SKevin Hilman cmd->resp[3] = readl(host->regs + SD_EMMC_CMD_RSP); 83551c5d844SKevin Hilman } else if (cmd->flags & MMC_RSP_PRESENT) { 83651c5d844SKevin Hilman cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP); 83751c5d844SKevin Hilman } 83851c5d844SKevin Hilman } 83951c5d844SKevin Hilman 84051c5d844SKevin Hilman static irqreturn_t meson_mmc_irq(int irq, void *dev_id) 84151c5d844SKevin Hilman { 84251c5d844SKevin Hilman struct meson_host *host = dev_id; 84319a91dd4SHeinrich Schuchardt struct mmc_command *cmd; 8442c8d96a4SHeiner Kallweit struct mmc_data *data; 84551c5d844SKevin Hilman u32 irq_en, status, raw_status; 84674858655SJerome Brunet irqreturn_t ret = IRQ_NONE; 84751c5d844SKevin Hilman 84818f92bc0SJerome Brunet irq_en = readl(host->regs + SD_EMMC_IRQ_EN); 84918f92bc0SJerome Brunet raw_status = readl(host->regs + SD_EMMC_STATUS); 85018f92bc0SJerome Brunet status = raw_status & irq_en; 85118f92bc0SJerome Brunet 85218f92bc0SJerome Brunet if (!status) { 85318f92bc0SJerome Brunet dev_dbg(host->dev, 85418f92bc0SJerome Brunet "Unexpected IRQ! irq_en 0x%08x - status 0x%08x\n", 85518f92bc0SJerome Brunet irq_en, raw_status); 85618f92bc0SJerome Brunet return IRQ_NONE; 85718f92bc0SJerome Brunet } 85818f92bc0SJerome Brunet 85974858655SJerome Brunet if (WARN_ON(!host) || WARN_ON(!host->cmd)) 86051c5d844SKevin Hilman return IRQ_NONE; 86151c5d844SKevin Hilman 862c2c1e63aSJerome Brunet /* ack all raised interrupts */ 863c2c1e63aSJerome Brunet writel(status, host->regs + SD_EMMC_STATUS); 864c2c1e63aSJerome Brunet 86574858655SJerome Brunet cmd = host->cmd; 86674858655SJerome Brunet data = cmd->data; 86774858655SJerome Brunet cmd->error = 0; 86874858655SJerome Brunet if (status & IRQ_CRC_ERR) { 86974858655SJerome Brunet dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status); 87074858655SJerome Brunet cmd->error = -EILSEQ; 87118f92bc0SJerome Brunet ret = IRQ_WAKE_THREAD; 87274858655SJerome Brunet goto out; 87374858655SJerome Brunet } 87474858655SJerome Brunet 87574858655SJerome Brunet if (status & IRQ_TIMEOUTS) { 87674858655SJerome Brunet dev_dbg(host->dev, "Timeout - status 0x%08x\n", status); 87774858655SJerome Brunet cmd->error = -ETIMEDOUT; 87818f92bc0SJerome Brunet ret = IRQ_WAKE_THREAD; 87951c5d844SKevin Hilman goto out; 88051c5d844SKevin Hilman } 88151c5d844SKevin Hilman 8821f8066d9SHeiner Kallweit meson_mmc_read_resp(host->mmc, cmd); 8831f8066d9SHeiner Kallweit 88474858655SJerome Brunet if (status & IRQ_SDIO) { 88574858655SJerome Brunet dev_dbg(host->dev, "IRQ: SDIO TODO.\n"); 88674858655SJerome Brunet ret = IRQ_HANDLED; 88751c5d844SKevin Hilman } 88851c5d844SKevin Hilman 8892c8d96a4SHeiner Kallweit if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) { 8902c8d96a4SHeiner Kallweit if (data && !cmd->error) 8912c8d96a4SHeiner Kallweit data->bytes_xfered = data->blksz * data->blocks; 89279ed05e3SHeiner Kallweit if (meson_mmc_bounce_buf_read(data) || 89379ed05e3SHeiner Kallweit meson_mmc_get_next_command(cmd)) 89451c5d844SKevin Hilman ret = IRQ_WAKE_THREAD; 89574858655SJerome Brunet else 89674858655SJerome Brunet ret = IRQ_HANDLED; 89751c5d844SKevin Hilman } 89851c5d844SKevin Hilman 89951c5d844SKevin Hilman out: 90018f92bc0SJerome Brunet if (cmd->error) { 90118f92bc0SJerome Brunet /* Stop desc in case of errors */ 90218f92bc0SJerome Brunet u32 start = readl(host->regs + SD_EMMC_START); 90318f92bc0SJerome Brunet 90418f92bc0SJerome Brunet start &= ~START_DESC_BUSY; 90518f92bc0SJerome Brunet writel(start, host->regs + SD_EMMC_START); 90618f92bc0SJerome Brunet } 90718f92bc0SJerome Brunet 9081f8066d9SHeiner Kallweit if (ret == IRQ_HANDLED) 90951c5d844SKevin Hilman meson_mmc_request_done(host->mmc, cmd->mrq); 91051c5d844SKevin Hilman 91151c5d844SKevin Hilman return ret; 91251c5d844SKevin Hilman } 91351c5d844SKevin Hilman 91418f92bc0SJerome Brunet static int meson_mmc_wait_desc_stop(struct meson_host *host) 91518f92bc0SJerome Brunet { 91618f92bc0SJerome Brunet u32 status; 91718f92bc0SJerome Brunet 91818f92bc0SJerome Brunet /* 91918f92bc0SJerome Brunet * It may sometimes take a while for it to actually halt. Here, we 92018f92bc0SJerome Brunet * are giving it 5ms to comply 92118f92bc0SJerome Brunet * 92218f92bc0SJerome Brunet * If we don't confirm the descriptor is stopped, it might raise new 92318f92bc0SJerome Brunet * IRQs after we have called mmc_request_done() which is bad. 92418f92bc0SJerome Brunet */ 92518f92bc0SJerome Brunet 92698849da6SJerome Brunet return readl_poll_timeout(host->regs + SD_EMMC_STATUS, status, 92798849da6SJerome Brunet !(status & (STATUS_BUSY | STATUS_DESC_BUSY)), 92898849da6SJerome Brunet 100, 5000); 92918f92bc0SJerome Brunet } 93018f92bc0SJerome Brunet 93151c5d844SKevin Hilman static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) 93251c5d844SKevin Hilman { 93351c5d844SKevin Hilman struct meson_host *host = dev_id; 934e5e4a3ebSHeiner Kallweit struct mmc_command *next_cmd, *cmd = host->cmd; 93551c5d844SKevin Hilman struct mmc_data *data; 93651c5d844SKevin Hilman unsigned int xfer_bytes; 93751c5d844SKevin Hilman 93851c5d844SKevin Hilman if (WARN_ON(!cmd)) 93919a91dd4SHeinrich Schuchardt return IRQ_NONE; 94051c5d844SKevin Hilman 94118f92bc0SJerome Brunet if (cmd->error) { 94218f92bc0SJerome Brunet meson_mmc_wait_desc_stop(host); 94318f92bc0SJerome Brunet meson_mmc_request_done(host->mmc, cmd->mrq); 94418f92bc0SJerome Brunet 94518f92bc0SJerome Brunet return IRQ_HANDLED; 94618f92bc0SJerome Brunet } 94718f92bc0SJerome Brunet 94851c5d844SKevin Hilman data = cmd->data; 94979ed05e3SHeiner Kallweit if (meson_mmc_bounce_buf_read(data)) { 95051c5d844SKevin Hilman xfer_bytes = data->blksz * data->blocks; 95151c5d844SKevin Hilman WARN_ON(xfer_bytes > host->bounce_buf_size); 95251c5d844SKevin Hilman sg_copy_from_buffer(data->sg, data->sg_len, 95351c5d844SKevin Hilman host->bounce_buf, xfer_bytes); 95451c5d844SKevin Hilman } 95551c5d844SKevin Hilman 956e5e4a3ebSHeiner Kallweit next_cmd = meson_mmc_get_next_command(cmd); 957e5e4a3ebSHeiner Kallweit if (next_cmd) 958e5e4a3ebSHeiner Kallweit meson_mmc_start_cmd(host->mmc, next_cmd); 95951c5d844SKevin Hilman else 960e5e4a3ebSHeiner Kallweit meson_mmc_request_done(host->mmc, cmd->mrq); 96151c5d844SKevin Hilman 962690f90b6SHeiner Kallweit return IRQ_HANDLED; 96351c5d844SKevin Hilman } 96451c5d844SKevin Hilman 96551c5d844SKevin Hilman /* 96651c5d844SKevin Hilman * NOTE: we only need this until the GPIO/pinctrl driver can handle 96751c5d844SKevin Hilman * interrupts. For now, the MMC core will use this for polling. 96851c5d844SKevin Hilman */ 96951c5d844SKevin Hilman static int meson_mmc_get_cd(struct mmc_host *mmc) 97051c5d844SKevin Hilman { 97151c5d844SKevin Hilman int status = mmc_gpio_get_cd(mmc); 97251c5d844SKevin Hilman 97351c5d844SKevin Hilman if (status == -ENOSYS) 97451c5d844SKevin Hilman return 1; /* assume present */ 97551c5d844SKevin Hilman 97651c5d844SKevin Hilman return status; 97751c5d844SKevin Hilman } 97851c5d844SKevin Hilman 979c01d1219SHeiner Kallweit static void meson_mmc_cfg_init(struct meson_host *host) 980c01d1219SHeiner Kallweit { 98171e3e00cSAndreas Fenkart u32 cfg = 0; 982c01d1219SHeiner Kallweit 9831231e7ebSHeiner Kallweit cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK, 9841231e7ebSHeiner Kallweit ilog2(SD_EMMC_CFG_RESP_TIMEOUT)); 9851231e7ebSHeiner Kallweit cfg |= FIELD_PREP(CFG_RC_CC_MASK, ilog2(SD_EMMC_CFG_CMD_GAP)); 9861231e7ebSHeiner Kallweit cfg |= FIELD_PREP(CFG_BLK_LEN_MASK, ilog2(SD_EMMC_CFG_BLK_SIZE)); 987c01d1219SHeiner Kallweit 98818f92bc0SJerome Brunet /* abort chain on R/W errors */ 98918f92bc0SJerome Brunet cfg |= CFG_ERR_ABORT; 99018f92bc0SJerome Brunet 991c01d1219SHeiner Kallweit writel(cfg, host->regs + SD_EMMC_CFG); 992c01d1219SHeiner Kallweit } 993c01d1219SHeiner Kallweit 994186cd8b7SJerome Brunet static int meson_mmc_card_busy(struct mmc_host *mmc) 995186cd8b7SJerome Brunet { 996186cd8b7SJerome Brunet struct meson_host *host = mmc_priv(mmc); 997186cd8b7SJerome Brunet u32 regval; 998186cd8b7SJerome Brunet 999186cd8b7SJerome Brunet regval = readl(host->regs + SD_EMMC_STATUS); 1000186cd8b7SJerome Brunet 1001186cd8b7SJerome Brunet /* We are only interrested in lines 0 to 3, so mask the other ones */ 1002186cd8b7SJerome Brunet return !(FIELD_GET(STATUS_DATI, regval) & 0xf); 1003186cd8b7SJerome Brunet } 1004186cd8b7SJerome Brunet 1005b1231b2fSJerome Brunet static int meson_mmc_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) 1006b1231b2fSJerome Brunet { 10079cbe0fc8SMarek Vasut int ret; 10089cbe0fc8SMarek Vasut 1009b1231b2fSJerome Brunet /* vqmmc regulator is available */ 1010b1231b2fSJerome Brunet if (!IS_ERR(mmc->supply.vqmmc)) { 1011b1231b2fSJerome Brunet /* 1012b1231b2fSJerome Brunet * The usual amlogic setup uses a GPIO to switch from one 1013b1231b2fSJerome Brunet * regulator to the other. While the voltage ramp up is 1014b1231b2fSJerome Brunet * pretty fast, care must be taken when switching from 3.3v 1015b1231b2fSJerome Brunet * to 1.8v. Please make sure the regulator framework is aware 1016b1231b2fSJerome Brunet * of your own regulator constraints 1017b1231b2fSJerome Brunet */ 10189cbe0fc8SMarek Vasut ret = mmc_regulator_set_vqmmc(mmc, ios); 10199cbe0fc8SMarek Vasut return ret < 0 ? ret : 0; 1020b1231b2fSJerome Brunet } 1021b1231b2fSJerome Brunet 1022b1231b2fSJerome Brunet /* no vqmmc regulator, assume fixed regulator at 3/3.3V */ 1023b1231b2fSJerome Brunet if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) 1024b1231b2fSJerome Brunet return 0; 1025b1231b2fSJerome Brunet 1026b1231b2fSJerome Brunet return -EINVAL; 1027b1231b2fSJerome Brunet } 1028b1231b2fSJerome Brunet 102951c5d844SKevin Hilman static const struct mmc_host_ops meson_mmc_ops = { 103051c5d844SKevin Hilman .request = meson_mmc_request, 103151c5d844SKevin Hilman .set_ios = meson_mmc_set_ios, 103251c5d844SKevin Hilman .get_cd = meson_mmc_get_cd, 103379ed05e3SHeiner Kallweit .pre_req = meson_mmc_pre_req, 103479ed05e3SHeiner Kallweit .post_req = meson_mmc_post_req, 1035f50b7ac5SJerome Brunet .execute_tuning = meson_mmc_resampling_tuning, 1036186cd8b7SJerome Brunet .card_busy = meson_mmc_card_busy, 1037b1231b2fSJerome Brunet .start_signal_voltage_switch = meson_mmc_voltage_switch, 103851c5d844SKevin Hilman }; 103951c5d844SKevin Hilman 104051c5d844SKevin Hilman static int meson_mmc_probe(struct platform_device *pdev) 104151c5d844SKevin Hilman { 104251c5d844SKevin Hilman struct resource *res; 104351c5d844SKevin Hilman struct meson_host *host; 104451c5d844SKevin Hilman struct mmc_host *mmc; 1045bb364890SRemi Pommarel int ret; 104651c5d844SKevin Hilman 104751c5d844SKevin Hilman mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev); 104851c5d844SKevin Hilman if (!mmc) 104951c5d844SKevin Hilman return -ENOMEM; 105051c5d844SKevin Hilman host = mmc_priv(mmc); 105151c5d844SKevin Hilman host->mmc = mmc; 105251c5d844SKevin Hilman host->dev = &pdev->dev; 105351c5d844SKevin Hilman dev_set_drvdata(&pdev->dev, host); 105451c5d844SKevin Hilman 1055acdc8e71SNeil Armstrong /* The G12A SDIO Controller needs an SRAM bounce buffer */ 1056acdc8e71SNeil Armstrong host->dram_access_quirk = device_property_read_bool(&pdev->dev, 1057acdc8e71SNeil Armstrong "amlogic,dram-access-quirk"); 1058acdc8e71SNeil Armstrong 105951c5d844SKevin Hilman /* Get regulators and the supported OCR mask */ 106051c5d844SKevin Hilman host->vqmmc_enabled = false; 106151c5d844SKevin Hilman ret = mmc_regulator_get_supply(mmc); 1062fa54f3e3SWolfram Sang if (ret) 106351c5d844SKevin Hilman goto free_host; 106451c5d844SKevin Hilman 106551c5d844SKevin Hilman ret = mmc_of_parse(mmc); 106651c5d844SKevin Hilman if (ret) { 1067dc012058SKevin Hilman if (ret != -EPROBE_DEFER) 106851c5d844SKevin Hilman dev_warn(&pdev->dev, "error parsing DT: %d\n", ret); 106951c5d844SKevin Hilman goto free_host; 107051c5d844SKevin Hilman } 107151c5d844SKevin Hilman 1072df069815SNan Li host->data = (struct meson_mmc_data *) 1073df069815SNan Li of_device_get_match_data(&pdev->dev); 1074df069815SNan Li if (!host->data) { 1075df069815SNan Li ret = -EINVAL; 1076df069815SNan Li goto free_host; 1077df069815SNan Li } 1078df069815SNan Li 107919c6beaaSJerome Brunet ret = device_reset_optional(&pdev->dev); 108019c6beaaSJerome Brunet if (ret) { 108119c6beaaSJerome Brunet if (ret != -EPROBE_DEFER) 108219c6beaaSJerome Brunet dev_err(&pdev->dev, "device reset failed: %d\n", ret); 108319c6beaaSJerome Brunet 108419c6beaaSJerome Brunet return ret; 108519c6beaaSJerome Brunet } 108619c6beaaSJerome Brunet 108751c5d844SKevin Hilman res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 108851c5d844SKevin Hilman host->regs = devm_ioremap_resource(&pdev->dev, res); 108951c5d844SKevin Hilman if (IS_ERR(host->regs)) { 109051c5d844SKevin Hilman ret = PTR_ERR(host->regs); 109151c5d844SKevin Hilman goto free_host; 109251c5d844SKevin Hilman } 109351c5d844SKevin Hilman 1094bb364890SRemi Pommarel host->irq = platform_get_irq(pdev, 0); 1095bb364890SRemi Pommarel if (host->irq <= 0) { 109651c5d844SKevin Hilman ret = -EINVAL; 109751c5d844SKevin Hilman goto free_host; 109851c5d844SKevin Hilman } 109951c5d844SKevin Hilman 11001e03331dSJerome Brunet host->pinctrl = devm_pinctrl_get(&pdev->dev); 11011e03331dSJerome Brunet if (IS_ERR(host->pinctrl)) { 11021e03331dSJerome Brunet ret = PTR_ERR(host->pinctrl); 11031e03331dSJerome Brunet goto free_host; 11041e03331dSJerome Brunet } 11051e03331dSJerome Brunet 11061e03331dSJerome Brunet host->pins_clk_gate = pinctrl_lookup_state(host->pinctrl, 11071e03331dSJerome Brunet "clk-gate"); 11081e03331dSJerome Brunet if (IS_ERR(host->pins_clk_gate)) { 11091e03331dSJerome Brunet dev_warn(&pdev->dev, 11101e03331dSJerome Brunet "can't get clk-gate pinctrl, using clk_stop bit\n"); 11111e03331dSJerome Brunet host->pins_clk_gate = NULL; 11121e03331dSJerome Brunet } 11131e03331dSJerome Brunet 111451c5d844SKevin Hilman host->core_clk = devm_clk_get(&pdev->dev, "core"); 111551c5d844SKevin Hilman if (IS_ERR(host->core_clk)) { 111651c5d844SKevin Hilman ret = PTR_ERR(host->core_clk); 111751c5d844SKevin Hilman goto free_host; 111851c5d844SKevin Hilman } 111951c5d844SKevin Hilman 112051c5d844SKevin Hilman ret = clk_prepare_enable(host->core_clk); 112151c5d844SKevin Hilman if (ret) 112251c5d844SKevin Hilman goto free_host; 112351c5d844SKevin Hilman 112451c5d844SKevin Hilman ret = meson_mmc_clk_init(host); 112551c5d844SKevin Hilman if (ret) 1126ce473d5bSMichał Zegan goto err_core_clk; 112751c5d844SKevin Hilman 11283c39e2caSJerome Brunet /* set config to sane default */ 11293c39e2caSJerome Brunet meson_mmc_cfg_init(host); 11303c39e2caSJerome Brunet 113151c5d844SKevin Hilman /* Stop execution */ 113251c5d844SKevin Hilman writel(0, host->regs + SD_EMMC_START); 113351c5d844SKevin Hilman 113474858655SJerome Brunet /* clear, ack and enable interrupts */ 113551c5d844SKevin Hilman writel(0, host->regs + SD_EMMC_IRQ_EN); 113674858655SJerome Brunet writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, 113774858655SJerome Brunet host->regs + SD_EMMC_STATUS); 113874858655SJerome Brunet writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, 113974858655SJerome Brunet host->regs + SD_EMMC_IRQ_EN); 114051c5d844SKevin Hilman 1141bb364890SRemi Pommarel ret = request_threaded_irq(host->irq, meson_mmc_irq, 1142eb4d8112SJerome Brunet meson_mmc_irq_thread, IRQF_ONESHOT, 114383e418a8SMartin Blumenstingl dev_name(&pdev->dev), host); 114451c5d844SKevin Hilman if (ret) 1145bd911ec4SJerome Brunet goto err_init_clk; 114651c5d844SKevin Hilman 1147e5e4a3ebSHeiner Kallweit mmc->caps |= MMC_CAP_CMD23; 1148acdc8e71SNeil Armstrong if (host->dram_access_quirk) { 1149acdc8e71SNeil Armstrong /* Limit to the available sram memory */ 1150acdc8e71SNeil Armstrong mmc->max_segs = SD_EMMC_SRAM_DATA_BUF_LEN / mmc->max_blk_size; 1151acdc8e71SNeil Armstrong mmc->max_blk_count = mmc->max_segs; 1152acdc8e71SNeil Armstrong } else { 1153efe0b669SHeiner Kallweit mmc->max_blk_count = CMD_CFG_LENGTH_MASK; 1154acdc8e71SNeil Armstrong mmc->max_segs = SD_EMMC_DESC_BUF_LEN / 1155acdc8e71SNeil Armstrong sizeof(struct sd_emmc_desc); 1156acdc8e71SNeil Armstrong } 1157efe0b669SHeiner Kallweit mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; 115879ed05e3SHeiner Kallweit mmc->max_seg_size = mmc->max_req_size; 1159efe0b669SHeiner Kallweit 1160d5f758f2SJerome Brunet /* 1161d5f758f2SJerome Brunet * At the moment, we don't know how to reliably enable HS400. 1162d5f758f2SJerome Brunet * From the different datasheets, it is not even clear if this mode 1163d5f758f2SJerome Brunet * is officially supported by any of the SoCs 1164d5f758f2SJerome Brunet */ 1165d5f758f2SJerome Brunet mmc->caps2 &= ~MMC_CAP2_HS400; 1166d5f758f2SJerome Brunet 1167acdc8e71SNeil Armstrong if (host->dram_access_quirk) { 1168acdc8e71SNeil Armstrong /* 1169acdc8e71SNeil Armstrong * The MMC Controller embeds 1,5KiB of internal SRAM 1170acdc8e71SNeil Armstrong * that can be used to be used as bounce buffer. 1171acdc8e71SNeil Armstrong * In the case of the G12A SDIO controller, use these 1172acdc8e71SNeil Armstrong * instead of the DDR memory 1173acdc8e71SNeil Armstrong */ 1174acdc8e71SNeil Armstrong host->bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN; 1175acdc8e71SNeil Armstrong host->bounce_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF; 1176acdc8e71SNeil Armstrong host->bounce_dma_addr = res->start + SD_EMMC_SRAM_DATA_BUF_OFF; 1177acdc8e71SNeil Armstrong } else { 117851c5d844SKevin Hilman /* data bounce buffer */ 11794136fcb5SHeiner Kallweit host->bounce_buf_size = mmc->max_req_size; 118051c5d844SKevin Hilman host->bounce_buf = 118151c5d844SKevin Hilman dma_alloc_coherent(host->dev, host->bounce_buf_size, 118251c5d844SKevin Hilman &host->bounce_dma_addr, GFP_KERNEL); 118351c5d844SKevin Hilman if (host->bounce_buf == NULL) { 118451c5d844SKevin Hilman dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); 118551c5d844SKevin Hilman ret = -ENOMEM; 1186bb364890SRemi Pommarel goto err_free_irq; 118751c5d844SKevin Hilman } 1188acdc8e71SNeil Armstrong } 118951c5d844SKevin Hilman 119079ed05e3SHeiner Kallweit host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, 119179ed05e3SHeiner Kallweit &host->descs_dma_addr, GFP_KERNEL); 119279ed05e3SHeiner Kallweit if (!host->descs) { 119379ed05e3SHeiner Kallweit dev_err(host->dev, "Allocating descriptor DMA buffer failed\n"); 119479ed05e3SHeiner Kallweit ret = -ENOMEM; 119579ed05e3SHeiner Kallweit goto err_bounce_buf; 119679ed05e3SHeiner Kallweit } 119779ed05e3SHeiner Kallweit 119851c5d844SKevin Hilman mmc->ops = &meson_mmc_ops; 119951c5d844SKevin Hilman mmc_add_host(mmc); 120051c5d844SKevin Hilman 120151c5d844SKevin Hilman return 0; 120251c5d844SKevin Hilman 120379ed05e3SHeiner Kallweit err_bounce_buf: 1204acdc8e71SNeil Armstrong if (!host->dram_access_quirk) 120579ed05e3SHeiner Kallweit dma_free_coherent(host->dev, host->bounce_buf_size, 120679ed05e3SHeiner Kallweit host->bounce_buf, host->bounce_dma_addr); 1207bb364890SRemi Pommarel err_free_irq: 1208bb364890SRemi Pommarel free_irq(host->irq, host); 1209bd911ec4SJerome Brunet err_init_clk: 1210bd911ec4SJerome Brunet clk_disable_unprepare(host->mmc_clk); 1211ce473d5bSMichał Zegan err_core_clk: 121251c5d844SKevin Hilman clk_disable_unprepare(host->core_clk); 1213ce473d5bSMichał Zegan free_host: 121451c5d844SKevin Hilman mmc_free_host(mmc); 121551c5d844SKevin Hilman return ret; 121651c5d844SKevin Hilman } 121751c5d844SKevin Hilman 121851c5d844SKevin Hilman static int meson_mmc_remove(struct platform_device *pdev) 121951c5d844SKevin Hilman { 122051c5d844SKevin Hilman struct meson_host *host = dev_get_drvdata(&pdev->dev); 122151c5d844SKevin Hilman 1222a01fc2a2SMichał Zegan mmc_remove_host(host->mmc); 1223a01fc2a2SMichał Zegan 122492763b99SHeiner Kallweit /* disable interrupts */ 122592763b99SHeiner Kallweit writel(0, host->regs + SD_EMMC_IRQ_EN); 1226bb364890SRemi Pommarel free_irq(host->irq, host); 122792763b99SHeiner Kallweit 122879ed05e3SHeiner Kallweit dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, 122979ed05e3SHeiner Kallweit host->descs, host->descs_dma_addr); 1230acdc8e71SNeil Armstrong 1231acdc8e71SNeil Armstrong if (!host->dram_access_quirk) 123251c5d844SKevin Hilman dma_free_coherent(host->dev, host->bounce_buf_size, 123351c5d844SKevin Hilman host->bounce_buf, host->bounce_dma_addr); 123451c5d844SKevin Hilman 1235bd911ec4SJerome Brunet clk_disable_unprepare(host->mmc_clk); 123651c5d844SKevin Hilman clk_disable_unprepare(host->core_clk); 123751c5d844SKevin Hilman 123851c5d844SKevin Hilman mmc_free_host(host->mmc); 123951c5d844SKevin Hilman return 0; 124051c5d844SKevin Hilman } 124151c5d844SKevin Hilman 1242df069815SNan Li static const struct meson_mmc_data meson_gx_data = { 1243df069815SNan Li .tx_delay_mask = CLK_V2_TX_DELAY_MASK, 1244df069815SNan Li .rx_delay_mask = CLK_V2_RX_DELAY_MASK, 1245df069815SNan Li .always_on = CLK_V2_ALWAYS_ON, 124671645e65SJerome Brunet .adjust = SD_EMMC_ADJUST, 1247df069815SNan Li }; 1248df069815SNan Li 1249df069815SNan Li static const struct meson_mmc_data meson_axg_data = { 1250df069815SNan Li .tx_delay_mask = CLK_V3_TX_DELAY_MASK, 1251df069815SNan Li .rx_delay_mask = CLK_V3_RX_DELAY_MASK, 1252df069815SNan Li .always_on = CLK_V3_ALWAYS_ON, 125371645e65SJerome Brunet .adjust = SD_EMMC_V3_ADJUST, 1254df069815SNan Li }; 1255df069815SNan Li 125651c5d844SKevin Hilman static const struct of_device_id meson_mmc_of_match[] = { 1257df069815SNan Li { .compatible = "amlogic,meson-gx-mmc", .data = &meson_gx_data }, 1258df069815SNan Li { .compatible = "amlogic,meson-gxbb-mmc", .data = &meson_gx_data }, 1259df069815SNan Li { .compatible = "amlogic,meson-gxl-mmc", .data = &meson_gx_data }, 1260df069815SNan Li { .compatible = "amlogic,meson-gxm-mmc", .data = &meson_gx_data }, 1261df069815SNan Li { .compatible = "amlogic,meson-axg-mmc", .data = &meson_axg_data }, 126251c5d844SKevin Hilman {} 126351c5d844SKevin Hilman }; 126451c5d844SKevin Hilman MODULE_DEVICE_TABLE(of, meson_mmc_of_match); 126551c5d844SKevin Hilman 126651c5d844SKevin Hilman static struct platform_driver meson_mmc_driver = { 126751c5d844SKevin Hilman .probe = meson_mmc_probe, 126851c5d844SKevin Hilman .remove = meson_mmc_remove, 126951c5d844SKevin Hilman .driver = { 127051c5d844SKevin Hilman .name = DRIVER_NAME, 127151c5d844SKevin Hilman .of_match_table = of_match_ptr(meson_mmc_of_match), 127251c5d844SKevin Hilman }, 127351c5d844SKevin Hilman }; 127451c5d844SKevin Hilman 127551c5d844SKevin Hilman module_platform_driver(meson_mmc_driver); 127651c5d844SKevin Hilman 1277e79dc1b4SNan Li MODULE_DESCRIPTION("Amlogic S905*/GX*/AXG SD/eMMC driver"); 127851c5d844SKevin Hilman MODULE_AUTHOR("Kevin Hilman <khilman@baylibre.com>"); 127951c5d844SKevin Hilman MODULE_LICENSE("GPL v2"); 1280