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 23124835611SHeiner Kallweit /* 232acdc8e71SNeil Armstrong * When Controller DMA cannot directly access DDR memory, disable 233acdc8e71SNeil Armstrong * support for Chain Mode to directly use the internal SRAM using 234acdc8e71SNeil Armstrong * the bounce buffer mode. 235acdc8e71SNeil Armstrong */ 236acdc8e71SNeil Armstrong if (host->dram_access_quirk) 237acdc8e71SNeil Armstrong return; 238acdc8e71SNeil Armstrong 239*e085b51cSDmitry Lebed if (data->blocks > 1) { 240acdc8e71SNeil Armstrong /* 241*e085b51cSDmitry Lebed * In block mode DMA descriptor format, "length" field indicates 242*e085b51cSDmitry Lebed * number of blocks and there is no way to pass DMA size that 243*e085b51cSDmitry Lebed * is not multiple of SDIO block size, making it impossible to 244*e085b51cSDmitry Lebed * tie more than one memory buffer with single SDIO block. 245*e085b51cSDmitry Lebed * Block mode sg buffer size should be aligned with SDIO block 246*e085b51cSDmitry Lebed * size, otherwise chain mode could not be used. 24724835611SHeiner Kallweit */ 248*e085b51cSDmitry Lebed for_each_sg(data->sg, sg, data->sg_len, i) { 249*e085b51cSDmitry Lebed if (sg->length % data->blksz) { 250*e085b51cSDmitry Lebed WARN_ONCE(1, "unaligned sg len %u blksize %u\n", 251*e085b51cSDmitry Lebed sg->length, data->blksz); 25224835611SHeiner Kallweit return; 253*e085b51cSDmitry Lebed } 254*e085b51cSDmitry Lebed } 25579ed05e3SHeiner Kallweit } 25679ed05e3SHeiner Kallweit 257*e085b51cSDmitry Lebed for_each_sg(data->sg, sg, data->sg_len, i) { 258*e085b51cSDmitry Lebed /* check for 8 byte alignment */ 259*e085b51cSDmitry Lebed if (sg->offset % 8) { 260*e085b51cSDmitry Lebed WARN_ONCE(1, "unaligned scatterlist buffer\n"); 261*e085b51cSDmitry Lebed return; 262*e085b51cSDmitry Lebed } 263*e085b51cSDmitry Lebed } 264*e085b51cSDmitry Lebed 26579ed05e3SHeiner Kallweit data->host_cookie |= SD_EMMC_DESC_CHAIN_MODE; 26679ed05e3SHeiner Kallweit } 26779ed05e3SHeiner Kallweit 26879ed05e3SHeiner Kallweit static inline bool meson_mmc_desc_chain_mode(const struct mmc_data *data) 26979ed05e3SHeiner Kallweit { 27079ed05e3SHeiner Kallweit return data->host_cookie & SD_EMMC_DESC_CHAIN_MODE; 27179ed05e3SHeiner Kallweit } 27279ed05e3SHeiner Kallweit 27379ed05e3SHeiner Kallweit static inline bool meson_mmc_bounce_buf_read(const struct mmc_data *data) 27479ed05e3SHeiner Kallweit { 27579ed05e3SHeiner Kallweit return data && data->flags & MMC_DATA_READ && 27679ed05e3SHeiner Kallweit !meson_mmc_desc_chain_mode(data); 27779ed05e3SHeiner Kallweit } 27879ed05e3SHeiner Kallweit 27979ed05e3SHeiner Kallweit static void meson_mmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) 28079ed05e3SHeiner Kallweit { 28179ed05e3SHeiner Kallweit struct mmc_data *data = mrq->data; 28279ed05e3SHeiner Kallweit 28379ed05e3SHeiner Kallweit if (!data) 28479ed05e3SHeiner Kallweit return; 28579ed05e3SHeiner Kallweit 28679ed05e3SHeiner Kallweit meson_mmc_get_transfer_mode(mmc, mrq); 28779ed05e3SHeiner Kallweit data->host_cookie |= SD_EMMC_PRE_REQ_DONE; 28879ed05e3SHeiner Kallweit 28979ed05e3SHeiner Kallweit if (!meson_mmc_desc_chain_mode(data)) 29079ed05e3SHeiner Kallweit return; 29179ed05e3SHeiner Kallweit 29279ed05e3SHeiner Kallweit data->sg_count = dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, 29379ed05e3SHeiner Kallweit mmc_get_dma_dir(data)); 29479ed05e3SHeiner Kallweit if (!data->sg_count) 29579ed05e3SHeiner Kallweit dev_err(mmc_dev(mmc), "dma_map_sg failed"); 29679ed05e3SHeiner Kallweit } 29779ed05e3SHeiner Kallweit 29879ed05e3SHeiner Kallweit static void meson_mmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, 29979ed05e3SHeiner Kallweit int err) 30079ed05e3SHeiner Kallweit { 30179ed05e3SHeiner Kallweit struct mmc_data *data = mrq->data; 30279ed05e3SHeiner Kallweit 30379ed05e3SHeiner Kallweit if (data && meson_mmc_desc_chain_mode(data) && data->sg_count) 30479ed05e3SHeiner Kallweit dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, 30579ed05e3SHeiner Kallweit mmc_get_dma_dir(data)); 30679ed05e3SHeiner Kallweit } 30779ed05e3SHeiner Kallweit 3081e03331dSJerome Brunet /* 3091e03331dSJerome Brunet * Gating the clock on this controller is tricky. It seems the mmc clock 3101e03331dSJerome Brunet * is also used by the controller. It may crash during some operation if the 3111e03331dSJerome Brunet * clock is stopped. The safest thing to do, whenever possible, is to keep 3121e03331dSJerome Brunet * clock running at stop it at the pad using the pinmux. 3131e03331dSJerome Brunet */ 3141e03331dSJerome Brunet static void meson_mmc_clk_gate(struct meson_host *host) 3151e03331dSJerome Brunet { 3161e03331dSJerome Brunet u32 cfg; 3171e03331dSJerome Brunet 3181e03331dSJerome Brunet if (host->pins_clk_gate) { 3191e03331dSJerome Brunet pinctrl_select_state(host->pinctrl, host->pins_clk_gate); 3201e03331dSJerome Brunet } else { 3211e03331dSJerome Brunet /* 3221e03331dSJerome Brunet * If the pinmux is not provided - default to the classic and 3231e03331dSJerome Brunet * unsafe method 3241e03331dSJerome Brunet */ 3251e03331dSJerome Brunet cfg = readl(host->regs + SD_EMMC_CFG); 3261e03331dSJerome Brunet cfg |= CFG_STOP_CLOCK; 3271e03331dSJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 3281e03331dSJerome Brunet } 3291e03331dSJerome Brunet } 3301e03331dSJerome Brunet 3311e03331dSJerome Brunet static void meson_mmc_clk_ungate(struct meson_host *host) 3321e03331dSJerome Brunet { 3331e03331dSJerome Brunet u32 cfg; 3341e03331dSJerome Brunet 3351e03331dSJerome Brunet if (host->pins_clk_gate) 336f9be7f9cSUlf Hansson pinctrl_select_default_state(host->dev); 3371e03331dSJerome Brunet 3381e03331dSJerome Brunet /* Make sure the clock is not stopped in the controller */ 3391e03331dSJerome Brunet cfg = readl(host->regs + SD_EMMC_CFG); 3401e03331dSJerome Brunet cfg &= ~CFG_STOP_CLOCK; 3411e03331dSJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 3421e03331dSJerome Brunet } 3431e03331dSJerome Brunet 344dc38ac81SJerome Brunet static int meson_mmc_clk_set(struct meson_host *host, unsigned long rate, 345dc38ac81SJerome Brunet bool ddr) 34651c5d844SKevin Hilman { 34751c5d844SKevin Hilman struct mmc_host *mmc = host->mmc; 3485da86887SHeiner Kallweit int ret; 34951c5d844SKevin Hilman u32 cfg; 35051c5d844SKevin Hilman 351f89f55dfSJerome Brunet /* Same request - bail-out */ 352dc38ac81SJerome Brunet if (host->ddr == ddr && host->req_rate == rate) 35351c5d844SKevin Hilman return 0; 35451c5d844SKevin Hilman 35551c5d844SKevin Hilman /* stop clock */ 3561e03331dSJerome Brunet meson_mmc_clk_gate(host); 357f89f55dfSJerome Brunet host->req_rate = 0; 35851c5d844SKevin Hilman mmc->actual_clock = 0; 359dc38ac81SJerome Brunet 3605da86887SHeiner Kallweit /* return with clock being stopped */ 361dc38ac81SJerome Brunet if (!rate) 36251c5d844SKevin Hilman return 0; 36351c5d844SKevin Hilman 3641e03331dSJerome Brunet /* Stop the clock during rate change to avoid glitches */ 3651e03331dSJerome Brunet cfg = readl(host->regs + SD_EMMC_CFG); 3661e03331dSJerome Brunet cfg |= CFG_STOP_CLOCK; 3671e03331dSJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 3681e03331dSJerome Brunet 369dc38ac81SJerome Brunet if (ddr) { 370dc38ac81SJerome Brunet /* DDR modes require higher module clock */ 371dc38ac81SJerome Brunet rate <<= 1; 372dc38ac81SJerome Brunet cfg |= CFG_DDR; 373dc38ac81SJerome Brunet } else { 374dc38ac81SJerome Brunet cfg &= ~CFG_DDR; 375dc38ac81SJerome Brunet } 376dc38ac81SJerome Brunet writel(cfg, host->regs + SD_EMMC_CFG); 377dc38ac81SJerome Brunet host->ddr = ddr; 378dc38ac81SJerome Brunet 379844c8a75SJerome Brunet ret = clk_set_rate(host->mmc_clk, rate); 3805da86887SHeiner Kallweit if (ret) { 3815da86887SHeiner Kallweit dev_err(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n", 382844c8a75SJerome Brunet rate, ret); 3835da86887SHeiner Kallweit return ret; 3845da86887SHeiner Kallweit } 38551c5d844SKevin Hilman 386844c8a75SJerome Brunet host->req_rate = rate; 387bd911ec4SJerome Brunet mmc->actual_clock = clk_get_rate(host->mmc_clk); 3885da86887SHeiner Kallweit 389844c8a75SJerome Brunet /* We should report the real output frequency of the controller */ 390dc38ac81SJerome Brunet if (ddr) { 391dc38ac81SJerome Brunet host->req_rate >>= 1; 392844c8a75SJerome Brunet mmc->actual_clock >>= 1; 393dc38ac81SJerome Brunet } 394844c8a75SJerome Brunet 395f89f55dfSJerome Brunet dev_dbg(host->dev, "clk rate: %u Hz\n", mmc->actual_clock); 396dc38ac81SJerome Brunet if (rate != mmc->actual_clock) 397dc38ac81SJerome Brunet dev_dbg(host->dev, "requested rate was %lu\n", rate); 3985da86887SHeiner Kallweit 3995da86887SHeiner Kallweit /* (re)start clock */ 4001e03331dSJerome Brunet meson_mmc_clk_ungate(host); 40151c5d844SKevin Hilman 4025da86887SHeiner Kallweit return 0; 40351c5d844SKevin Hilman } 40451c5d844SKevin Hilman 40551c5d844SKevin Hilman /* 40651c5d844SKevin Hilman * The SD/eMMC IP block has an internal mux and divider used for 40751c5d844SKevin Hilman * generating the MMC clock. Use the clock framework to create and 40851c5d844SKevin Hilman * manage these clocks. 40951c5d844SKevin Hilman */ 41051c5d844SKevin Hilman static int meson_mmc_clk_init(struct meson_host *host) 41151c5d844SKevin Hilman { 41251c5d844SKevin Hilman struct clk_init_data init; 413bd911ec4SJerome Brunet struct clk_mux *mux; 414bd911ec4SJerome Brunet struct clk_divider *div; 41551c5d844SKevin Hilman char clk_name[32]; 41651c5d844SKevin Hilman int i, ret = 0; 41751c5d844SKevin Hilman const char *mux_parent_names[MUX_CLK_NUM_PARENTS]; 418bd911ec4SJerome Brunet const char *clk_parent[1]; 4193c39e2caSJerome Brunet u32 clk_reg; 42051c5d844SKevin Hilman 421ef5c4815SJerome Brunet /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ 4225e6f75f4SJerome Brunet clk_reg = CLK_ALWAYS_ON(host); 423ef5c4815SJerome Brunet clk_reg |= CLK_DIV_MASK; 4245e6f75f4SJerome Brunet clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180); 4255e6f75f4SJerome Brunet clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0); 4265e6f75f4SJerome Brunet clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0); 427ef5c4815SJerome Brunet writel(clk_reg, host->regs + SD_EMMC_CLOCK); 428ef5c4815SJerome Brunet 42951c5d844SKevin Hilman /* get the mux parents */ 43051c5d844SKevin Hilman for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) { 431e9883ef2SHeiner Kallweit struct clk *clk; 43251c5d844SKevin Hilman char name[16]; 43351c5d844SKevin Hilman 43451c5d844SKevin Hilman snprintf(name, sizeof(name), "clkin%d", i); 435e9883ef2SHeiner Kallweit clk = devm_clk_get(host->dev, name); 43689280d09SKrzysztof Kozlowski if (IS_ERR(clk)) 43789280d09SKrzysztof Kozlowski return dev_err_probe(host->dev, PTR_ERR(clk), 43889280d09SKrzysztof Kozlowski "Missing clock %s\n", name); 43951c5d844SKevin Hilman 440e9883ef2SHeiner Kallweit mux_parent_names[i] = __clk_get_name(clk); 44151c5d844SKevin Hilman } 44251c5d844SKevin Hilman 44351c5d844SKevin Hilman /* create the mux */ 444bd911ec4SJerome Brunet mux = devm_kzalloc(host->dev, sizeof(*mux), GFP_KERNEL); 445bd911ec4SJerome Brunet if (!mux) 446bd911ec4SJerome Brunet return -ENOMEM; 447bd911ec4SJerome Brunet 44851c5d844SKevin Hilman snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev)); 44951c5d844SKevin Hilman init.name = clk_name; 45051c5d844SKevin Hilman init.ops = &clk_mux_ops; 45151c5d844SKevin Hilman init.flags = 0; 45251c5d844SKevin Hilman init.parent_names = mux_parent_names; 4537558c113SHeiner Kallweit init.num_parents = MUX_CLK_NUM_PARENTS; 45451c5d844SKevin Hilman 455bd911ec4SJerome Brunet mux->reg = host->regs + SD_EMMC_CLOCK; 456795c633fSJerome Brunet mux->shift = __ffs(CLK_SRC_MASK); 457bd911ec4SJerome Brunet mux->mask = CLK_SRC_MASK >> mux->shift; 458bd911ec4SJerome Brunet mux->hw.init = &init; 459bd911ec4SJerome Brunet 4605e6f75f4SJerome Brunet host->mux_clk = devm_clk_register(host->dev, &mux->hw); 4615e6f75f4SJerome Brunet if (WARN_ON(IS_ERR(host->mux_clk))) 4625e6f75f4SJerome Brunet return PTR_ERR(host->mux_clk); 46351c5d844SKevin Hilman 46451c5d844SKevin Hilman /* create the divider */ 465bd911ec4SJerome Brunet div = devm_kzalloc(host->dev, sizeof(*div), GFP_KERNEL); 466bd911ec4SJerome Brunet if (!div) 467bd911ec4SJerome Brunet return -ENOMEM; 468bd911ec4SJerome Brunet 46951c5d844SKevin Hilman snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev)); 4707b9ebad3SHeiner Kallweit init.name = clk_name; 47151c5d844SKevin Hilman init.ops = &clk_divider_ops; 47251c5d844SKevin Hilman init.flags = CLK_SET_RATE_PARENT; 4735e6f75f4SJerome Brunet clk_parent[0] = __clk_get_name(host->mux_clk); 474bd911ec4SJerome Brunet init.parent_names = clk_parent; 475bd911ec4SJerome Brunet init.num_parents = 1; 47651c5d844SKevin Hilman 477bd911ec4SJerome Brunet div->reg = host->regs + SD_EMMC_CLOCK; 478795c633fSJerome Brunet div->shift = __ffs(CLK_DIV_MASK); 479bd911ec4SJerome Brunet div->width = __builtin_popcountl(CLK_DIV_MASK); 480bd911ec4SJerome Brunet div->hw.init = &init; 481ca3dcd3fSJerome Brunet div->flags = CLK_DIVIDER_ONE_BASED; 48251c5d844SKevin Hilman 4835e6f75f4SJerome Brunet host->mmc_clk = devm_clk_register(host->dev, &div->hw); 4845e6f75f4SJerome Brunet if (WARN_ON(IS_ERR(host->mmc_clk))) 485bd911ec4SJerome Brunet return PTR_ERR(host->mmc_clk); 48651c5d844SKevin Hilman 487bd911ec4SJerome Brunet /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ 488bd911ec4SJerome Brunet host->mmc->f_min = clk_round_rate(host->mmc_clk, 400000); 489bd911ec4SJerome Brunet ret = clk_set_rate(host->mmc_clk, host->mmc->f_min); 490a4c38c8dSUlf Hansson if (ret) 491a4c38c8dSUlf Hansson return ret; 49251c5d844SKevin Hilman 493bd911ec4SJerome Brunet return clk_prepare_enable(host->mmc_clk); 49451c5d844SKevin Hilman } 49551c5d844SKevin Hilman 496f50b7ac5SJerome Brunet static void meson_mmc_disable_resampling(struct meson_host *host) 497f50b7ac5SJerome Brunet { 498f50b7ac5SJerome Brunet unsigned int val = readl(host->regs + host->data->adjust); 499f50b7ac5SJerome Brunet 500f50b7ac5SJerome Brunet val &= ~ADJUST_ADJ_EN; 501f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 502f50b7ac5SJerome Brunet } 503f50b7ac5SJerome Brunet 504f50b7ac5SJerome Brunet static void meson_mmc_reset_resampling(struct meson_host *host) 505f50b7ac5SJerome Brunet { 506f50b7ac5SJerome Brunet unsigned int val; 507f50b7ac5SJerome Brunet 508f50b7ac5SJerome Brunet meson_mmc_disable_resampling(host); 509f50b7ac5SJerome Brunet 510f50b7ac5SJerome Brunet val = readl(host->regs + host->data->adjust); 511f50b7ac5SJerome Brunet val &= ~ADJUST_ADJ_DELAY_MASK; 512f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 513f50b7ac5SJerome Brunet } 514f50b7ac5SJerome Brunet 515f50b7ac5SJerome Brunet static int meson_mmc_resampling_tuning(struct mmc_host *mmc, u32 opcode) 516f50b7ac5SJerome Brunet { 517f50b7ac5SJerome Brunet struct meson_host *host = mmc_priv(mmc); 518f50b7ac5SJerome Brunet unsigned int val, dly, max_dly, i; 519f50b7ac5SJerome Brunet int ret; 520f50b7ac5SJerome Brunet 521f50b7ac5SJerome Brunet /* Resampling is done using the source clock */ 522f50b7ac5SJerome Brunet max_dly = DIV_ROUND_UP(clk_get_rate(host->mux_clk), 523f50b7ac5SJerome Brunet clk_get_rate(host->mmc_clk)); 524f50b7ac5SJerome Brunet 525f50b7ac5SJerome Brunet val = readl(host->regs + host->data->adjust); 526f50b7ac5SJerome Brunet val |= ADJUST_ADJ_EN; 527f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 528f50b7ac5SJerome Brunet 529e0c29be6SWolfram Sang if (mmc_doing_retune(mmc)) 530f50b7ac5SJerome Brunet dly = FIELD_GET(ADJUST_ADJ_DELAY_MASK, val) + 1; 531f50b7ac5SJerome Brunet else 532f50b7ac5SJerome Brunet dly = 0; 533f50b7ac5SJerome Brunet 534f50b7ac5SJerome Brunet for (i = 0; i < max_dly; i++) { 535f50b7ac5SJerome Brunet val &= ~ADJUST_ADJ_DELAY_MASK; 536f50b7ac5SJerome Brunet val |= FIELD_PREP(ADJUST_ADJ_DELAY_MASK, (dly + i) % max_dly); 537f50b7ac5SJerome Brunet writel(val, host->regs + host->data->adjust); 538f50b7ac5SJerome Brunet 539f50b7ac5SJerome Brunet ret = mmc_send_tuning(mmc, opcode, NULL); 540f50b7ac5SJerome Brunet if (!ret) { 541f50b7ac5SJerome Brunet dev_dbg(mmc_dev(mmc), "resampling delay: %u\n", 542f50b7ac5SJerome Brunet (dly + i) % max_dly); 543f50b7ac5SJerome Brunet return 0; 544f50b7ac5SJerome Brunet } 545f50b7ac5SJerome Brunet } 546f50b7ac5SJerome Brunet 547f50b7ac5SJerome Brunet meson_mmc_reset_resampling(host); 548f50b7ac5SJerome Brunet return -EIO; 549f50b7ac5SJerome Brunet } 550f50b7ac5SJerome Brunet 551dc38ac81SJerome Brunet static int meson_mmc_prepare_ios_clock(struct meson_host *host, 552dc38ac81SJerome Brunet struct mmc_ios *ios) 553dc38ac81SJerome Brunet { 554dc38ac81SJerome Brunet bool ddr; 555dc38ac81SJerome Brunet 556dc38ac81SJerome Brunet switch (ios->timing) { 557dc38ac81SJerome Brunet case MMC_TIMING_MMC_DDR52: 558dc38ac81SJerome Brunet case MMC_TIMING_UHS_DDR50: 559dc38ac81SJerome Brunet ddr = true; 560dc38ac81SJerome Brunet break; 561dc38ac81SJerome Brunet 562dc38ac81SJerome Brunet default: 563dc38ac81SJerome Brunet ddr = false; 564dc38ac81SJerome Brunet break; 565dc38ac81SJerome Brunet } 566dc38ac81SJerome Brunet 567dc38ac81SJerome Brunet return meson_mmc_clk_set(host, ios->clock, ddr); 568dc38ac81SJerome Brunet } 569dc38ac81SJerome Brunet 570f50b7ac5SJerome Brunet static void meson_mmc_check_resampling(struct meson_host *host, 571f50b7ac5SJerome Brunet struct mmc_ios *ios) 572f50b7ac5SJerome Brunet { 573f50b7ac5SJerome Brunet switch (ios->timing) { 574f50b7ac5SJerome Brunet case MMC_TIMING_LEGACY: 575f50b7ac5SJerome Brunet case MMC_TIMING_MMC_HS: 576f50b7ac5SJerome Brunet case MMC_TIMING_SD_HS: 577f50b7ac5SJerome Brunet case MMC_TIMING_MMC_DDR52: 578f50b7ac5SJerome Brunet meson_mmc_disable_resampling(host); 579f50b7ac5SJerome Brunet break; 580f50b7ac5SJerome Brunet } 581f50b7ac5SJerome Brunet } 582f50b7ac5SJerome Brunet 58351c5d844SKevin Hilman static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 58451c5d844SKevin Hilman { 58551c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 586c36cf125SJerome Brunet u32 bus_width, val; 587c36cf125SJerome Brunet int err; 58851c5d844SKevin Hilman 58951c5d844SKevin Hilman /* 59051c5d844SKevin Hilman * GPIO regulator, only controls switching between 1v8 and 59151c5d844SKevin Hilman * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON. 59251c5d844SKevin Hilman */ 59351c5d844SKevin Hilman switch (ios->power_mode) { 59451c5d844SKevin Hilman case MMC_POWER_OFF: 59551c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vmmc)) 59651c5d844SKevin Hilman mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 59751c5d844SKevin Hilman 59851c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { 59951c5d844SKevin Hilman regulator_disable(mmc->supply.vqmmc); 60051c5d844SKevin Hilman host->vqmmc_enabled = false; 60151c5d844SKevin Hilman } 60251c5d844SKevin Hilman 60351c5d844SKevin Hilman break; 60451c5d844SKevin Hilman 60551c5d844SKevin Hilman case MMC_POWER_UP: 60651c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vmmc)) 60751c5d844SKevin Hilman mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); 6083e2b0af4SJerome Brunet 60951c5d844SKevin Hilman break; 61051c5d844SKevin Hilman 61151c5d844SKevin Hilman case MMC_POWER_ON: 61251c5d844SKevin Hilman if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { 61351c5d844SKevin Hilman int ret = regulator_enable(mmc->supply.vqmmc); 61451c5d844SKevin Hilman 61551c5d844SKevin Hilman if (ret < 0) 616c36cf125SJerome Brunet dev_err(host->dev, 61751c5d844SKevin Hilman "failed to enable vqmmc regulator\n"); 61851c5d844SKevin Hilman else 61951c5d844SKevin Hilman host->vqmmc_enabled = true; 62051c5d844SKevin Hilman } 62151c5d844SKevin Hilman 62251c5d844SKevin Hilman break; 62351c5d844SKevin Hilman } 62451c5d844SKevin Hilman 62551c5d844SKevin Hilman /* Bus width */ 62651c5d844SKevin Hilman switch (ios->bus_width) { 62751c5d844SKevin Hilman case MMC_BUS_WIDTH_1: 62851c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_1; 62951c5d844SKevin Hilman break; 63051c5d844SKevin Hilman case MMC_BUS_WIDTH_4: 63151c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_4; 63251c5d844SKevin Hilman break; 63351c5d844SKevin Hilman case MMC_BUS_WIDTH_8: 63451c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_8; 63551c5d844SKevin Hilman break; 63651c5d844SKevin Hilman default: 63751c5d844SKevin Hilman dev_err(host->dev, "Invalid ios->bus_width: %u. Setting to 4.\n", 63851c5d844SKevin Hilman ios->bus_width); 63951c5d844SKevin Hilman bus_width = CFG_BUS_WIDTH_4; 64051c5d844SKevin Hilman } 64151c5d844SKevin Hilman 64251c5d844SKevin Hilman val = readl(host->regs + SD_EMMC_CFG); 6431231e7ebSHeiner Kallweit val &= ~CFG_BUS_WIDTH_MASK; 6441231e7ebSHeiner Kallweit val |= FIELD_PREP(CFG_BUS_WIDTH_MASK, bus_width); 645dc38ac81SJerome Brunet writel(val, host->regs + SD_EMMC_CFG); 64651c5d844SKevin Hilman 647f50b7ac5SJerome Brunet meson_mmc_check_resampling(host, ios); 648dc38ac81SJerome Brunet err = meson_mmc_prepare_ios_clock(host, ios); 649c36cf125SJerome Brunet if (err) 650c36cf125SJerome Brunet dev_err(host->dev, "Failed to set clock: %d\n,", err); 651c36cf125SJerome Brunet 652c36cf125SJerome Brunet dev_dbg(host->dev, "SD_EMMC_CFG: 0x%08x\n", val); 653c01d1219SHeiner Kallweit } 65451c5d844SKevin Hilman 6553d6c991bSHeiner Kallweit static void meson_mmc_request_done(struct mmc_host *mmc, 6563d6c991bSHeiner Kallweit struct mmc_request *mrq) 65751c5d844SKevin Hilman { 65851c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 65951c5d844SKevin Hilman 66051c5d844SKevin Hilman host->cmd = NULL; 66151c5d844SKevin Hilman mmc_request_done(host->mmc, mrq); 66251c5d844SKevin Hilman } 66351c5d844SKevin Hilman 6643d03f6a9SHeiner Kallweit static void meson_mmc_set_blksz(struct mmc_host *mmc, unsigned int blksz) 6653d03f6a9SHeiner Kallweit { 6663d03f6a9SHeiner Kallweit struct meson_host *host = mmc_priv(mmc); 6673d03f6a9SHeiner Kallweit u32 cfg, blksz_old; 6683d03f6a9SHeiner Kallweit 6693d03f6a9SHeiner Kallweit cfg = readl(host->regs + SD_EMMC_CFG); 6703d03f6a9SHeiner Kallweit blksz_old = FIELD_GET(CFG_BLK_LEN_MASK, cfg); 6713d03f6a9SHeiner Kallweit 6723d03f6a9SHeiner Kallweit if (!is_power_of_2(blksz)) 6733d03f6a9SHeiner Kallweit dev_err(host->dev, "blksz %u is not a power of 2\n", blksz); 6743d03f6a9SHeiner Kallweit 6753d03f6a9SHeiner Kallweit blksz = ilog2(blksz); 6763d03f6a9SHeiner Kallweit 6773d03f6a9SHeiner Kallweit /* check if block-size matches, if not update */ 6783d03f6a9SHeiner Kallweit if (blksz == blksz_old) 6793d03f6a9SHeiner Kallweit return; 6803d03f6a9SHeiner Kallweit 6813d03f6a9SHeiner Kallweit dev_dbg(host->dev, "%s: update blk_len %d -> %d\n", __func__, 6823d03f6a9SHeiner Kallweit blksz_old, blksz); 6833d03f6a9SHeiner Kallweit 6843d03f6a9SHeiner Kallweit cfg &= ~CFG_BLK_LEN_MASK; 6853d03f6a9SHeiner Kallweit cfg |= FIELD_PREP(CFG_BLK_LEN_MASK, blksz); 6863d03f6a9SHeiner Kallweit writel(cfg, host->regs + SD_EMMC_CFG); 6873d03f6a9SHeiner Kallweit } 6883d03f6a9SHeiner Kallweit 68975c7fd96SHeiner Kallweit static void meson_mmc_set_response_bits(struct mmc_command *cmd, u32 *cmd_cfg) 69075c7fd96SHeiner Kallweit { 69175c7fd96SHeiner Kallweit if (cmd->flags & MMC_RSP_PRESENT) { 69275c7fd96SHeiner Kallweit if (cmd->flags & MMC_RSP_136) 69375c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_RESP_128; 69475c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_RESP_NUM; 69575c7fd96SHeiner Kallweit 69675c7fd96SHeiner Kallweit if (!(cmd->flags & MMC_RSP_CRC)) 69775c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_RESP_NOCRC; 69875c7fd96SHeiner Kallweit 69975c7fd96SHeiner Kallweit if (cmd->flags & MMC_RSP_BUSY) 70075c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_R1B; 70175c7fd96SHeiner Kallweit } else { 70275c7fd96SHeiner Kallweit *cmd_cfg |= CMD_CFG_NO_RESP; 70375c7fd96SHeiner Kallweit } 70475c7fd96SHeiner Kallweit } 70575c7fd96SHeiner Kallweit 70679ed05e3SHeiner Kallweit static void meson_mmc_desc_chain_transfer(struct mmc_host *mmc, u32 cmd_cfg) 70779ed05e3SHeiner Kallweit { 70879ed05e3SHeiner Kallweit struct meson_host *host = mmc_priv(mmc); 70979ed05e3SHeiner Kallweit struct sd_emmc_desc *desc = host->descs; 71079ed05e3SHeiner Kallweit struct mmc_data *data = host->cmd->data; 71179ed05e3SHeiner Kallweit struct scatterlist *sg; 71279ed05e3SHeiner Kallweit u32 start; 71379ed05e3SHeiner Kallweit int i; 71479ed05e3SHeiner Kallweit 71579ed05e3SHeiner Kallweit if (data->flags & MMC_DATA_WRITE) 71679ed05e3SHeiner Kallweit cmd_cfg |= CMD_CFG_DATA_WR; 71779ed05e3SHeiner Kallweit 71879ed05e3SHeiner Kallweit if (data->blocks > 1) { 71979ed05e3SHeiner Kallweit cmd_cfg |= CMD_CFG_BLOCK_MODE; 72079ed05e3SHeiner Kallweit meson_mmc_set_blksz(mmc, data->blksz); 72179ed05e3SHeiner Kallweit } 72279ed05e3SHeiner Kallweit 72379ed05e3SHeiner Kallweit for_each_sg(data->sg, sg, data->sg_count, i) { 72479ed05e3SHeiner Kallweit unsigned int len = sg_dma_len(sg); 72579ed05e3SHeiner Kallweit 72679ed05e3SHeiner Kallweit if (data->blocks > 1) 72779ed05e3SHeiner Kallweit len /= data->blksz; 72879ed05e3SHeiner Kallweit 72979ed05e3SHeiner Kallweit desc[i].cmd_cfg = cmd_cfg; 73079ed05e3SHeiner Kallweit desc[i].cmd_cfg |= FIELD_PREP(CMD_CFG_LENGTH_MASK, len); 73179ed05e3SHeiner Kallweit if (i > 0) 73279ed05e3SHeiner Kallweit desc[i].cmd_cfg |= CMD_CFG_NO_CMD; 73379ed05e3SHeiner Kallweit desc[i].cmd_arg = host->cmd->arg; 73479ed05e3SHeiner Kallweit desc[i].cmd_resp = 0; 73579ed05e3SHeiner Kallweit desc[i].cmd_data = sg_dma_address(sg); 73679ed05e3SHeiner Kallweit } 73779ed05e3SHeiner Kallweit desc[data->sg_count - 1].cmd_cfg |= CMD_CFG_END_OF_CHAIN; 73879ed05e3SHeiner Kallweit 73979ed05e3SHeiner Kallweit dma_wmb(); /* ensure descriptor is written before kicked */ 74079ed05e3SHeiner Kallweit start = host->descs_dma_addr | START_DESC_BUSY; 74179ed05e3SHeiner Kallweit writel(start, host->regs + SD_EMMC_START); 74279ed05e3SHeiner Kallweit } 74379ed05e3SHeiner Kallweit 74451c5d844SKevin Hilman static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) 74551c5d844SKevin Hilman { 74651c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 74700412ddcSHeiner Kallweit struct mmc_data *data = cmd->data; 7483d03f6a9SHeiner Kallweit u32 cmd_cfg = 0, cmd_data = 0; 74951c5d844SKevin Hilman unsigned int xfer_bytes = 0; 75051c5d844SKevin Hilman 75151c5d844SKevin Hilman /* Setup descriptors */ 75251c5d844SKevin Hilman dma_rmb(); 75351c5d844SKevin Hilman 75479ed05e3SHeiner Kallweit host->cmd = cmd; 75579ed05e3SHeiner Kallweit 7561231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_CMD_INDEX_MASK, cmd->opcode); 757a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */ 75818f92bc0SJerome Brunet cmd_cfg |= CMD_CFG_ERROR; /* stop in case of error */ 75951c5d844SKevin Hilman 76075c7fd96SHeiner Kallweit meson_mmc_set_response_bits(cmd, &cmd_cfg); 76151c5d844SKevin Hilman 76251c5d844SKevin Hilman /* data? */ 76300412ddcSHeiner Kallweit if (data) { 76479ed05e3SHeiner Kallweit data->bytes_xfered = 0; 765a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_DATA_IO; 7661231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_TIMEOUT_MASK, 7674eee86c3SHeiner Kallweit ilog2(meson_mmc_get_timeout_msecs(data))); 768a744c6feSHeiner Kallweit 76979ed05e3SHeiner Kallweit if (meson_mmc_desc_chain_mode(data)) { 77079ed05e3SHeiner Kallweit meson_mmc_desc_chain_transfer(mmc, cmd_cfg); 77179ed05e3SHeiner Kallweit return; 77279ed05e3SHeiner Kallweit } 77379ed05e3SHeiner Kallweit 77400412ddcSHeiner Kallweit if (data->blocks > 1) { 775a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_BLOCK_MODE; 7761231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_LENGTH_MASK, 7771231e7ebSHeiner Kallweit data->blocks); 7783d03f6a9SHeiner Kallweit meson_mmc_set_blksz(mmc, data->blksz); 77951c5d844SKevin Hilman } else { 7801231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_LENGTH_MASK, data->blksz); 78151c5d844SKevin Hilman } 78251c5d844SKevin Hilman 78300412ddcSHeiner Kallweit xfer_bytes = data->blksz * data->blocks; 78400412ddcSHeiner Kallweit if (data->flags & MMC_DATA_WRITE) { 785a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_DATA_WR; 78651c5d844SKevin Hilman WARN_ON(xfer_bytes > host->bounce_buf_size); 78700412ddcSHeiner Kallweit sg_copy_to_buffer(data->sg, data->sg_len, 78851c5d844SKevin Hilman host->bounce_buf, xfer_bytes); 78951c5d844SKevin Hilman dma_wmb(); 79051c5d844SKevin Hilman } 79151c5d844SKevin Hilman 792a322febeSHeiner Kallweit cmd_data = host->bounce_dma_addr & CMD_DATA_MASK; 79351c5d844SKevin Hilman } else { 7941231e7ebSHeiner Kallweit cmd_cfg |= FIELD_PREP(CMD_CFG_TIMEOUT_MASK, 7951231e7ebSHeiner Kallweit ilog2(SD_EMMC_CMD_TIMEOUT)); 79651c5d844SKevin Hilman } 79751c5d844SKevin Hilman 79851c5d844SKevin Hilman /* Last descriptor */ 799a322febeSHeiner Kallweit cmd_cfg |= CMD_CFG_END_OF_CHAIN; 800a322febeSHeiner Kallweit writel(cmd_cfg, host->regs + SD_EMMC_CMD_CFG); 801a322febeSHeiner Kallweit writel(cmd_data, host->regs + SD_EMMC_CMD_DAT); 802a322febeSHeiner Kallweit writel(0, host->regs + SD_EMMC_CMD_RSP); 80351c5d844SKevin Hilman wmb(); /* ensure descriptor is written before kicked */ 804a322febeSHeiner Kallweit writel(cmd->arg, host->regs + SD_EMMC_CMD_ARG); 80551c5d844SKevin Hilman } 80651c5d844SKevin Hilman 80751c5d844SKevin Hilman static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 80851c5d844SKevin Hilman { 80951c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 81079ed05e3SHeiner Kallweit bool needs_pre_post_req = mrq->data && 81179ed05e3SHeiner Kallweit !(mrq->data->host_cookie & SD_EMMC_PRE_REQ_DONE); 81279ed05e3SHeiner Kallweit 81379ed05e3SHeiner Kallweit if (needs_pre_post_req) { 81479ed05e3SHeiner Kallweit meson_mmc_get_transfer_mode(mmc, mrq); 81579ed05e3SHeiner Kallweit if (!meson_mmc_desc_chain_mode(mrq->data)) 81679ed05e3SHeiner Kallweit needs_pre_post_req = false; 81779ed05e3SHeiner Kallweit } 81879ed05e3SHeiner Kallweit 81979ed05e3SHeiner Kallweit if (needs_pre_post_req) 82079ed05e3SHeiner Kallweit meson_mmc_pre_req(mmc, mrq); 82151c5d844SKevin Hilman 82251c5d844SKevin Hilman /* Stop execution */ 82351c5d844SKevin Hilman writel(0, host->regs + SD_EMMC_START); 82451c5d844SKevin Hilman 82579ed05e3SHeiner Kallweit meson_mmc_start_cmd(mmc, mrq->sbc ?: mrq->cmd); 82679ed05e3SHeiner Kallweit 82779ed05e3SHeiner Kallweit if (needs_pre_post_req) 82879ed05e3SHeiner Kallweit meson_mmc_post_req(mmc, mrq, 0); 82951c5d844SKevin Hilman } 83051c5d844SKevin Hilman 8313d6c991bSHeiner Kallweit static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) 83251c5d844SKevin Hilman { 83351c5d844SKevin Hilman struct meson_host *host = mmc_priv(mmc); 83451c5d844SKevin Hilman 83551c5d844SKevin Hilman if (cmd->flags & MMC_RSP_136) { 83651c5d844SKevin Hilman cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP3); 83751c5d844SKevin Hilman cmd->resp[1] = readl(host->regs + SD_EMMC_CMD_RSP2); 83851c5d844SKevin Hilman cmd->resp[2] = readl(host->regs + SD_EMMC_CMD_RSP1); 83951c5d844SKevin Hilman cmd->resp[3] = readl(host->regs + SD_EMMC_CMD_RSP); 84051c5d844SKevin Hilman } else if (cmd->flags & MMC_RSP_PRESENT) { 84151c5d844SKevin Hilman cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP); 84251c5d844SKevin Hilman } 84351c5d844SKevin Hilman } 84451c5d844SKevin Hilman 84551c5d844SKevin Hilman static irqreturn_t meson_mmc_irq(int irq, void *dev_id) 84651c5d844SKevin Hilman { 84751c5d844SKevin Hilman struct meson_host *host = dev_id; 84819a91dd4SHeinrich Schuchardt struct mmc_command *cmd; 8492c8d96a4SHeiner Kallweit struct mmc_data *data; 85051c5d844SKevin Hilman u32 irq_en, status, raw_status; 85174858655SJerome Brunet irqreturn_t ret = IRQ_NONE; 85251c5d844SKevin Hilman 85318f92bc0SJerome Brunet irq_en = readl(host->regs + SD_EMMC_IRQ_EN); 85418f92bc0SJerome Brunet raw_status = readl(host->regs + SD_EMMC_STATUS); 85518f92bc0SJerome Brunet status = raw_status & irq_en; 85618f92bc0SJerome Brunet 85718f92bc0SJerome Brunet if (!status) { 85818f92bc0SJerome Brunet dev_dbg(host->dev, 85918f92bc0SJerome Brunet "Unexpected IRQ! irq_en 0x%08x - status 0x%08x\n", 86018f92bc0SJerome Brunet irq_en, raw_status); 86118f92bc0SJerome Brunet return IRQ_NONE; 86218f92bc0SJerome Brunet } 86318f92bc0SJerome Brunet 86474858655SJerome Brunet if (WARN_ON(!host) || WARN_ON(!host->cmd)) 86551c5d844SKevin Hilman return IRQ_NONE; 86651c5d844SKevin Hilman 867c2c1e63aSJerome Brunet /* ack all raised interrupts */ 868c2c1e63aSJerome Brunet writel(status, host->regs + SD_EMMC_STATUS); 869c2c1e63aSJerome Brunet 87074858655SJerome Brunet cmd = host->cmd; 87174858655SJerome Brunet data = cmd->data; 87274858655SJerome Brunet cmd->error = 0; 87374858655SJerome Brunet if (status & IRQ_CRC_ERR) { 87474858655SJerome Brunet dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status); 87574858655SJerome Brunet cmd->error = -EILSEQ; 87618f92bc0SJerome Brunet ret = IRQ_WAKE_THREAD; 87774858655SJerome Brunet goto out; 87874858655SJerome Brunet } 87974858655SJerome Brunet 88074858655SJerome Brunet if (status & IRQ_TIMEOUTS) { 88174858655SJerome Brunet dev_dbg(host->dev, "Timeout - status 0x%08x\n", status); 88274858655SJerome Brunet cmd->error = -ETIMEDOUT; 88318f92bc0SJerome Brunet ret = IRQ_WAKE_THREAD; 88451c5d844SKevin Hilman goto out; 88551c5d844SKevin Hilman } 88651c5d844SKevin Hilman 8871f8066d9SHeiner Kallweit meson_mmc_read_resp(host->mmc, cmd); 8881f8066d9SHeiner Kallweit 88974858655SJerome Brunet if (status & IRQ_SDIO) { 89074858655SJerome Brunet dev_dbg(host->dev, "IRQ: SDIO TODO.\n"); 89174858655SJerome Brunet ret = IRQ_HANDLED; 89251c5d844SKevin Hilman } 89351c5d844SKevin Hilman 8942c8d96a4SHeiner Kallweit if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) { 8952c8d96a4SHeiner Kallweit if (data && !cmd->error) 8962c8d96a4SHeiner Kallweit data->bytes_xfered = data->blksz * data->blocks; 89779ed05e3SHeiner Kallweit if (meson_mmc_bounce_buf_read(data) || 89879ed05e3SHeiner Kallweit meson_mmc_get_next_command(cmd)) 89951c5d844SKevin Hilman ret = IRQ_WAKE_THREAD; 90074858655SJerome Brunet else 90174858655SJerome Brunet ret = IRQ_HANDLED; 90251c5d844SKevin Hilman } 90351c5d844SKevin Hilman 90451c5d844SKevin Hilman out: 90518f92bc0SJerome Brunet if (cmd->error) { 90618f92bc0SJerome Brunet /* Stop desc in case of errors */ 90718f92bc0SJerome Brunet u32 start = readl(host->regs + SD_EMMC_START); 90818f92bc0SJerome Brunet 90918f92bc0SJerome Brunet start &= ~START_DESC_BUSY; 91018f92bc0SJerome Brunet writel(start, host->regs + SD_EMMC_START); 91118f92bc0SJerome Brunet } 91218f92bc0SJerome Brunet 9131f8066d9SHeiner Kallweit if (ret == IRQ_HANDLED) 91451c5d844SKevin Hilman meson_mmc_request_done(host->mmc, cmd->mrq); 91551c5d844SKevin Hilman 91651c5d844SKevin Hilman return ret; 91751c5d844SKevin Hilman } 91851c5d844SKevin Hilman 91918f92bc0SJerome Brunet static int meson_mmc_wait_desc_stop(struct meson_host *host) 92018f92bc0SJerome Brunet { 92118f92bc0SJerome Brunet u32 status; 92218f92bc0SJerome Brunet 92318f92bc0SJerome Brunet /* 92418f92bc0SJerome Brunet * It may sometimes take a while for it to actually halt. Here, we 92518f92bc0SJerome Brunet * are giving it 5ms to comply 92618f92bc0SJerome Brunet * 92718f92bc0SJerome Brunet * If we don't confirm the descriptor is stopped, it might raise new 92818f92bc0SJerome Brunet * IRQs after we have called mmc_request_done() which is bad. 92918f92bc0SJerome Brunet */ 93018f92bc0SJerome Brunet 93198849da6SJerome Brunet return readl_poll_timeout(host->regs + SD_EMMC_STATUS, status, 93298849da6SJerome Brunet !(status & (STATUS_BUSY | STATUS_DESC_BUSY)), 93398849da6SJerome Brunet 100, 5000); 93418f92bc0SJerome Brunet } 93518f92bc0SJerome Brunet 93651c5d844SKevin Hilman static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) 93751c5d844SKevin Hilman { 93851c5d844SKevin Hilman struct meson_host *host = dev_id; 939e5e4a3ebSHeiner Kallweit struct mmc_command *next_cmd, *cmd = host->cmd; 94051c5d844SKevin Hilman struct mmc_data *data; 94151c5d844SKevin Hilman unsigned int xfer_bytes; 94251c5d844SKevin Hilman 94351c5d844SKevin Hilman if (WARN_ON(!cmd)) 94419a91dd4SHeinrich Schuchardt return IRQ_NONE; 94551c5d844SKevin Hilman 94618f92bc0SJerome Brunet if (cmd->error) { 94718f92bc0SJerome Brunet meson_mmc_wait_desc_stop(host); 94818f92bc0SJerome Brunet meson_mmc_request_done(host->mmc, cmd->mrq); 94918f92bc0SJerome Brunet 95018f92bc0SJerome Brunet return IRQ_HANDLED; 95118f92bc0SJerome Brunet } 95218f92bc0SJerome Brunet 95351c5d844SKevin Hilman data = cmd->data; 95479ed05e3SHeiner Kallweit if (meson_mmc_bounce_buf_read(data)) { 95551c5d844SKevin Hilman xfer_bytes = data->blksz * data->blocks; 95651c5d844SKevin Hilman WARN_ON(xfer_bytes > host->bounce_buf_size); 95751c5d844SKevin Hilman sg_copy_from_buffer(data->sg, data->sg_len, 95851c5d844SKevin Hilman host->bounce_buf, xfer_bytes); 95951c5d844SKevin Hilman } 96051c5d844SKevin Hilman 961e5e4a3ebSHeiner Kallweit next_cmd = meson_mmc_get_next_command(cmd); 962e5e4a3ebSHeiner Kallweit if (next_cmd) 963e5e4a3ebSHeiner Kallweit meson_mmc_start_cmd(host->mmc, next_cmd); 96451c5d844SKevin Hilman else 965e5e4a3ebSHeiner Kallweit meson_mmc_request_done(host->mmc, cmd->mrq); 96651c5d844SKevin Hilman 967690f90b6SHeiner Kallweit return IRQ_HANDLED; 96851c5d844SKevin Hilman } 96951c5d844SKevin Hilman 97051c5d844SKevin Hilman /* 97151c5d844SKevin Hilman * NOTE: we only need this until the GPIO/pinctrl driver can handle 97251c5d844SKevin Hilman * interrupts. For now, the MMC core will use this for polling. 97351c5d844SKevin Hilman */ 97451c5d844SKevin Hilman static int meson_mmc_get_cd(struct mmc_host *mmc) 97551c5d844SKevin Hilman { 97651c5d844SKevin Hilman int status = mmc_gpio_get_cd(mmc); 97751c5d844SKevin Hilman 97851c5d844SKevin Hilman if (status == -ENOSYS) 97951c5d844SKevin Hilman return 1; /* assume present */ 98051c5d844SKevin Hilman 98151c5d844SKevin Hilman return status; 98251c5d844SKevin Hilman } 98351c5d844SKevin Hilman 984c01d1219SHeiner Kallweit static void meson_mmc_cfg_init(struct meson_host *host) 985c01d1219SHeiner Kallweit { 98671e3e00cSAndreas Fenkart u32 cfg = 0; 987c01d1219SHeiner Kallweit 9881231e7ebSHeiner Kallweit cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK, 9891231e7ebSHeiner Kallweit ilog2(SD_EMMC_CFG_RESP_TIMEOUT)); 9901231e7ebSHeiner Kallweit cfg |= FIELD_PREP(CFG_RC_CC_MASK, ilog2(SD_EMMC_CFG_CMD_GAP)); 9911231e7ebSHeiner Kallweit cfg |= FIELD_PREP(CFG_BLK_LEN_MASK, ilog2(SD_EMMC_CFG_BLK_SIZE)); 992c01d1219SHeiner Kallweit 99318f92bc0SJerome Brunet /* abort chain on R/W errors */ 99418f92bc0SJerome Brunet cfg |= CFG_ERR_ABORT; 99518f92bc0SJerome Brunet 996c01d1219SHeiner Kallweit writel(cfg, host->regs + SD_EMMC_CFG); 997c01d1219SHeiner Kallweit } 998c01d1219SHeiner Kallweit 999186cd8b7SJerome Brunet static int meson_mmc_card_busy(struct mmc_host *mmc) 1000186cd8b7SJerome Brunet { 1001186cd8b7SJerome Brunet struct meson_host *host = mmc_priv(mmc); 1002186cd8b7SJerome Brunet u32 regval; 1003186cd8b7SJerome Brunet 1004186cd8b7SJerome Brunet regval = readl(host->regs + SD_EMMC_STATUS); 1005186cd8b7SJerome Brunet 1006186cd8b7SJerome Brunet /* We are only interrested in lines 0 to 3, so mask the other ones */ 1007186cd8b7SJerome Brunet return !(FIELD_GET(STATUS_DATI, regval) & 0xf); 1008186cd8b7SJerome Brunet } 1009186cd8b7SJerome Brunet 1010b1231b2fSJerome Brunet static int meson_mmc_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) 1011b1231b2fSJerome Brunet { 10129cbe0fc8SMarek Vasut int ret; 10139cbe0fc8SMarek Vasut 1014b1231b2fSJerome Brunet /* vqmmc regulator is available */ 1015b1231b2fSJerome Brunet if (!IS_ERR(mmc->supply.vqmmc)) { 1016b1231b2fSJerome Brunet /* 1017b1231b2fSJerome Brunet * The usual amlogic setup uses a GPIO to switch from one 1018b1231b2fSJerome Brunet * regulator to the other. While the voltage ramp up is 1019b1231b2fSJerome Brunet * pretty fast, care must be taken when switching from 3.3v 1020b1231b2fSJerome Brunet * to 1.8v. Please make sure the regulator framework is aware 1021b1231b2fSJerome Brunet * of your own regulator constraints 1022b1231b2fSJerome Brunet */ 10239cbe0fc8SMarek Vasut ret = mmc_regulator_set_vqmmc(mmc, ios); 10249cbe0fc8SMarek Vasut return ret < 0 ? ret : 0; 1025b1231b2fSJerome Brunet } 1026b1231b2fSJerome Brunet 1027b1231b2fSJerome Brunet /* no vqmmc regulator, assume fixed regulator at 3/3.3V */ 1028b1231b2fSJerome Brunet if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) 1029b1231b2fSJerome Brunet return 0; 1030b1231b2fSJerome Brunet 1031b1231b2fSJerome Brunet return -EINVAL; 1032b1231b2fSJerome Brunet } 1033b1231b2fSJerome Brunet 103451c5d844SKevin Hilman static const struct mmc_host_ops meson_mmc_ops = { 103551c5d844SKevin Hilman .request = meson_mmc_request, 103651c5d844SKevin Hilman .set_ios = meson_mmc_set_ios, 103751c5d844SKevin Hilman .get_cd = meson_mmc_get_cd, 103879ed05e3SHeiner Kallweit .pre_req = meson_mmc_pre_req, 103979ed05e3SHeiner Kallweit .post_req = meson_mmc_post_req, 1040f50b7ac5SJerome Brunet .execute_tuning = meson_mmc_resampling_tuning, 1041186cd8b7SJerome Brunet .card_busy = meson_mmc_card_busy, 1042b1231b2fSJerome Brunet .start_signal_voltage_switch = meson_mmc_voltage_switch, 104351c5d844SKevin Hilman }; 104451c5d844SKevin Hilman 104551c5d844SKevin Hilman static int meson_mmc_probe(struct platform_device *pdev) 104651c5d844SKevin Hilman { 104751c5d844SKevin Hilman struct resource *res; 104851c5d844SKevin Hilman struct meson_host *host; 104951c5d844SKevin Hilman struct mmc_host *mmc; 1050bb364890SRemi Pommarel int ret; 105151c5d844SKevin Hilman 105251c5d844SKevin Hilman mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev); 105351c5d844SKevin Hilman if (!mmc) 105451c5d844SKevin Hilman return -ENOMEM; 105551c5d844SKevin Hilman host = mmc_priv(mmc); 105651c5d844SKevin Hilman host->mmc = mmc; 105751c5d844SKevin Hilman host->dev = &pdev->dev; 105851c5d844SKevin Hilman dev_set_drvdata(&pdev->dev, host); 105951c5d844SKevin Hilman 1060acdc8e71SNeil Armstrong /* The G12A SDIO Controller needs an SRAM bounce buffer */ 1061acdc8e71SNeil Armstrong host->dram_access_quirk = device_property_read_bool(&pdev->dev, 1062acdc8e71SNeil Armstrong "amlogic,dram-access-quirk"); 1063acdc8e71SNeil Armstrong 106451c5d844SKevin Hilman /* Get regulators and the supported OCR mask */ 106551c5d844SKevin Hilman host->vqmmc_enabled = false; 106651c5d844SKevin Hilman ret = mmc_regulator_get_supply(mmc); 1067fa54f3e3SWolfram Sang if (ret) 106851c5d844SKevin Hilman goto free_host; 106951c5d844SKevin Hilman 107051c5d844SKevin Hilman ret = mmc_of_parse(mmc); 107151c5d844SKevin Hilman if (ret) { 1072dc012058SKevin Hilman if (ret != -EPROBE_DEFER) 107351c5d844SKevin Hilman dev_warn(&pdev->dev, "error parsing DT: %d\n", ret); 107451c5d844SKevin Hilman goto free_host; 107551c5d844SKevin Hilman } 107651c5d844SKevin Hilman 1077df069815SNan Li host->data = (struct meson_mmc_data *) 1078df069815SNan Li of_device_get_match_data(&pdev->dev); 1079df069815SNan Li if (!host->data) { 1080df069815SNan Li ret = -EINVAL; 1081df069815SNan Li goto free_host; 1082df069815SNan Li } 1083df069815SNan Li 108419c6beaaSJerome Brunet ret = device_reset_optional(&pdev->dev); 108589280d09SKrzysztof Kozlowski if (ret) 108689280d09SKrzysztof Kozlowski return dev_err_probe(&pdev->dev, ret, "device reset failed\n"); 108719c6beaaSJerome Brunet 108851c5d844SKevin Hilman res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 108951c5d844SKevin Hilman host->regs = devm_ioremap_resource(&pdev->dev, res); 109051c5d844SKevin Hilman if (IS_ERR(host->regs)) { 109151c5d844SKevin Hilman ret = PTR_ERR(host->regs); 109251c5d844SKevin Hilman goto free_host; 109351c5d844SKevin Hilman } 109451c5d844SKevin Hilman 1095bb364890SRemi Pommarel host->irq = platform_get_irq(pdev, 0); 1096bb364890SRemi Pommarel if (host->irq <= 0) { 109751c5d844SKevin Hilman ret = -EINVAL; 109851c5d844SKevin Hilman goto free_host; 109951c5d844SKevin Hilman } 110051c5d844SKevin Hilman 11011e03331dSJerome Brunet host->pinctrl = devm_pinctrl_get(&pdev->dev); 11021e03331dSJerome Brunet if (IS_ERR(host->pinctrl)) { 11031e03331dSJerome Brunet ret = PTR_ERR(host->pinctrl); 11041e03331dSJerome Brunet goto free_host; 11051e03331dSJerome Brunet } 11061e03331dSJerome Brunet 11071e03331dSJerome Brunet host->pins_clk_gate = pinctrl_lookup_state(host->pinctrl, 11081e03331dSJerome Brunet "clk-gate"); 11091e03331dSJerome Brunet if (IS_ERR(host->pins_clk_gate)) { 11101e03331dSJerome Brunet dev_warn(&pdev->dev, 11111e03331dSJerome Brunet "can't get clk-gate pinctrl, using clk_stop bit\n"); 11121e03331dSJerome Brunet host->pins_clk_gate = NULL; 11131e03331dSJerome Brunet } 11141e03331dSJerome Brunet 111551c5d844SKevin Hilman host->core_clk = devm_clk_get(&pdev->dev, "core"); 111651c5d844SKevin Hilman if (IS_ERR(host->core_clk)) { 111751c5d844SKevin Hilman ret = PTR_ERR(host->core_clk); 111851c5d844SKevin Hilman goto free_host; 111951c5d844SKevin Hilman } 112051c5d844SKevin Hilman 112151c5d844SKevin Hilman ret = clk_prepare_enable(host->core_clk); 112251c5d844SKevin Hilman if (ret) 112351c5d844SKevin Hilman goto free_host; 112451c5d844SKevin Hilman 112551c5d844SKevin Hilman ret = meson_mmc_clk_init(host); 112651c5d844SKevin Hilman if (ret) 1127ce473d5bSMichał Zegan goto err_core_clk; 112851c5d844SKevin Hilman 11293c39e2caSJerome Brunet /* set config to sane default */ 11303c39e2caSJerome Brunet meson_mmc_cfg_init(host); 11313c39e2caSJerome Brunet 113251c5d844SKevin Hilman /* Stop execution */ 113351c5d844SKevin Hilman writel(0, host->regs + SD_EMMC_START); 113451c5d844SKevin Hilman 113574858655SJerome Brunet /* clear, ack and enable interrupts */ 113651c5d844SKevin Hilman writel(0, host->regs + SD_EMMC_IRQ_EN); 113774858655SJerome Brunet writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, 113874858655SJerome Brunet host->regs + SD_EMMC_STATUS); 113974858655SJerome Brunet writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, 114074858655SJerome Brunet host->regs + SD_EMMC_IRQ_EN); 114151c5d844SKevin Hilman 1142bb364890SRemi Pommarel ret = request_threaded_irq(host->irq, meson_mmc_irq, 1143eb4d8112SJerome Brunet meson_mmc_irq_thread, IRQF_ONESHOT, 114483e418a8SMartin Blumenstingl dev_name(&pdev->dev), host); 114551c5d844SKevin Hilman if (ret) 1146bd911ec4SJerome Brunet goto err_init_clk; 114751c5d844SKevin Hilman 1148e5e4a3ebSHeiner Kallweit mmc->caps |= MMC_CAP_CMD23; 1149acdc8e71SNeil Armstrong if (host->dram_access_quirk) { 115027a5e7d3SNeil Armstrong /* Limit segments to 1 due to low available sram memory */ 115127a5e7d3SNeil Armstrong mmc->max_segs = 1; 1152acdc8e71SNeil Armstrong /* Limit to the available sram memory */ 115327a5e7d3SNeil Armstrong mmc->max_blk_count = SD_EMMC_SRAM_DATA_BUF_LEN / 115427a5e7d3SNeil Armstrong mmc->max_blk_size; 1155acdc8e71SNeil Armstrong } else { 1156efe0b669SHeiner Kallweit mmc->max_blk_count = CMD_CFG_LENGTH_MASK; 1157acdc8e71SNeil Armstrong mmc->max_segs = SD_EMMC_DESC_BUF_LEN / 1158acdc8e71SNeil Armstrong sizeof(struct sd_emmc_desc); 1159acdc8e71SNeil Armstrong } 1160efe0b669SHeiner Kallweit mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; 116179ed05e3SHeiner Kallweit mmc->max_seg_size = mmc->max_req_size; 1162efe0b669SHeiner Kallweit 1163d5f758f2SJerome Brunet /* 1164d5f758f2SJerome Brunet * At the moment, we don't know how to reliably enable HS400. 1165d5f758f2SJerome Brunet * From the different datasheets, it is not even clear if this mode 1166d5f758f2SJerome Brunet * is officially supported by any of the SoCs 1167d5f758f2SJerome Brunet */ 1168d5f758f2SJerome Brunet mmc->caps2 &= ~MMC_CAP2_HS400; 1169d5f758f2SJerome Brunet 1170acdc8e71SNeil Armstrong if (host->dram_access_quirk) { 1171acdc8e71SNeil Armstrong /* 1172acdc8e71SNeil Armstrong * The MMC Controller embeds 1,5KiB of internal SRAM 1173acdc8e71SNeil Armstrong * that can be used to be used as bounce buffer. 1174acdc8e71SNeil Armstrong * In the case of the G12A SDIO controller, use these 1175acdc8e71SNeil Armstrong * instead of the DDR memory 1176acdc8e71SNeil Armstrong */ 1177acdc8e71SNeil Armstrong host->bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN; 1178acdc8e71SNeil Armstrong host->bounce_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF; 1179acdc8e71SNeil Armstrong host->bounce_dma_addr = res->start + SD_EMMC_SRAM_DATA_BUF_OFF; 1180acdc8e71SNeil Armstrong } else { 118151c5d844SKevin Hilman /* data bounce buffer */ 11824136fcb5SHeiner Kallweit host->bounce_buf_size = mmc->max_req_size; 118351c5d844SKevin Hilman host->bounce_buf = 118451c5d844SKevin Hilman dma_alloc_coherent(host->dev, host->bounce_buf_size, 118551c5d844SKevin Hilman &host->bounce_dma_addr, GFP_KERNEL); 118651c5d844SKevin Hilman if (host->bounce_buf == NULL) { 118751c5d844SKevin Hilman dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); 118851c5d844SKevin Hilman ret = -ENOMEM; 1189bb364890SRemi Pommarel goto err_free_irq; 119051c5d844SKevin Hilman } 1191acdc8e71SNeil Armstrong } 119251c5d844SKevin Hilman 119379ed05e3SHeiner Kallweit host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, 119479ed05e3SHeiner Kallweit &host->descs_dma_addr, GFP_KERNEL); 119579ed05e3SHeiner Kallweit if (!host->descs) { 119679ed05e3SHeiner Kallweit dev_err(host->dev, "Allocating descriptor DMA buffer failed\n"); 119779ed05e3SHeiner Kallweit ret = -ENOMEM; 119879ed05e3SHeiner Kallweit goto err_bounce_buf; 119979ed05e3SHeiner Kallweit } 120079ed05e3SHeiner Kallweit 120151c5d844SKevin Hilman mmc->ops = &meson_mmc_ops; 120251c5d844SKevin Hilman mmc_add_host(mmc); 120351c5d844SKevin Hilman 120451c5d844SKevin Hilman return 0; 120551c5d844SKevin Hilman 120679ed05e3SHeiner Kallweit err_bounce_buf: 1207acdc8e71SNeil Armstrong if (!host->dram_access_quirk) 120879ed05e3SHeiner Kallweit dma_free_coherent(host->dev, host->bounce_buf_size, 120979ed05e3SHeiner Kallweit host->bounce_buf, host->bounce_dma_addr); 1210bb364890SRemi Pommarel err_free_irq: 1211bb364890SRemi Pommarel free_irq(host->irq, host); 1212bd911ec4SJerome Brunet err_init_clk: 1213bd911ec4SJerome Brunet clk_disable_unprepare(host->mmc_clk); 1214ce473d5bSMichał Zegan err_core_clk: 121551c5d844SKevin Hilman clk_disable_unprepare(host->core_clk); 1216ce473d5bSMichał Zegan free_host: 121751c5d844SKevin Hilman mmc_free_host(mmc); 121851c5d844SKevin Hilman return ret; 121951c5d844SKevin Hilman } 122051c5d844SKevin Hilman 122151c5d844SKevin Hilman static int meson_mmc_remove(struct platform_device *pdev) 122251c5d844SKevin Hilman { 122351c5d844SKevin Hilman struct meson_host *host = dev_get_drvdata(&pdev->dev); 122451c5d844SKevin Hilman 1225a01fc2a2SMichał Zegan mmc_remove_host(host->mmc); 1226a01fc2a2SMichał Zegan 122792763b99SHeiner Kallweit /* disable interrupts */ 122892763b99SHeiner Kallweit writel(0, host->regs + SD_EMMC_IRQ_EN); 1229bb364890SRemi Pommarel free_irq(host->irq, host); 123092763b99SHeiner Kallweit 123179ed05e3SHeiner Kallweit dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, 123279ed05e3SHeiner Kallweit host->descs, host->descs_dma_addr); 1233acdc8e71SNeil Armstrong 1234acdc8e71SNeil Armstrong if (!host->dram_access_quirk) 123551c5d844SKevin Hilman dma_free_coherent(host->dev, host->bounce_buf_size, 123651c5d844SKevin Hilman host->bounce_buf, host->bounce_dma_addr); 123751c5d844SKevin Hilman 1238bd911ec4SJerome Brunet clk_disable_unprepare(host->mmc_clk); 123951c5d844SKevin Hilman clk_disable_unprepare(host->core_clk); 124051c5d844SKevin Hilman 124151c5d844SKevin Hilman mmc_free_host(host->mmc); 124251c5d844SKevin Hilman return 0; 124351c5d844SKevin Hilman } 124451c5d844SKevin Hilman 1245df069815SNan Li static const struct meson_mmc_data meson_gx_data = { 1246df069815SNan Li .tx_delay_mask = CLK_V2_TX_DELAY_MASK, 1247df069815SNan Li .rx_delay_mask = CLK_V2_RX_DELAY_MASK, 1248df069815SNan Li .always_on = CLK_V2_ALWAYS_ON, 124971645e65SJerome Brunet .adjust = SD_EMMC_ADJUST, 1250df069815SNan Li }; 1251df069815SNan Li 1252df069815SNan Li static const struct meson_mmc_data meson_axg_data = { 1253df069815SNan Li .tx_delay_mask = CLK_V3_TX_DELAY_MASK, 1254df069815SNan Li .rx_delay_mask = CLK_V3_RX_DELAY_MASK, 1255df069815SNan Li .always_on = CLK_V3_ALWAYS_ON, 125671645e65SJerome Brunet .adjust = SD_EMMC_V3_ADJUST, 1257df069815SNan Li }; 1258df069815SNan Li 125951c5d844SKevin Hilman static const struct of_device_id meson_mmc_of_match[] = { 1260df069815SNan Li { .compatible = "amlogic,meson-gx-mmc", .data = &meson_gx_data }, 1261df069815SNan Li { .compatible = "amlogic,meson-gxbb-mmc", .data = &meson_gx_data }, 1262df069815SNan Li { .compatible = "amlogic,meson-gxl-mmc", .data = &meson_gx_data }, 1263df069815SNan Li { .compatible = "amlogic,meson-gxm-mmc", .data = &meson_gx_data }, 1264df069815SNan Li { .compatible = "amlogic,meson-axg-mmc", .data = &meson_axg_data }, 126551c5d844SKevin Hilman {} 126651c5d844SKevin Hilman }; 126751c5d844SKevin Hilman MODULE_DEVICE_TABLE(of, meson_mmc_of_match); 126851c5d844SKevin Hilman 126951c5d844SKevin Hilman static struct platform_driver meson_mmc_driver = { 127051c5d844SKevin Hilman .probe = meson_mmc_probe, 127151c5d844SKevin Hilman .remove = meson_mmc_remove, 127251c5d844SKevin Hilman .driver = { 127351c5d844SKevin Hilman .name = DRIVER_NAME, 12747320915cSDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS, 1275e2c01e91SKrzysztof Kozlowski .of_match_table = meson_mmc_of_match, 127651c5d844SKevin Hilman }, 127751c5d844SKevin Hilman }; 127851c5d844SKevin Hilman 127951c5d844SKevin Hilman module_platform_driver(meson_mmc_driver); 128051c5d844SKevin Hilman 1281e79dc1b4SNan Li MODULE_DESCRIPTION("Amlogic S905*/GX*/AXG SD/eMMC driver"); 128251c5d844SKevin Hilman MODULE_AUTHOR("Kevin Hilman <khilman@baylibre.com>"); 128351c5d844SKevin Hilman MODULE_LICENSE("GPL v2"); 1284