162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for sunxi SD/MMC host controllers 462306a36Sopenharmony_ci * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. 562306a36Sopenharmony_ci * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com> 662306a36Sopenharmony_ci * (C) Copyright 2013-2014 O2S GmbH <www.o2s.ch> 762306a36Sopenharmony_ci * (C) Copyright 2013-2014 David Lanzendörfer <david.lanzendoerfer@o2s.ch> 862306a36Sopenharmony_ci * (C) Copyright 2013-2014 Hans de Goede <hdegoede@redhat.com> 962306a36Sopenharmony_ci * (C) Copyright 2017 Sootech SA 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/clk.h> 1362306a36Sopenharmony_ci#include <linux/clk/sunxi-ng.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/device.h> 1662306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1762306a36Sopenharmony_ci#include <linux/err.h> 1862306a36Sopenharmony_ci#include <linux/interrupt.h> 1962306a36Sopenharmony_ci#include <linux/io.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include <linux/mmc/card.h> 2262306a36Sopenharmony_ci#include <linux/mmc/core.h> 2362306a36Sopenharmony_ci#include <linux/mmc/host.h> 2462306a36Sopenharmony_ci#include <linux/mmc/mmc.h> 2562306a36Sopenharmony_ci#include <linux/mmc/sd.h> 2662306a36Sopenharmony_ci#include <linux/mmc/sdio.h> 2762306a36Sopenharmony_ci#include <linux/mmc/slot-gpio.h> 2862306a36Sopenharmony_ci#include <linux/module.h> 2962306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 3062306a36Sopenharmony_ci#include <linux/of_address.h> 3162306a36Sopenharmony_ci#include <linux/of_platform.h> 3262306a36Sopenharmony_ci#include <linux/platform_device.h> 3362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 3462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 3562306a36Sopenharmony_ci#include <linux/reset.h> 3662306a36Sopenharmony_ci#include <linux/scatterlist.h> 3762306a36Sopenharmony_ci#include <linux/slab.h> 3862306a36Sopenharmony_ci#include <linux/spinlock.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* register offset definitions */ 4162306a36Sopenharmony_ci#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */ 4262306a36Sopenharmony_ci#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */ 4362306a36Sopenharmony_ci#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */ 4462306a36Sopenharmony_ci#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */ 4562306a36Sopenharmony_ci#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */ 4662306a36Sopenharmony_ci#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */ 4762306a36Sopenharmony_ci#define SDXC_REG_CMDR (0x18) /* SMC Command Register */ 4862306a36Sopenharmony_ci#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */ 4962306a36Sopenharmony_ci#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */ 5062306a36Sopenharmony_ci#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */ 5162306a36Sopenharmony_ci#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */ 5262306a36Sopenharmony_ci#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */ 5362306a36Sopenharmony_ci#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */ 5462306a36Sopenharmony_ci#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ 5562306a36Sopenharmony_ci#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ 5662306a36Sopenharmony_ci#define SDXC_REG_STAS (0x3C) /* SMC Status Register */ 5762306a36Sopenharmony_ci#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ 5862306a36Sopenharmony_ci#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ 5962306a36Sopenharmony_ci#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ 6062306a36Sopenharmony_ci#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ 6162306a36Sopenharmony_ci#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ 6262306a36Sopenharmony_ci#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ 6362306a36Sopenharmony_ci#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ 6462306a36Sopenharmony_ci#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ 6562306a36Sopenharmony_ci#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ 6662306a36Sopenharmony_ci#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ 6762306a36Sopenharmony_ci#define SDXC_REG_CHDA (0x90) 6862306a36Sopenharmony_ci#define SDXC_REG_CBDA (0x94) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* New registers introduced in A64 */ 7162306a36Sopenharmony_ci#define SDXC_REG_A12A 0x058 /* SMC Auto Command 12 Register */ 7262306a36Sopenharmony_ci#define SDXC_REG_SD_NTSR 0x05C /* SMC New Timing Set Register */ 7362306a36Sopenharmony_ci#define SDXC_REG_DRV_DL 0x140 /* Drive Delay Control Register */ 7462306a36Sopenharmony_ci#define SDXC_REG_SAMP_DL_REG 0x144 /* SMC sample delay control */ 7562306a36Sopenharmony_ci#define SDXC_REG_DS_DL_REG 0x148 /* SMC data strobe delay control */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define mmc_readl(host, reg) \ 7862306a36Sopenharmony_ci readl((host)->reg_base + SDXC_##reg) 7962306a36Sopenharmony_ci#define mmc_writel(host, reg, value) \ 8062306a36Sopenharmony_ci writel((value), (host)->reg_base + SDXC_##reg) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* global control register bits */ 8362306a36Sopenharmony_ci#define SDXC_SOFT_RESET BIT(0) 8462306a36Sopenharmony_ci#define SDXC_FIFO_RESET BIT(1) 8562306a36Sopenharmony_ci#define SDXC_DMA_RESET BIT(2) 8662306a36Sopenharmony_ci#define SDXC_INTERRUPT_ENABLE_BIT BIT(4) 8762306a36Sopenharmony_ci#define SDXC_DMA_ENABLE_BIT BIT(5) 8862306a36Sopenharmony_ci#define SDXC_DEBOUNCE_ENABLE_BIT BIT(8) 8962306a36Sopenharmony_ci#define SDXC_POSEDGE_LATCH_DATA BIT(9) 9062306a36Sopenharmony_ci#define SDXC_DDR_MODE BIT(10) 9162306a36Sopenharmony_ci#define SDXC_MEMORY_ACCESS_DONE BIT(29) 9262306a36Sopenharmony_ci#define SDXC_ACCESS_DONE_DIRECT BIT(30) 9362306a36Sopenharmony_ci#define SDXC_ACCESS_BY_AHB BIT(31) 9462306a36Sopenharmony_ci#define SDXC_ACCESS_BY_DMA (0 << 31) 9562306a36Sopenharmony_ci#define SDXC_HARDWARE_RESET \ 9662306a36Sopenharmony_ci (SDXC_SOFT_RESET | SDXC_FIFO_RESET | SDXC_DMA_RESET) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* clock control bits */ 9962306a36Sopenharmony_ci#define SDXC_MASK_DATA0 BIT(31) 10062306a36Sopenharmony_ci#define SDXC_CARD_CLOCK_ON BIT(16) 10162306a36Sopenharmony_ci#define SDXC_LOW_POWER_ON BIT(17) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* bus width */ 10462306a36Sopenharmony_ci#define SDXC_WIDTH1 0 10562306a36Sopenharmony_ci#define SDXC_WIDTH4 1 10662306a36Sopenharmony_ci#define SDXC_WIDTH8 2 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* smc command bits */ 10962306a36Sopenharmony_ci#define SDXC_RESP_EXPIRE BIT(6) 11062306a36Sopenharmony_ci#define SDXC_LONG_RESPONSE BIT(7) 11162306a36Sopenharmony_ci#define SDXC_CHECK_RESPONSE_CRC BIT(8) 11262306a36Sopenharmony_ci#define SDXC_DATA_EXPIRE BIT(9) 11362306a36Sopenharmony_ci#define SDXC_WRITE BIT(10) 11462306a36Sopenharmony_ci#define SDXC_SEQUENCE_MODE BIT(11) 11562306a36Sopenharmony_ci#define SDXC_SEND_AUTO_STOP BIT(12) 11662306a36Sopenharmony_ci#define SDXC_WAIT_PRE_OVER BIT(13) 11762306a36Sopenharmony_ci#define SDXC_STOP_ABORT_CMD BIT(14) 11862306a36Sopenharmony_ci#define SDXC_SEND_INIT_SEQUENCE BIT(15) 11962306a36Sopenharmony_ci#define SDXC_UPCLK_ONLY BIT(21) 12062306a36Sopenharmony_ci#define SDXC_READ_CEATA_DEV BIT(22) 12162306a36Sopenharmony_ci#define SDXC_CCS_EXPIRE BIT(23) 12262306a36Sopenharmony_ci#define SDXC_ENABLE_BIT_BOOT BIT(24) 12362306a36Sopenharmony_ci#define SDXC_ALT_BOOT_OPTIONS BIT(25) 12462306a36Sopenharmony_ci#define SDXC_BOOT_ACK_EXPIRE BIT(26) 12562306a36Sopenharmony_ci#define SDXC_BOOT_ABORT BIT(27) 12662306a36Sopenharmony_ci#define SDXC_VOLTAGE_SWITCH BIT(28) 12762306a36Sopenharmony_ci#define SDXC_USE_HOLD_REGISTER BIT(29) 12862306a36Sopenharmony_ci#define SDXC_START BIT(31) 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* interrupt bits */ 13162306a36Sopenharmony_ci#define SDXC_RESP_ERROR BIT(1) 13262306a36Sopenharmony_ci#define SDXC_COMMAND_DONE BIT(2) 13362306a36Sopenharmony_ci#define SDXC_DATA_OVER BIT(3) 13462306a36Sopenharmony_ci#define SDXC_TX_DATA_REQUEST BIT(4) 13562306a36Sopenharmony_ci#define SDXC_RX_DATA_REQUEST BIT(5) 13662306a36Sopenharmony_ci#define SDXC_RESP_CRC_ERROR BIT(6) 13762306a36Sopenharmony_ci#define SDXC_DATA_CRC_ERROR BIT(7) 13862306a36Sopenharmony_ci#define SDXC_RESP_TIMEOUT BIT(8) 13962306a36Sopenharmony_ci#define SDXC_DATA_TIMEOUT BIT(9) 14062306a36Sopenharmony_ci#define SDXC_VOLTAGE_CHANGE_DONE BIT(10) 14162306a36Sopenharmony_ci#define SDXC_FIFO_RUN_ERROR BIT(11) 14262306a36Sopenharmony_ci#define SDXC_HARD_WARE_LOCKED BIT(12) 14362306a36Sopenharmony_ci#define SDXC_START_BIT_ERROR BIT(13) 14462306a36Sopenharmony_ci#define SDXC_AUTO_COMMAND_DONE BIT(14) 14562306a36Sopenharmony_ci#define SDXC_END_BIT_ERROR BIT(15) 14662306a36Sopenharmony_ci#define SDXC_SDIO_INTERRUPT BIT(16) 14762306a36Sopenharmony_ci#define SDXC_CARD_INSERT BIT(30) 14862306a36Sopenharmony_ci#define SDXC_CARD_REMOVE BIT(31) 14962306a36Sopenharmony_ci#define SDXC_INTERRUPT_ERROR_BIT \ 15062306a36Sopenharmony_ci (SDXC_RESP_ERROR | SDXC_RESP_CRC_ERROR | SDXC_DATA_CRC_ERROR | \ 15162306a36Sopenharmony_ci SDXC_RESP_TIMEOUT | SDXC_DATA_TIMEOUT | SDXC_FIFO_RUN_ERROR | \ 15262306a36Sopenharmony_ci SDXC_HARD_WARE_LOCKED | SDXC_START_BIT_ERROR | SDXC_END_BIT_ERROR) 15362306a36Sopenharmony_ci#define SDXC_INTERRUPT_DONE_BIT \ 15462306a36Sopenharmony_ci (SDXC_AUTO_COMMAND_DONE | SDXC_DATA_OVER | \ 15562306a36Sopenharmony_ci SDXC_COMMAND_DONE | SDXC_VOLTAGE_CHANGE_DONE) 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* status */ 15862306a36Sopenharmony_ci#define SDXC_RXWL_FLAG BIT(0) 15962306a36Sopenharmony_ci#define SDXC_TXWL_FLAG BIT(1) 16062306a36Sopenharmony_ci#define SDXC_FIFO_EMPTY BIT(2) 16162306a36Sopenharmony_ci#define SDXC_FIFO_FULL BIT(3) 16262306a36Sopenharmony_ci#define SDXC_CARD_PRESENT BIT(8) 16362306a36Sopenharmony_ci#define SDXC_CARD_DATA_BUSY BIT(9) 16462306a36Sopenharmony_ci#define SDXC_DATA_FSM_BUSY BIT(10) 16562306a36Sopenharmony_ci#define SDXC_DMA_REQUEST BIT(31) 16662306a36Sopenharmony_ci#define SDXC_FIFO_SIZE 16 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/* Function select */ 16962306a36Sopenharmony_ci#define SDXC_CEATA_ON (0xceaa << 16) 17062306a36Sopenharmony_ci#define SDXC_SEND_IRQ_RESPONSE BIT(0) 17162306a36Sopenharmony_ci#define SDXC_SDIO_READ_WAIT BIT(1) 17262306a36Sopenharmony_ci#define SDXC_ABORT_READ_DATA BIT(2) 17362306a36Sopenharmony_ci#define SDXC_SEND_CCSD BIT(8) 17462306a36Sopenharmony_ci#define SDXC_SEND_AUTO_STOPCCSD BIT(9) 17562306a36Sopenharmony_ci#define SDXC_CEATA_DEV_IRQ_ENABLE BIT(10) 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/* IDMA controller bus mod bit field */ 17862306a36Sopenharmony_ci#define SDXC_IDMAC_SOFT_RESET BIT(0) 17962306a36Sopenharmony_ci#define SDXC_IDMAC_FIX_BURST BIT(1) 18062306a36Sopenharmony_ci#define SDXC_IDMAC_IDMA_ON BIT(7) 18162306a36Sopenharmony_ci#define SDXC_IDMAC_REFETCH_DES BIT(31) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* IDMA status bit field */ 18462306a36Sopenharmony_ci#define SDXC_IDMAC_TRANSMIT_INTERRUPT BIT(0) 18562306a36Sopenharmony_ci#define SDXC_IDMAC_RECEIVE_INTERRUPT BIT(1) 18662306a36Sopenharmony_ci#define SDXC_IDMAC_FATAL_BUS_ERROR BIT(2) 18762306a36Sopenharmony_ci#define SDXC_IDMAC_DESTINATION_INVALID BIT(4) 18862306a36Sopenharmony_ci#define SDXC_IDMAC_CARD_ERROR_SUM BIT(5) 18962306a36Sopenharmony_ci#define SDXC_IDMAC_NORMAL_INTERRUPT_SUM BIT(8) 19062306a36Sopenharmony_ci#define SDXC_IDMAC_ABNORMAL_INTERRUPT_SUM BIT(9) 19162306a36Sopenharmony_ci#define SDXC_IDMAC_HOST_ABORT_INTERRUPT BIT(10) 19262306a36Sopenharmony_ci#define SDXC_IDMAC_IDLE (0 << 13) 19362306a36Sopenharmony_ci#define SDXC_IDMAC_SUSPEND (1 << 13) 19462306a36Sopenharmony_ci#define SDXC_IDMAC_DESC_READ (2 << 13) 19562306a36Sopenharmony_ci#define SDXC_IDMAC_DESC_CHECK (3 << 13) 19662306a36Sopenharmony_ci#define SDXC_IDMAC_READ_REQUEST_WAIT (4 << 13) 19762306a36Sopenharmony_ci#define SDXC_IDMAC_WRITE_REQUEST_WAIT (5 << 13) 19862306a36Sopenharmony_ci#define SDXC_IDMAC_READ (6 << 13) 19962306a36Sopenharmony_ci#define SDXC_IDMAC_WRITE (7 << 13) 20062306a36Sopenharmony_ci#define SDXC_IDMAC_DESC_CLOSE (8 << 13) 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* 20362306a36Sopenharmony_ci* If the idma-des-size-bits of property is ie 13, bufsize bits are: 20462306a36Sopenharmony_ci* Bits 0-12: buf1 size 20562306a36Sopenharmony_ci* Bits 13-25: buf2 size 20662306a36Sopenharmony_ci* Bits 26-31: not used 20762306a36Sopenharmony_ci* Since we only ever set buf1 size, we can simply store it directly. 20862306a36Sopenharmony_ci*/ 20962306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */ 21062306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */ 21162306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */ 21262306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */ 21362306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */ 21462306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ 21562306a36Sopenharmony_ci#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci#define SDXC_CLK_400K 0 21862306a36Sopenharmony_ci#define SDXC_CLK_25M 1 21962306a36Sopenharmony_ci#define SDXC_CLK_50M 2 22062306a36Sopenharmony_ci#define SDXC_CLK_50M_DDR 3 22162306a36Sopenharmony_ci#define SDXC_CLK_50M_DDR_8BIT 4 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci#define SDXC_2X_TIMING_MODE BIT(31) 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci#define SDXC_CAL_START BIT(15) 22662306a36Sopenharmony_ci#define SDXC_CAL_DONE BIT(14) 22762306a36Sopenharmony_ci#define SDXC_CAL_DL_SHIFT 8 22862306a36Sopenharmony_ci#define SDXC_CAL_DL_SW_EN BIT(7) 22962306a36Sopenharmony_ci#define SDXC_CAL_DL_SW_SHIFT 0 23062306a36Sopenharmony_ci#define SDXC_CAL_DL_MASK 0x3f 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#define SDXC_CAL_TIMEOUT 3 /* in seconds, 3s is enough*/ 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistruct sunxi_mmc_clk_delay { 23562306a36Sopenharmony_ci u32 output; 23662306a36Sopenharmony_ci u32 sample; 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistruct sunxi_idma_des { 24062306a36Sopenharmony_ci __le32 config; 24162306a36Sopenharmony_ci __le32 buf_size; 24262306a36Sopenharmony_ci __le32 buf_addr_ptr1; 24362306a36Sopenharmony_ci __le32 buf_addr_ptr2; 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistruct sunxi_mmc_cfg { 24762306a36Sopenharmony_ci u32 idma_des_size_bits; 24862306a36Sopenharmony_ci u32 idma_des_shift; 24962306a36Sopenharmony_ci const struct sunxi_mmc_clk_delay *clk_delays; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* does the IP block support autocalibration? */ 25262306a36Sopenharmony_ci bool can_calibrate; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Does DATA0 needs to be masked while the clock is updated */ 25562306a36Sopenharmony_ci bool mask_data0; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * hardware only supports new timing mode, either due to lack of 25962306a36Sopenharmony_ci * a mode switch in the clock controller, or the mmc controller 26062306a36Sopenharmony_ci * is permanently configured in the new timing mode, without the 26162306a36Sopenharmony_ci * NTSR mode switch. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci bool needs_new_timings; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci /* clock hardware can switch between old and new timing modes */ 26662306a36Sopenharmony_ci bool ccu_has_timings_switch; 26762306a36Sopenharmony_ci}; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistruct sunxi_mmc_host { 27062306a36Sopenharmony_ci struct device *dev; 27162306a36Sopenharmony_ci struct mmc_host *mmc; 27262306a36Sopenharmony_ci struct reset_control *reset; 27362306a36Sopenharmony_ci const struct sunxi_mmc_cfg *cfg; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* IO mapping base */ 27662306a36Sopenharmony_ci void __iomem *reg_base; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci /* clock management */ 27962306a36Sopenharmony_ci struct clk *clk_ahb; 28062306a36Sopenharmony_ci struct clk *clk_mmc; 28162306a36Sopenharmony_ci struct clk *clk_sample; 28262306a36Sopenharmony_ci struct clk *clk_output; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* irq */ 28562306a36Sopenharmony_ci spinlock_t lock; 28662306a36Sopenharmony_ci int irq; 28762306a36Sopenharmony_ci u32 int_sum; 28862306a36Sopenharmony_ci u32 sdio_imask; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* dma */ 29162306a36Sopenharmony_ci dma_addr_t sg_dma; 29262306a36Sopenharmony_ci void *sg_cpu; 29362306a36Sopenharmony_ci bool wait_dma; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci struct mmc_request *mrq; 29662306a36Sopenharmony_ci struct mmc_request *manual_stop_mrq; 29762306a36Sopenharmony_ci int ferror; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* vqmmc */ 30062306a36Sopenharmony_ci bool vqmmc_enabled; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* timings */ 30362306a36Sopenharmony_ci bool use_new_timings; 30462306a36Sopenharmony_ci}; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci unsigned long expire = jiffies + msecs_to_jiffies(250); 30962306a36Sopenharmony_ci u32 rval; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, SDXC_HARDWARE_RESET); 31262306a36Sopenharmony_ci do { 31362306a36Sopenharmony_ci rval = mmc_readl(host, REG_GCTRL); 31462306a36Sopenharmony_ci } while (time_before(jiffies, expire) && (rval & SDXC_HARDWARE_RESET)); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (rval & SDXC_HARDWARE_RESET) { 31762306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), "fatal err reset timeout\n"); 31862306a36Sopenharmony_ci return -EIO; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci return 0; 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic int sunxi_mmc_init_host(struct sunxi_mmc_host *host) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci u32 rval; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (sunxi_mmc_reset_host(host)) 32962306a36Sopenharmony_ci return -EIO; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* 33262306a36Sopenharmony_ci * Burst 8 transfers, RX trigger level: 7, TX trigger level: 8 33362306a36Sopenharmony_ci * 33462306a36Sopenharmony_ci * TODO: sun9i has a larger FIFO and supports higher trigger values 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci mmc_writel(host, REG_FTRGL, 0x20070008); 33762306a36Sopenharmony_ci /* Maximum timeout value */ 33862306a36Sopenharmony_ci mmc_writel(host, REG_TMOUT, 0xffffffff); 33962306a36Sopenharmony_ci /* Unmask SDIO interrupt if needed */ 34062306a36Sopenharmony_ci mmc_writel(host, REG_IMASK, host->sdio_imask); 34162306a36Sopenharmony_ci /* Clear all pending interrupts */ 34262306a36Sopenharmony_ci mmc_writel(host, REG_RINTR, 0xffffffff); 34362306a36Sopenharmony_ci /* Debug register? undocumented */ 34462306a36Sopenharmony_ci mmc_writel(host, REG_DBGC, 0xdeb); 34562306a36Sopenharmony_ci /* Enable CEATA support */ 34662306a36Sopenharmony_ci mmc_writel(host, REG_FUNS, SDXC_CEATA_ON); 34762306a36Sopenharmony_ci /* Set DMA descriptor list base address */ 34862306a36Sopenharmony_ci mmc_writel(host, REG_DLBA, host->sg_dma >> host->cfg->idma_des_shift); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci rval = mmc_readl(host, REG_GCTRL); 35162306a36Sopenharmony_ci rval |= SDXC_INTERRUPT_ENABLE_BIT; 35262306a36Sopenharmony_ci /* Undocumented, but found in Allwinner code */ 35362306a36Sopenharmony_ci rval &= ~SDXC_ACCESS_DONE_DIRECT; 35462306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return 0; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, 36062306a36Sopenharmony_ci struct mmc_data *data) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; 36362306a36Sopenharmony_ci dma_addr_t next_desc = host->sg_dma; 36462306a36Sopenharmony_ci int i, max_len = (1 << host->cfg->idma_des_size_bits); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci for (i = 0; i < data->sg_len; i++) { 36762306a36Sopenharmony_ci pdes[i].config = cpu_to_le32(SDXC_IDMAC_DES0_CH | 36862306a36Sopenharmony_ci SDXC_IDMAC_DES0_OWN | 36962306a36Sopenharmony_ci SDXC_IDMAC_DES0_DIC); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (data->sg[i].length == max_len) 37262306a36Sopenharmony_ci pdes[i].buf_size = 0; /* 0 == max_len */ 37362306a36Sopenharmony_ci else 37462306a36Sopenharmony_ci pdes[i].buf_size = cpu_to_le32(data->sg[i].length); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci next_desc += sizeof(struct sunxi_idma_des); 37762306a36Sopenharmony_ci pdes[i].buf_addr_ptr1 = 37862306a36Sopenharmony_ci cpu_to_le32(sg_dma_address(&data->sg[i]) >> 37962306a36Sopenharmony_ci host->cfg->idma_des_shift); 38062306a36Sopenharmony_ci pdes[i].buf_addr_ptr2 = 38162306a36Sopenharmony_ci cpu_to_le32(next_desc >> 38262306a36Sopenharmony_ci host->cfg->idma_des_shift); 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD); 38662306a36Sopenharmony_ci pdes[i - 1].config |= cpu_to_le32(SDXC_IDMAC_DES0_LD | 38762306a36Sopenharmony_ci SDXC_IDMAC_DES0_ER); 38862306a36Sopenharmony_ci pdes[i - 1].config &= cpu_to_le32(~SDXC_IDMAC_DES0_DIC); 38962306a36Sopenharmony_ci pdes[i - 1].buf_addr_ptr2 = 0; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* 39262306a36Sopenharmony_ci * Avoid the io-store starting the idmac hitting io-mem before the 39362306a36Sopenharmony_ci * descriptors hit the main-mem. 39462306a36Sopenharmony_ci */ 39562306a36Sopenharmony_ci wmb(); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic int sunxi_mmc_map_dma(struct sunxi_mmc_host *host, 39962306a36Sopenharmony_ci struct mmc_data *data) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci u32 i, dma_len; 40262306a36Sopenharmony_ci struct scatterlist *sg; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 40562306a36Sopenharmony_ci mmc_get_dma_dir(data)); 40662306a36Sopenharmony_ci if (dma_len == 0) { 40762306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); 40862306a36Sopenharmony_ci return -ENOMEM; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci for_each_sg(data->sg, sg, data->sg_len, i) { 41262306a36Sopenharmony_ci if (sg->offset & 3 || sg->length & 3) { 41362306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), 41462306a36Sopenharmony_ci "unaligned scatterlist: os %x length %d\n", 41562306a36Sopenharmony_ci sg->offset, sg->length); 41662306a36Sopenharmony_ci return -EINVAL; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return 0; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void sunxi_mmc_start_dma(struct sunxi_mmc_host *host, 42462306a36Sopenharmony_ci struct mmc_data *data) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci u32 rval; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci sunxi_mmc_init_idma_des(host, data); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci rval = mmc_readl(host, REG_GCTRL); 43162306a36Sopenharmony_ci rval |= SDXC_DMA_ENABLE_BIT; 43262306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 43362306a36Sopenharmony_ci rval |= SDXC_DMA_RESET; 43462306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci mmc_writel(host, REG_DMAC, SDXC_IDMAC_SOFT_RESET); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci if (!(data->flags & MMC_DATA_WRITE)) 43962306a36Sopenharmony_ci mmc_writel(host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci mmc_writel(host, REG_DMAC, 44262306a36Sopenharmony_ci SDXC_IDMAC_FIX_BURST | SDXC_IDMAC_IDMA_ON); 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, 44662306a36Sopenharmony_ci struct mmc_request *req) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci u32 arg, cmd_val, ri; 44962306a36Sopenharmony_ci unsigned long expire = jiffies + msecs_to_jiffies(1000); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci cmd_val = SDXC_START | SDXC_RESP_EXPIRE | 45262306a36Sopenharmony_ci SDXC_STOP_ABORT_CMD | SDXC_CHECK_RESPONSE_CRC; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (req->cmd->opcode == SD_IO_RW_EXTENDED) { 45562306a36Sopenharmony_ci cmd_val |= SD_IO_RW_DIRECT; 45662306a36Sopenharmony_ci arg = (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | 45762306a36Sopenharmony_ci ((req->cmd->arg >> 28) & 0x7); 45862306a36Sopenharmony_ci } else { 45962306a36Sopenharmony_ci cmd_val |= MMC_STOP_TRANSMISSION; 46062306a36Sopenharmony_ci arg = 0; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci mmc_writel(host, REG_CARG, arg); 46462306a36Sopenharmony_ci mmc_writel(host, REG_CMDR, cmd_val); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci do { 46762306a36Sopenharmony_ci ri = mmc_readl(host, REG_RINTR); 46862306a36Sopenharmony_ci } while (!(ri & (SDXC_COMMAND_DONE | SDXC_INTERRUPT_ERROR_BIT)) && 46962306a36Sopenharmony_ci time_before(jiffies, expire)); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci if (!(ri & SDXC_COMMAND_DONE) || (ri & SDXC_INTERRUPT_ERROR_BIT)) { 47262306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), "send stop command failed\n"); 47362306a36Sopenharmony_ci if (req->stop) 47462306a36Sopenharmony_ci req->stop->resp[0] = -ETIMEDOUT; 47562306a36Sopenharmony_ci } else { 47662306a36Sopenharmony_ci if (req->stop) 47762306a36Sopenharmony_ci req->stop->resp[0] = mmc_readl(host, REG_RESP0); 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci mmc_writel(host, REG_RINTR, 0xffff); 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *host) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci struct mmc_command *cmd = host->mrq->cmd; 48662306a36Sopenharmony_ci struct mmc_data *data = host->mrq->data; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* For some cmds timeout is normal with sd/mmc cards */ 48962306a36Sopenharmony_ci if ((host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == 49062306a36Sopenharmony_ci SDXC_RESP_TIMEOUT && (cmd->opcode == SD_IO_SEND_OP_COND || 49162306a36Sopenharmony_ci cmd->opcode == SD_IO_RW_DIRECT)) 49262306a36Sopenharmony_ci return; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci dev_dbg(mmc_dev(host->mmc), 49562306a36Sopenharmony_ci "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", 49662306a36Sopenharmony_ci host->mmc->index, cmd->opcode, 49762306a36Sopenharmony_ci data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", 49862306a36Sopenharmony_ci host->int_sum & SDXC_RESP_ERROR ? " RE" : "", 49962306a36Sopenharmony_ci host->int_sum & SDXC_RESP_CRC_ERROR ? " RCE" : "", 50062306a36Sopenharmony_ci host->int_sum & SDXC_DATA_CRC_ERROR ? " DCE" : "", 50162306a36Sopenharmony_ci host->int_sum & SDXC_RESP_TIMEOUT ? " RTO" : "", 50262306a36Sopenharmony_ci host->int_sum & SDXC_DATA_TIMEOUT ? " DTO" : "", 50362306a36Sopenharmony_ci host->int_sum & SDXC_FIFO_RUN_ERROR ? " FE" : "", 50462306a36Sopenharmony_ci host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL" : "", 50562306a36Sopenharmony_ci host->int_sum & SDXC_START_BIT_ERROR ? " SBE" : "", 50662306a36Sopenharmony_ci host->int_sum & SDXC_END_BIT_ERROR ? " EBE" : "" 50762306a36Sopenharmony_ci ); 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci/* Called in interrupt context! */ 51162306a36Sopenharmony_cistatic irqreturn_t sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci struct mmc_request *mrq = host->mrq; 51462306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 51562306a36Sopenharmony_ci u32 rval; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci mmc_writel(host, REG_IMASK, host->sdio_imask); 51862306a36Sopenharmony_ci mmc_writel(host, REG_IDIE, 0); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) { 52162306a36Sopenharmony_ci sunxi_mmc_dump_errinfo(host); 52262306a36Sopenharmony_ci mrq->cmd->error = -ETIMEDOUT; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (data) { 52562306a36Sopenharmony_ci data->error = -ETIMEDOUT; 52662306a36Sopenharmony_ci host->manual_stop_mrq = mrq; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (mrq->stop) 53062306a36Sopenharmony_ci mrq->stop->error = -ETIMEDOUT; 53162306a36Sopenharmony_ci } else { 53262306a36Sopenharmony_ci if (mrq->cmd->flags & MMC_RSP_136) { 53362306a36Sopenharmony_ci mrq->cmd->resp[0] = mmc_readl(host, REG_RESP3); 53462306a36Sopenharmony_ci mrq->cmd->resp[1] = mmc_readl(host, REG_RESP2); 53562306a36Sopenharmony_ci mrq->cmd->resp[2] = mmc_readl(host, REG_RESP1); 53662306a36Sopenharmony_ci mrq->cmd->resp[3] = mmc_readl(host, REG_RESP0); 53762306a36Sopenharmony_ci } else { 53862306a36Sopenharmony_ci mrq->cmd->resp[0] = mmc_readl(host, REG_RESP0); 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (data) 54262306a36Sopenharmony_ci data->bytes_xfered = data->blocks * data->blksz; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (data) { 54662306a36Sopenharmony_ci mmc_writel(host, REG_IDST, 0x337); 54762306a36Sopenharmony_ci mmc_writel(host, REG_DMAC, 0); 54862306a36Sopenharmony_ci rval = mmc_readl(host, REG_GCTRL); 54962306a36Sopenharmony_ci rval |= SDXC_DMA_RESET; 55062306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 55162306a36Sopenharmony_ci rval &= ~SDXC_DMA_ENABLE_BIT; 55262306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 55362306a36Sopenharmony_ci rval |= SDXC_FIFO_RESET; 55462306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 55562306a36Sopenharmony_ci dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 55662306a36Sopenharmony_ci mmc_get_dma_dir(data)); 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci mmc_writel(host, REG_RINTR, 0xffff); 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci host->mrq = NULL; 56262306a36Sopenharmony_ci host->int_sum = 0; 56362306a36Sopenharmony_ci host->wait_dma = false; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci return host->manual_stop_mrq ? IRQ_WAKE_THREAD : IRQ_HANDLED; 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci struct sunxi_mmc_host *host = dev_id; 57162306a36Sopenharmony_ci struct mmc_request *mrq; 57262306a36Sopenharmony_ci u32 msk_int, idma_int; 57362306a36Sopenharmony_ci bool finalize = false; 57462306a36Sopenharmony_ci bool sdio_int = false; 57562306a36Sopenharmony_ci irqreturn_t ret = IRQ_HANDLED; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci spin_lock(&host->lock); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci idma_int = mmc_readl(host, REG_IDST); 58062306a36Sopenharmony_ci msk_int = mmc_readl(host, REG_MISTA); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", 58362306a36Sopenharmony_ci host->mrq, msk_int, idma_int); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci mrq = host->mrq; 58662306a36Sopenharmony_ci if (mrq) { 58762306a36Sopenharmony_ci if (idma_int & SDXC_IDMAC_RECEIVE_INTERRUPT) 58862306a36Sopenharmony_ci host->wait_dma = false; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci host->int_sum |= msk_int; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* Wait for COMMAND_DONE on RESPONSE_TIMEOUT before finalize */ 59362306a36Sopenharmony_ci if ((host->int_sum & SDXC_RESP_TIMEOUT) && 59462306a36Sopenharmony_ci !(host->int_sum & SDXC_COMMAND_DONE)) 59562306a36Sopenharmony_ci mmc_writel(host, REG_IMASK, 59662306a36Sopenharmony_ci host->sdio_imask | SDXC_COMMAND_DONE); 59762306a36Sopenharmony_ci /* Don't wait for dma on error */ 59862306a36Sopenharmony_ci else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) 59962306a36Sopenharmony_ci finalize = true; 60062306a36Sopenharmony_ci else if ((host->int_sum & SDXC_INTERRUPT_DONE_BIT) && 60162306a36Sopenharmony_ci !host->wait_dma) 60262306a36Sopenharmony_ci finalize = true; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci if (msk_int & SDXC_SDIO_INTERRUPT) 60662306a36Sopenharmony_ci sdio_int = true; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci mmc_writel(host, REG_RINTR, msk_int); 60962306a36Sopenharmony_ci mmc_writel(host, REG_IDST, idma_int); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci if (finalize) 61262306a36Sopenharmony_ci ret = sunxi_mmc_finalize_request(host); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci spin_unlock(&host->lock); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (finalize && ret == IRQ_HANDLED) 61762306a36Sopenharmony_ci mmc_request_done(host->mmc, mrq); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (sdio_int) 62062306a36Sopenharmony_ci mmc_signal_sdio_irq(host->mmc); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return ret; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic irqreturn_t sunxi_mmc_handle_manual_stop(int irq, void *dev_id) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci struct sunxi_mmc_host *host = dev_id; 62862306a36Sopenharmony_ci struct mmc_request *mrq; 62962306a36Sopenharmony_ci unsigned long iflags; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, iflags); 63262306a36Sopenharmony_ci mrq = host->manual_stop_mrq; 63362306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, iflags); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if (!mrq) { 63662306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), "no request for manual stop\n"); 63762306a36Sopenharmony_ci return IRQ_HANDLED; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), "data error, sending stop command\n"); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci /* 64362306a36Sopenharmony_ci * We will never have more than one outstanding request, 64462306a36Sopenharmony_ci * and we do not complete the request until after 64562306a36Sopenharmony_ci * we've cleared host->manual_stop_mrq so we do not need to 64662306a36Sopenharmony_ci * spin lock this function. 64762306a36Sopenharmony_ci * Additionally we have wait states within this function 64862306a36Sopenharmony_ci * so having it in a lock is a very bad idea. 64962306a36Sopenharmony_ci */ 65062306a36Sopenharmony_ci sunxi_mmc_send_manual_stop(host, mrq); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, iflags); 65362306a36Sopenharmony_ci host->manual_stop_mrq = NULL; 65462306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, iflags); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci mmc_request_done(host->mmc, mrq); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci return IRQ_HANDLED; 65962306a36Sopenharmony_ci} 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_cistatic int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) 66262306a36Sopenharmony_ci{ 66362306a36Sopenharmony_ci unsigned long expire = jiffies + msecs_to_jiffies(750); 66462306a36Sopenharmony_ci u32 rval; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci dev_dbg(mmc_dev(host->mmc), "%sabling the clock\n", 66762306a36Sopenharmony_ci oclk_en ? "en" : "dis"); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci rval = mmc_readl(host, REG_CLKCR); 67062306a36Sopenharmony_ci rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON | SDXC_MASK_DATA0); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (oclk_en) 67362306a36Sopenharmony_ci rval |= SDXC_CARD_CLOCK_ON; 67462306a36Sopenharmony_ci if (host->cfg->mask_data0) 67562306a36Sopenharmony_ci rval |= SDXC_MASK_DATA0; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci mmc_writel(host, REG_CLKCR, rval); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER; 68062306a36Sopenharmony_ci mmc_writel(host, REG_CMDR, rval); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci do { 68362306a36Sopenharmony_ci rval = mmc_readl(host, REG_CMDR); 68462306a36Sopenharmony_ci } while (time_before(jiffies, expire) && (rval & SDXC_START)); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* clear irq status bits set by the command */ 68762306a36Sopenharmony_ci mmc_writel(host, REG_RINTR, 68862306a36Sopenharmony_ci mmc_readl(host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci if (rval & SDXC_START) { 69162306a36Sopenharmony_ci dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); 69262306a36Sopenharmony_ci return -EIO; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (host->cfg->mask_data0) { 69662306a36Sopenharmony_ci rval = mmc_readl(host, REG_CLKCR); 69762306a36Sopenharmony_ci mmc_writel(host, REG_CLKCR, rval & ~SDXC_MASK_DATA0); 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci return 0; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic int sunxi_mmc_calibrate(struct sunxi_mmc_host *host, int reg_off) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci if (!host->cfg->can_calibrate) 70662306a36Sopenharmony_ci return 0; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci /* 70962306a36Sopenharmony_ci * FIXME: 71062306a36Sopenharmony_ci * This is not clear how the calibration is supposed to work 71162306a36Sopenharmony_ci * yet. The best rate have been obtained by simply setting the 71262306a36Sopenharmony_ci * delay to 0, as Allwinner does in its BSP. 71362306a36Sopenharmony_ci * 71462306a36Sopenharmony_ci * The only mode that doesn't have such a delay is HS400, that 71562306a36Sopenharmony_ci * is in itself a TODO. 71662306a36Sopenharmony_ci */ 71762306a36Sopenharmony_ci writel(SDXC_CAL_DL_SW_EN, host->reg_base + reg_off); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci return 0; 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_cistatic int sunxi_mmc_clk_set_phase(struct sunxi_mmc_host *host, 72362306a36Sopenharmony_ci struct mmc_ios *ios, u32 rate) 72462306a36Sopenharmony_ci{ 72562306a36Sopenharmony_ci int index; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci /* clk controller delays not used under new timings mode */ 72862306a36Sopenharmony_ci if (host->use_new_timings) 72962306a36Sopenharmony_ci return 0; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci /* some old controllers don't support delays */ 73262306a36Sopenharmony_ci if (!host->cfg->clk_delays) 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* determine delays */ 73662306a36Sopenharmony_ci if (rate <= 400000) { 73762306a36Sopenharmony_ci index = SDXC_CLK_400K; 73862306a36Sopenharmony_ci } else if (rate <= 25000000) { 73962306a36Sopenharmony_ci index = SDXC_CLK_25M; 74062306a36Sopenharmony_ci } else if (rate <= 52000000) { 74162306a36Sopenharmony_ci if (ios->timing != MMC_TIMING_UHS_DDR50 && 74262306a36Sopenharmony_ci ios->timing != MMC_TIMING_MMC_DDR52) { 74362306a36Sopenharmony_ci index = SDXC_CLK_50M; 74462306a36Sopenharmony_ci } else if (ios->bus_width == MMC_BUS_WIDTH_8) { 74562306a36Sopenharmony_ci index = SDXC_CLK_50M_DDR_8BIT; 74662306a36Sopenharmony_ci } else { 74762306a36Sopenharmony_ci index = SDXC_CLK_50M_DDR; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci } else { 75062306a36Sopenharmony_ci dev_dbg(mmc_dev(host->mmc), "Invalid clock... returning\n"); 75162306a36Sopenharmony_ci return -EINVAL; 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci clk_set_phase(host->clk_sample, host->cfg->clk_delays[index].sample); 75562306a36Sopenharmony_ci clk_set_phase(host->clk_output, host->cfg->clk_delays[index].output); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return 0; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, 76162306a36Sopenharmony_ci struct mmc_ios *ios) 76262306a36Sopenharmony_ci{ 76362306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 76462306a36Sopenharmony_ci long rate; 76562306a36Sopenharmony_ci u32 rval, clock = ios->clock, div = 1; 76662306a36Sopenharmony_ci int ret; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci ret = sunxi_mmc_oclk_onoff(host, 0); 76962306a36Sopenharmony_ci if (ret) 77062306a36Sopenharmony_ci return ret; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci /* Our clock is gated now */ 77362306a36Sopenharmony_ci mmc->actual_clock = 0; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci if (!ios->clock) 77662306a36Sopenharmony_ci return 0; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci /* 77962306a36Sopenharmony_ci * Under the old timing mode, 8 bit DDR requires the module 78062306a36Sopenharmony_ci * clock to be double the card clock. Under the new timing 78162306a36Sopenharmony_ci * mode, all DDR modes require a doubled module clock. 78262306a36Sopenharmony_ci * 78362306a36Sopenharmony_ci * We currently only support the standard MMC DDR52 mode. 78462306a36Sopenharmony_ci * This block should be updated once support for other DDR 78562306a36Sopenharmony_ci * modes is added. 78662306a36Sopenharmony_ci */ 78762306a36Sopenharmony_ci if (ios->timing == MMC_TIMING_MMC_DDR52 && 78862306a36Sopenharmony_ci (host->use_new_timings || 78962306a36Sopenharmony_ci ios->bus_width == MMC_BUS_WIDTH_8)) { 79062306a36Sopenharmony_ci div = 2; 79162306a36Sopenharmony_ci clock <<= 1; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci if (host->use_new_timings && host->cfg->ccu_has_timings_switch) { 79562306a36Sopenharmony_ci ret = sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true); 79662306a36Sopenharmony_ci if (ret) { 79762306a36Sopenharmony_ci dev_err(mmc_dev(mmc), 79862306a36Sopenharmony_ci "error setting new timing mode\n"); 79962306a36Sopenharmony_ci return ret; 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci rate = clk_round_rate(host->clk_mmc, clock); 80462306a36Sopenharmony_ci if (rate < 0) { 80562306a36Sopenharmony_ci dev_err(mmc_dev(mmc), "error rounding clk to %d: %ld\n", 80662306a36Sopenharmony_ci clock, rate); 80762306a36Sopenharmony_ci return rate; 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci dev_dbg(mmc_dev(mmc), "setting clk to %d, rounded %ld\n", 81062306a36Sopenharmony_ci clock, rate); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* setting clock rate */ 81362306a36Sopenharmony_ci ret = clk_set_rate(host->clk_mmc, rate); 81462306a36Sopenharmony_ci if (ret) { 81562306a36Sopenharmony_ci dev_err(mmc_dev(mmc), "error setting clk to %ld: %d\n", 81662306a36Sopenharmony_ci rate, ret); 81762306a36Sopenharmony_ci return ret; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci /* set internal divider */ 82162306a36Sopenharmony_ci rval = mmc_readl(host, REG_CLKCR); 82262306a36Sopenharmony_ci rval &= ~0xff; 82362306a36Sopenharmony_ci rval |= div - 1; 82462306a36Sopenharmony_ci mmc_writel(host, REG_CLKCR, rval); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci /* update card clock rate to account for internal divider */ 82762306a36Sopenharmony_ci rate /= div; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci /* 83062306a36Sopenharmony_ci * Configure the controller to use the new timing mode if needed. 83162306a36Sopenharmony_ci * On controllers that only support the new timing mode, such as 83262306a36Sopenharmony_ci * the eMMC controller on the A64, this register does not exist, 83362306a36Sopenharmony_ci * and any writes to it are ignored. 83462306a36Sopenharmony_ci */ 83562306a36Sopenharmony_ci if (host->use_new_timings) { 83662306a36Sopenharmony_ci /* Don't touch the delay bits */ 83762306a36Sopenharmony_ci rval = mmc_readl(host, REG_SD_NTSR); 83862306a36Sopenharmony_ci rval |= SDXC_2X_TIMING_MODE; 83962306a36Sopenharmony_ci mmc_writel(host, REG_SD_NTSR, rval); 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /* sunxi_mmc_clk_set_phase expects the actual card clock rate */ 84362306a36Sopenharmony_ci ret = sunxi_mmc_clk_set_phase(host, ios, rate); 84462306a36Sopenharmony_ci if (ret) 84562306a36Sopenharmony_ci return ret; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci ret = sunxi_mmc_calibrate(host, SDXC_REG_SAMP_DL_REG); 84862306a36Sopenharmony_ci if (ret) 84962306a36Sopenharmony_ci return ret; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci /* 85262306a36Sopenharmony_ci * FIXME: 85362306a36Sopenharmony_ci * 85462306a36Sopenharmony_ci * In HS400 we'll also need to calibrate the data strobe 85562306a36Sopenharmony_ci * signal. This should only happen on the MMC2 controller (at 85662306a36Sopenharmony_ci * least on the A64). 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci ret = sunxi_mmc_oclk_onoff(host, 1); 86062306a36Sopenharmony_ci if (ret) 86162306a36Sopenharmony_ci return ret; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* And we just enabled our clock back */ 86462306a36Sopenharmony_ci mmc->actual_clock = rate; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci return 0; 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic void sunxi_mmc_set_bus_width(struct sunxi_mmc_host *host, 87062306a36Sopenharmony_ci unsigned char width) 87162306a36Sopenharmony_ci{ 87262306a36Sopenharmony_ci switch (width) { 87362306a36Sopenharmony_ci case MMC_BUS_WIDTH_1: 87462306a36Sopenharmony_ci mmc_writel(host, REG_WIDTH, SDXC_WIDTH1); 87562306a36Sopenharmony_ci break; 87662306a36Sopenharmony_ci case MMC_BUS_WIDTH_4: 87762306a36Sopenharmony_ci mmc_writel(host, REG_WIDTH, SDXC_WIDTH4); 87862306a36Sopenharmony_ci break; 87962306a36Sopenharmony_ci case MMC_BUS_WIDTH_8: 88062306a36Sopenharmony_ci mmc_writel(host, REG_WIDTH, SDXC_WIDTH8); 88162306a36Sopenharmony_ci break; 88262306a36Sopenharmony_ci } 88362306a36Sopenharmony_ci} 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_cistatic void sunxi_mmc_set_clk(struct sunxi_mmc_host *host, struct mmc_ios *ios) 88662306a36Sopenharmony_ci{ 88762306a36Sopenharmony_ci u32 rval; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci /* set ddr mode */ 89062306a36Sopenharmony_ci rval = mmc_readl(host, REG_GCTRL); 89162306a36Sopenharmony_ci if (ios->timing == MMC_TIMING_UHS_DDR50 || 89262306a36Sopenharmony_ci ios->timing == MMC_TIMING_MMC_DDR52) 89362306a36Sopenharmony_ci rval |= SDXC_DDR_MODE; 89462306a36Sopenharmony_ci else 89562306a36Sopenharmony_ci rval &= ~SDXC_DDR_MODE; 89662306a36Sopenharmony_ci mmc_writel(host, REG_GCTRL, rval); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci host->ferror = sunxi_mmc_clk_set_rate(host, ios); 89962306a36Sopenharmony_ci /* Android code had a usleep_range(50000, 55000); here */ 90062306a36Sopenharmony_ci} 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cistatic void sunxi_mmc_card_power(struct sunxi_mmc_host *host, 90362306a36Sopenharmony_ci struct mmc_ios *ios) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci struct mmc_host *mmc = host->mmc; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci switch (ios->power_mode) { 90862306a36Sopenharmony_ci case MMC_POWER_UP: 90962306a36Sopenharmony_ci dev_dbg(mmc_dev(mmc), "Powering card up\n"); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if (!IS_ERR(mmc->supply.vmmc)) { 91262306a36Sopenharmony_ci host->ferror = mmc_regulator_set_ocr(mmc, 91362306a36Sopenharmony_ci mmc->supply.vmmc, 91462306a36Sopenharmony_ci ios->vdd); 91562306a36Sopenharmony_ci if (host->ferror) 91662306a36Sopenharmony_ci return; 91762306a36Sopenharmony_ci } 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (!IS_ERR(mmc->supply.vqmmc)) { 92062306a36Sopenharmony_ci host->ferror = regulator_enable(mmc->supply.vqmmc); 92162306a36Sopenharmony_ci if (host->ferror) { 92262306a36Sopenharmony_ci dev_err(mmc_dev(mmc), 92362306a36Sopenharmony_ci "failed to enable vqmmc\n"); 92462306a36Sopenharmony_ci return; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci host->vqmmc_enabled = true; 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci break; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci case MMC_POWER_OFF: 93162306a36Sopenharmony_ci dev_dbg(mmc_dev(mmc), "Powering card off\n"); 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci if (!IS_ERR(mmc->supply.vmmc)) 93462306a36Sopenharmony_ci mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) 93762306a36Sopenharmony_ci regulator_disable(mmc->supply.vqmmc); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci host->vqmmc_enabled = false; 94062306a36Sopenharmony_ci break; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci default: 94362306a36Sopenharmony_ci dev_dbg(mmc_dev(mmc), "Ignoring unknown card power state\n"); 94462306a36Sopenharmony_ci break; 94562306a36Sopenharmony_ci } 94662306a36Sopenharmony_ci} 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_cistatic void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 94962306a36Sopenharmony_ci{ 95062306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci sunxi_mmc_card_power(host, ios); 95362306a36Sopenharmony_ci sunxi_mmc_set_bus_width(host, ios->bus_width); 95462306a36Sopenharmony_ci sunxi_mmc_set_clk(host, ios); 95562306a36Sopenharmony_ci} 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_cistatic int sunxi_mmc_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios) 95862306a36Sopenharmony_ci{ 95962306a36Sopenharmony_ci int ret; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci /* vqmmc regulator is available */ 96262306a36Sopenharmony_ci if (!IS_ERR(mmc->supply.vqmmc)) { 96362306a36Sopenharmony_ci ret = mmc_regulator_set_vqmmc(mmc, ios); 96462306a36Sopenharmony_ci return ret < 0 ? ret : 0; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci /* no vqmmc regulator, assume fixed regulator at 3/3.3V */ 96862306a36Sopenharmony_ci if (mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) 96962306a36Sopenharmony_ci return 0; 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci return -EINVAL; 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cistatic void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) 97562306a36Sopenharmony_ci{ 97662306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 97762306a36Sopenharmony_ci unsigned long flags; 97862306a36Sopenharmony_ci u32 imask; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci if (enable) 98162306a36Sopenharmony_ci pm_runtime_get_noresume(host->dev); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, flags); 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci imask = mmc_readl(host, REG_IMASK); 98662306a36Sopenharmony_ci if (enable) { 98762306a36Sopenharmony_ci host->sdio_imask = SDXC_SDIO_INTERRUPT; 98862306a36Sopenharmony_ci imask |= SDXC_SDIO_INTERRUPT; 98962306a36Sopenharmony_ci } else { 99062306a36Sopenharmony_ci host->sdio_imask = 0; 99162306a36Sopenharmony_ci imask &= ~SDXC_SDIO_INTERRUPT; 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci mmc_writel(host, REG_IMASK, imask); 99462306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, flags); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (!enable) 99762306a36Sopenharmony_ci pm_runtime_put_noidle(host->mmc->parent); 99862306a36Sopenharmony_ci} 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_cistatic void sunxi_mmc_hw_reset(struct mmc_host *mmc) 100162306a36Sopenharmony_ci{ 100262306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 100362306a36Sopenharmony_ci mmc_writel(host, REG_HWRST, 0); 100462306a36Sopenharmony_ci udelay(10); 100562306a36Sopenharmony_ci mmc_writel(host, REG_HWRST, 1); 100662306a36Sopenharmony_ci udelay(300); 100762306a36Sopenharmony_ci} 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_cistatic void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 101262306a36Sopenharmony_ci struct mmc_command *cmd = mrq->cmd; 101362306a36Sopenharmony_ci struct mmc_data *data = mrq->data; 101462306a36Sopenharmony_ci unsigned long iflags; 101562306a36Sopenharmony_ci u32 imask = SDXC_INTERRUPT_ERROR_BIT; 101662306a36Sopenharmony_ci u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f); 101762306a36Sopenharmony_ci bool wait_dma = host->wait_dma; 101862306a36Sopenharmony_ci int ret; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci /* Check for set_ios errors (should never happen) */ 102162306a36Sopenharmony_ci if (host->ferror) { 102262306a36Sopenharmony_ci mrq->cmd->error = host->ferror; 102362306a36Sopenharmony_ci mmc_request_done(mmc, mrq); 102462306a36Sopenharmony_ci return; 102562306a36Sopenharmony_ci } 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (data) { 102862306a36Sopenharmony_ci ret = sunxi_mmc_map_dma(host, data); 102962306a36Sopenharmony_ci if (ret < 0) { 103062306a36Sopenharmony_ci dev_err(mmc_dev(mmc), "map DMA failed\n"); 103162306a36Sopenharmony_ci cmd->error = ret; 103262306a36Sopenharmony_ci data->error = ret; 103362306a36Sopenharmony_ci mmc_request_done(mmc, mrq); 103462306a36Sopenharmony_ci return; 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci if (cmd->opcode == MMC_GO_IDLE_STATE) { 103962306a36Sopenharmony_ci cmd_val |= SDXC_SEND_INIT_SEQUENCE; 104062306a36Sopenharmony_ci imask |= SDXC_COMMAND_DONE; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci if (cmd->flags & MMC_RSP_PRESENT) { 104462306a36Sopenharmony_ci cmd_val |= SDXC_RESP_EXPIRE; 104562306a36Sopenharmony_ci if (cmd->flags & MMC_RSP_136) 104662306a36Sopenharmony_ci cmd_val |= SDXC_LONG_RESPONSE; 104762306a36Sopenharmony_ci if (cmd->flags & MMC_RSP_CRC) 104862306a36Sopenharmony_ci cmd_val |= SDXC_CHECK_RESPONSE_CRC; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) { 105162306a36Sopenharmony_ci cmd_val |= SDXC_DATA_EXPIRE | SDXC_WAIT_PRE_OVER; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci if (cmd->data->stop) { 105462306a36Sopenharmony_ci imask |= SDXC_AUTO_COMMAND_DONE; 105562306a36Sopenharmony_ci cmd_val |= SDXC_SEND_AUTO_STOP; 105662306a36Sopenharmony_ci } else { 105762306a36Sopenharmony_ci imask |= SDXC_DATA_OVER; 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci if (cmd->data->flags & MMC_DATA_WRITE) 106162306a36Sopenharmony_ci cmd_val |= SDXC_WRITE; 106262306a36Sopenharmony_ci else 106362306a36Sopenharmony_ci wait_dma = true; 106462306a36Sopenharmony_ci } else { 106562306a36Sopenharmony_ci imask |= SDXC_COMMAND_DONE; 106662306a36Sopenharmony_ci } 106762306a36Sopenharmony_ci } else { 106862306a36Sopenharmony_ci imask |= SDXC_COMMAND_DONE; 106962306a36Sopenharmony_ci } 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci dev_dbg(mmc_dev(mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n", 107262306a36Sopenharmony_ci cmd_val & 0x3f, cmd_val, cmd->arg, imask, 107362306a36Sopenharmony_ci mrq->data ? mrq->data->blksz * mrq->data->blocks : 0); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci spin_lock_irqsave(&host->lock, iflags); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci if (host->mrq || host->manual_stop_mrq) { 107862306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, iflags); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci if (data) 108162306a36Sopenharmony_ci dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, 108262306a36Sopenharmony_ci mmc_get_dma_dir(data)); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci dev_err(mmc_dev(mmc), "request already pending\n"); 108562306a36Sopenharmony_ci mrq->cmd->error = -EBUSY; 108662306a36Sopenharmony_ci mmc_request_done(mmc, mrq); 108762306a36Sopenharmony_ci return; 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci if (data) { 109162306a36Sopenharmony_ci mmc_writel(host, REG_BLKSZ, data->blksz); 109262306a36Sopenharmony_ci mmc_writel(host, REG_BCNTR, data->blksz * data->blocks); 109362306a36Sopenharmony_ci sunxi_mmc_start_dma(host, data); 109462306a36Sopenharmony_ci } 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci host->mrq = mrq; 109762306a36Sopenharmony_ci host->wait_dma = wait_dma; 109862306a36Sopenharmony_ci mmc_writel(host, REG_IMASK, host->sdio_imask | imask); 109962306a36Sopenharmony_ci mmc_writel(host, REG_CARG, cmd->arg); 110062306a36Sopenharmony_ci mmc_writel(host, REG_CMDR, cmd_val); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci spin_unlock_irqrestore(&host->lock, iflags); 110362306a36Sopenharmony_ci} 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_cistatic int sunxi_mmc_card_busy(struct mmc_host *mmc) 110662306a36Sopenharmony_ci{ 110762306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci return !!(mmc_readl(host, REG_STAS) & SDXC_CARD_DATA_BUSY); 111062306a36Sopenharmony_ci} 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_cistatic const struct mmc_host_ops sunxi_mmc_ops = { 111362306a36Sopenharmony_ci .request = sunxi_mmc_request, 111462306a36Sopenharmony_ci .set_ios = sunxi_mmc_set_ios, 111562306a36Sopenharmony_ci .get_ro = mmc_gpio_get_ro, 111662306a36Sopenharmony_ci .get_cd = mmc_gpio_get_cd, 111762306a36Sopenharmony_ci .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, 111862306a36Sopenharmony_ci .start_signal_voltage_switch = sunxi_mmc_volt_switch, 111962306a36Sopenharmony_ci .card_hw_reset = sunxi_mmc_hw_reset, 112062306a36Sopenharmony_ci .card_busy = sunxi_mmc_card_busy, 112162306a36Sopenharmony_ci}; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_cistatic const struct sunxi_mmc_clk_delay sunxi_mmc_clk_delays[] = { 112462306a36Sopenharmony_ci [SDXC_CLK_400K] = { .output = 180, .sample = 180 }, 112562306a36Sopenharmony_ci [SDXC_CLK_25M] = { .output = 180, .sample = 75 }, 112662306a36Sopenharmony_ci [SDXC_CLK_50M] = { .output = 90, .sample = 120 }, 112762306a36Sopenharmony_ci [SDXC_CLK_50M_DDR] = { .output = 60, .sample = 120 }, 112862306a36Sopenharmony_ci /* Value from A83T "new timing mode". Works but might not be right. */ 112962306a36Sopenharmony_ci [SDXC_CLK_50M_DDR_8BIT] = { .output = 90, .sample = 180 }, 113062306a36Sopenharmony_ci}; 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cistatic const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = { 113362306a36Sopenharmony_ci [SDXC_CLK_400K] = { .output = 180, .sample = 180 }, 113462306a36Sopenharmony_ci [SDXC_CLK_25M] = { .output = 180, .sample = 75 }, 113562306a36Sopenharmony_ci [SDXC_CLK_50M] = { .output = 150, .sample = 120 }, 113662306a36Sopenharmony_ci [SDXC_CLK_50M_DDR] = { .output = 54, .sample = 36 }, 113762306a36Sopenharmony_ci [SDXC_CLK_50M_DDR_8BIT] = { .output = 72, .sample = 72 }, 113862306a36Sopenharmony_ci}; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun4i_a10_cfg = { 114162306a36Sopenharmony_ci .idma_des_size_bits = 13, 114262306a36Sopenharmony_ci .clk_delays = NULL, 114362306a36Sopenharmony_ci .can_calibrate = false, 114462306a36Sopenharmony_ci}; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun5i_a13_cfg = { 114762306a36Sopenharmony_ci .idma_des_size_bits = 16, 114862306a36Sopenharmony_ci .clk_delays = NULL, 114962306a36Sopenharmony_ci .can_calibrate = false, 115062306a36Sopenharmony_ci}; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun7i_a20_cfg = { 115362306a36Sopenharmony_ci .idma_des_size_bits = 16, 115462306a36Sopenharmony_ci .clk_delays = sunxi_mmc_clk_delays, 115562306a36Sopenharmony_ci .can_calibrate = false, 115662306a36Sopenharmony_ci}; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun8i_a83t_emmc_cfg = { 115962306a36Sopenharmony_ci .idma_des_size_bits = 16, 116062306a36Sopenharmony_ci .clk_delays = sunxi_mmc_clk_delays, 116162306a36Sopenharmony_ci .can_calibrate = false, 116262306a36Sopenharmony_ci .ccu_has_timings_switch = true, 116362306a36Sopenharmony_ci}; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun9i_a80_cfg = { 116662306a36Sopenharmony_ci .idma_des_size_bits = 16, 116762306a36Sopenharmony_ci .clk_delays = sun9i_mmc_clk_delays, 116862306a36Sopenharmony_ci .can_calibrate = false, 116962306a36Sopenharmony_ci}; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun20i_d1_cfg = { 117262306a36Sopenharmony_ci .idma_des_size_bits = 13, 117362306a36Sopenharmony_ci .idma_des_shift = 2, 117462306a36Sopenharmony_ci .can_calibrate = true, 117562306a36Sopenharmony_ci .mask_data0 = true, 117662306a36Sopenharmony_ci .needs_new_timings = true, 117762306a36Sopenharmony_ci}; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun50i_a64_cfg = { 118062306a36Sopenharmony_ci .idma_des_size_bits = 16, 118162306a36Sopenharmony_ci .clk_delays = NULL, 118262306a36Sopenharmony_ci .can_calibrate = true, 118362306a36Sopenharmony_ci .mask_data0 = true, 118462306a36Sopenharmony_ci .needs_new_timings = true, 118562306a36Sopenharmony_ci}; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = { 118862306a36Sopenharmony_ci .idma_des_size_bits = 13, 118962306a36Sopenharmony_ci .clk_delays = NULL, 119062306a36Sopenharmony_ci .can_calibrate = true, 119162306a36Sopenharmony_ci .needs_new_timings = true, 119262306a36Sopenharmony_ci}; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun50i_a100_cfg = { 119562306a36Sopenharmony_ci .idma_des_size_bits = 16, 119662306a36Sopenharmony_ci .idma_des_shift = 2, 119762306a36Sopenharmony_ci .clk_delays = NULL, 119862306a36Sopenharmony_ci .can_calibrate = true, 119962306a36Sopenharmony_ci .mask_data0 = true, 120062306a36Sopenharmony_ci .needs_new_timings = true, 120162306a36Sopenharmony_ci}; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_cistatic const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = { 120462306a36Sopenharmony_ci .idma_des_size_bits = 13, 120562306a36Sopenharmony_ci .idma_des_shift = 2, 120662306a36Sopenharmony_ci .clk_delays = NULL, 120762306a36Sopenharmony_ci .can_calibrate = true, 120862306a36Sopenharmony_ci .needs_new_timings = true, 120962306a36Sopenharmony_ci}; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_cistatic const struct of_device_id sunxi_mmc_of_match[] = { 121262306a36Sopenharmony_ci { .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg }, 121362306a36Sopenharmony_ci { .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg }, 121462306a36Sopenharmony_ci { .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg }, 121562306a36Sopenharmony_ci { .compatible = "allwinner,sun8i-a83t-emmc", .data = &sun8i_a83t_emmc_cfg }, 121662306a36Sopenharmony_ci { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg }, 121762306a36Sopenharmony_ci { .compatible = "allwinner,sun20i-d1-mmc", .data = &sun20i_d1_cfg }, 121862306a36Sopenharmony_ci { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg }, 121962306a36Sopenharmony_ci { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg }, 122062306a36Sopenharmony_ci { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg }, 122162306a36Sopenharmony_ci { .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg }, 122262306a36Sopenharmony_ci { /* sentinel */ } 122362306a36Sopenharmony_ci}; 122462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_cistatic int sunxi_mmc_enable(struct sunxi_mmc_host *host) 122762306a36Sopenharmony_ci{ 122862306a36Sopenharmony_ci int ret; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci if (!IS_ERR(host->reset)) { 123162306a36Sopenharmony_ci ret = reset_control_reset(host->reset); 123262306a36Sopenharmony_ci if (ret) { 123362306a36Sopenharmony_ci dev_err(host->dev, "Couldn't reset the MMC controller (%d)\n", 123462306a36Sopenharmony_ci ret); 123562306a36Sopenharmony_ci return ret; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci ret = clk_prepare_enable(host->clk_ahb); 124062306a36Sopenharmony_ci if (ret) { 124162306a36Sopenharmony_ci dev_err(host->dev, "Couldn't enable the bus clocks (%d)\n", ret); 124262306a36Sopenharmony_ci goto error_assert_reset; 124362306a36Sopenharmony_ci } 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci ret = clk_prepare_enable(host->clk_mmc); 124662306a36Sopenharmony_ci if (ret) { 124762306a36Sopenharmony_ci dev_err(host->dev, "Enable mmc clk err %d\n", ret); 124862306a36Sopenharmony_ci goto error_disable_clk_ahb; 124962306a36Sopenharmony_ci } 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci ret = clk_prepare_enable(host->clk_output); 125262306a36Sopenharmony_ci if (ret) { 125362306a36Sopenharmony_ci dev_err(host->dev, "Enable output clk err %d\n", ret); 125462306a36Sopenharmony_ci goto error_disable_clk_mmc; 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci ret = clk_prepare_enable(host->clk_sample); 125862306a36Sopenharmony_ci if (ret) { 125962306a36Sopenharmony_ci dev_err(host->dev, "Enable sample clk err %d\n", ret); 126062306a36Sopenharmony_ci goto error_disable_clk_output; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* 126462306a36Sopenharmony_ci * Sometimes the controller asserts the irq on boot for some reason, 126562306a36Sopenharmony_ci * make sure the controller is in a sane state before enabling irqs. 126662306a36Sopenharmony_ci */ 126762306a36Sopenharmony_ci ret = sunxi_mmc_reset_host(host); 126862306a36Sopenharmony_ci if (ret) 126962306a36Sopenharmony_ci goto error_disable_clk_sample; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci return 0; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_cierror_disable_clk_sample: 127462306a36Sopenharmony_ci clk_disable_unprepare(host->clk_sample); 127562306a36Sopenharmony_cierror_disable_clk_output: 127662306a36Sopenharmony_ci clk_disable_unprepare(host->clk_output); 127762306a36Sopenharmony_cierror_disable_clk_mmc: 127862306a36Sopenharmony_ci clk_disable_unprepare(host->clk_mmc); 127962306a36Sopenharmony_cierror_disable_clk_ahb: 128062306a36Sopenharmony_ci clk_disable_unprepare(host->clk_ahb); 128162306a36Sopenharmony_cierror_assert_reset: 128262306a36Sopenharmony_ci if (!IS_ERR(host->reset)) 128362306a36Sopenharmony_ci reset_control_assert(host->reset); 128462306a36Sopenharmony_ci return ret; 128562306a36Sopenharmony_ci} 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_cistatic void sunxi_mmc_disable(struct sunxi_mmc_host *host) 128862306a36Sopenharmony_ci{ 128962306a36Sopenharmony_ci sunxi_mmc_reset_host(host); 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci clk_disable_unprepare(host->clk_sample); 129262306a36Sopenharmony_ci clk_disable_unprepare(host->clk_output); 129362306a36Sopenharmony_ci clk_disable_unprepare(host->clk_mmc); 129462306a36Sopenharmony_ci clk_disable_unprepare(host->clk_ahb); 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci if (!IS_ERR(host->reset)) 129762306a36Sopenharmony_ci reset_control_assert(host->reset); 129862306a36Sopenharmony_ci} 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_cistatic int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, 130162306a36Sopenharmony_ci struct platform_device *pdev) 130262306a36Sopenharmony_ci{ 130362306a36Sopenharmony_ci int ret; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci host->cfg = of_device_get_match_data(&pdev->dev); 130662306a36Sopenharmony_ci if (!host->cfg) 130762306a36Sopenharmony_ci return -EINVAL; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci ret = mmc_regulator_get_supply(host->mmc); 131062306a36Sopenharmony_ci if (ret) 131162306a36Sopenharmony_ci return ret; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci host->reg_base = devm_platform_ioremap_resource(pdev, 0); 131462306a36Sopenharmony_ci if (IS_ERR(host->reg_base)) 131562306a36Sopenharmony_ci return PTR_ERR(host->reg_base); 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); 131862306a36Sopenharmony_ci if (IS_ERR(host->clk_ahb)) { 131962306a36Sopenharmony_ci dev_err(&pdev->dev, "Could not get ahb clock\n"); 132062306a36Sopenharmony_ci return PTR_ERR(host->clk_ahb); 132162306a36Sopenharmony_ci } 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci host->clk_mmc = devm_clk_get(&pdev->dev, "mmc"); 132462306a36Sopenharmony_ci if (IS_ERR(host->clk_mmc)) { 132562306a36Sopenharmony_ci dev_err(&pdev->dev, "Could not get mmc clock\n"); 132662306a36Sopenharmony_ci return PTR_ERR(host->clk_mmc); 132762306a36Sopenharmony_ci } 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci if (host->cfg->clk_delays) { 133062306a36Sopenharmony_ci host->clk_output = devm_clk_get(&pdev->dev, "output"); 133162306a36Sopenharmony_ci if (IS_ERR(host->clk_output)) { 133262306a36Sopenharmony_ci dev_err(&pdev->dev, "Could not get output clock\n"); 133362306a36Sopenharmony_ci return PTR_ERR(host->clk_output); 133462306a36Sopenharmony_ci } 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci host->clk_sample = devm_clk_get(&pdev->dev, "sample"); 133762306a36Sopenharmony_ci if (IS_ERR(host->clk_sample)) { 133862306a36Sopenharmony_ci dev_err(&pdev->dev, "Could not get sample clock\n"); 133962306a36Sopenharmony_ci return PTR_ERR(host->clk_sample); 134062306a36Sopenharmony_ci } 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, 134462306a36Sopenharmony_ci "ahb"); 134562306a36Sopenharmony_ci if (PTR_ERR(host->reset) == -EPROBE_DEFER) 134662306a36Sopenharmony_ci return PTR_ERR(host->reset); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci ret = sunxi_mmc_enable(host); 134962306a36Sopenharmony_ci if (ret) 135062306a36Sopenharmony_ci return ret; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci host->irq = platform_get_irq(pdev, 0); 135362306a36Sopenharmony_ci if (host->irq < 0) { 135462306a36Sopenharmony_ci ret = host->irq; 135562306a36Sopenharmony_ci goto error_disable_mmc; 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 135962306a36Sopenharmony_ci sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_cierror_disable_mmc: 136262306a36Sopenharmony_ci sunxi_mmc_disable(host); 136362306a36Sopenharmony_ci return ret; 136462306a36Sopenharmony_ci} 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_cistatic int sunxi_mmc_probe(struct platform_device *pdev) 136762306a36Sopenharmony_ci{ 136862306a36Sopenharmony_ci struct sunxi_mmc_host *host; 136962306a36Sopenharmony_ci struct mmc_host *mmc; 137062306a36Sopenharmony_ci int ret; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); 137362306a36Sopenharmony_ci if (!mmc) { 137462306a36Sopenharmony_ci dev_err(&pdev->dev, "mmc alloc host failed\n"); 137562306a36Sopenharmony_ci return -ENOMEM; 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci platform_set_drvdata(pdev, mmc); 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci host = mmc_priv(mmc); 138062306a36Sopenharmony_ci host->dev = &pdev->dev; 138162306a36Sopenharmony_ci host->mmc = mmc; 138262306a36Sopenharmony_ci spin_lock_init(&host->lock); 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci ret = sunxi_mmc_resource_request(host, pdev); 138562306a36Sopenharmony_ci if (ret) 138662306a36Sopenharmony_ci goto error_free_host; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, 138962306a36Sopenharmony_ci &host->sg_dma, GFP_KERNEL); 139062306a36Sopenharmony_ci if (!host->sg_cpu) { 139162306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n"); 139262306a36Sopenharmony_ci ret = -ENOMEM; 139362306a36Sopenharmony_ci goto error_free_host; 139462306a36Sopenharmony_ci } 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci if (host->cfg->ccu_has_timings_switch) { 139762306a36Sopenharmony_ci /* 139862306a36Sopenharmony_ci * Supports both old and new timing modes. 139962306a36Sopenharmony_ci * Try setting the clk to new timing mode. 140062306a36Sopenharmony_ci */ 140162306a36Sopenharmony_ci sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true); 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* And check the result */ 140462306a36Sopenharmony_ci ret = sunxi_ccu_get_mmc_timing_mode(host->clk_mmc); 140562306a36Sopenharmony_ci if (ret < 0) { 140662306a36Sopenharmony_ci /* 140762306a36Sopenharmony_ci * For whatever reason we were not able to get 140862306a36Sopenharmony_ci * the current active mode. Default to old mode. 140962306a36Sopenharmony_ci */ 141062306a36Sopenharmony_ci dev_warn(&pdev->dev, "MMC clk timing mode unknown\n"); 141162306a36Sopenharmony_ci host->use_new_timings = false; 141262306a36Sopenharmony_ci } else { 141362306a36Sopenharmony_ci host->use_new_timings = !!ret; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci } else if (host->cfg->needs_new_timings) { 141662306a36Sopenharmony_ci /* Supports new timing mode only */ 141762306a36Sopenharmony_ci host->use_new_timings = true; 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci mmc->ops = &sunxi_mmc_ops; 142162306a36Sopenharmony_ci mmc->max_blk_count = 8192; 142262306a36Sopenharmony_ci mmc->max_blk_size = 4096; 142362306a36Sopenharmony_ci mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); 142462306a36Sopenharmony_ci mmc->max_seg_size = (1 << host->cfg->idma_des_size_bits); 142562306a36Sopenharmony_ci mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; 142662306a36Sopenharmony_ci /* 400kHz ~ 52MHz */ 142762306a36Sopenharmony_ci mmc->f_min = 400000; 142862306a36Sopenharmony_ci mmc->f_max = 52000000; 142962306a36Sopenharmony_ci mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | 143062306a36Sopenharmony_ci MMC_CAP_SDIO_IRQ; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci /* 143362306a36Sopenharmony_ci * Some H5 devices do not have signal traces precise enough to 143462306a36Sopenharmony_ci * use HS DDR mode for their eMMC chips. 143562306a36Sopenharmony_ci * 143662306a36Sopenharmony_ci * We still enable HS DDR modes for all the other controller 143762306a36Sopenharmony_ci * variants that support them. 143862306a36Sopenharmony_ci */ 143962306a36Sopenharmony_ci if ((host->cfg->clk_delays || host->use_new_timings) && 144062306a36Sopenharmony_ci !of_device_is_compatible(pdev->dev.of_node, 144162306a36Sopenharmony_ci "allwinner,sun50i-h5-emmc")) 144262306a36Sopenharmony_ci mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci ret = mmc_of_parse(mmc); 144562306a36Sopenharmony_ci if (ret) 144662306a36Sopenharmony_ci goto error_free_dma; 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci /* 144962306a36Sopenharmony_ci * If we don't support delay chains in the SoC, we can't use any 145062306a36Sopenharmony_ci * of the higher speed modes. Mask them out in case the device 145162306a36Sopenharmony_ci * tree specifies the properties for them, which gets added to 145262306a36Sopenharmony_ci * the caps by mmc_of_parse() above. 145362306a36Sopenharmony_ci */ 145462306a36Sopenharmony_ci if (!(host->cfg->clk_delays || host->use_new_timings)) { 145562306a36Sopenharmony_ci mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR | 145662306a36Sopenharmony_ci MMC_CAP_1_2V_DDR | MMC_CAP_UHS); 145762306a36Sopenharmony_ci mmc->caps2 &= ~MMC_CAP2_HS200; 145862306a36Sopenharmony_ci } 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci /* TODO: This driver doesn't support HS400 mode yet */ 146162306a36Sopenharmony_ci mmc->caps2 &= ~MMC_CAP2_HS400; 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci ret = sunxi_mmc_init_host(host); 146462306a36Sopenharmony_ci if (ret) 146562306a36Sopenharmony_ci goto error_free_dma; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci pm_runtime_set_active(&pdev->dev); 146862306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(&pdev->dev, 50); 146962306a36Sopenharmony_ci pm_runtime_use_autosuspend(&pdev->dev); 147062306a36Sopenharmony_ci pm_runtime_enable(&pdev->dev); 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci ret = mmc_add_host(mmc); 147362306a36Sopenharmony_ci if (ret) 147462306a36Sopenharmony_ci goto error_free_dma; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci dev_info(&pdev->dev, "initialized, max. request size: %u KB%s\n", 147762306a36Sopenharmony_ci mmc->max_req_size >> 10, 147862306a36Sopenharmony_ci host->use_new_timings ? ", uses new timings mode" : ""); 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci return 0; 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_cierror_free_dma: 148362306a36Sopenharmony_ci dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); 148462306a36Sopenharmony_cierror_free_host: 148562306a36Sopenharmony_ci mmc_free_host(mmc); 148662306a36Sopenharmony_ci return ret; 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_cistatic void sunxi_mmc_remove(struct platform_device *pdev) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci struct mmc_host *mmc = platform_get_drvdata(pdev); 149262306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci mmc_remove_host(mmc); 149562306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 149662306a36Sopenharmony_ci if (!pm_runtime_status_suspended(&pdev->dev)) { 149762306a36Sopenharmony_ci disable_irq(host->irq); 149862306a36Sopenharmony_ci sunxi_mmc_disable(host); 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); 150162306a36Sopenharmony_ci mmc_free_host(mmc); 150262306a36Sopenharmony_ci} 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci#ifdef CONFIG_PM 150562306a36Sopenharmony_cistatic int sunxi_mmc_runtime_resume(struct device *dev) 150662306a36Sopenharmony_ci{ 150762306a36Sopenharmony_ci struct mmc_host *mmc = dev_get_drvdata(dev); 150862306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 150962306a36Sopenharmony_ci int ret; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci ret = sunxi_mmc_enable(host); 151262306a36Sopenharmony_ci if (ret) 151362306a36Sopenharmony_ci return ret; 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci sunxi_mmc_init_host(host); 151662306a36Sopenharmony_ci sunxi_mmc_set_bus_width(host, mmc->ios.bus_width); 151762306a36Sopenharmony_ci sunxi_mmc_set_clk(host, &mmc->ios); 151862306a36Sopenharmony_ci enable_irq(host->irq); 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci return 0; 152162306a36Sopenharmony_ci} 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_cistatic int sunxi_mmc_runtime_suspend(struct device *dev) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci struct mmc_host *mmc = dev_get_drvdata(dev); 152662306a36Sopenharmony_ci struct sunxi_mmc_host *host = mmc_priv(mmc); 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci /* 152962306a36Sopenharmony_ci * When clocks are off, it's possible receiving 153062306a36Sopenharmony_ci * fake interrupts, which will stall the system. 153162306a36Sopenharmony_ci * Disabling the irq will prevent this. 153262306a36Sopenharmony_ci */ 153362306a36Sopenharmony_ci disable_irq(host->irq); 153462306a36Sopenharmony_ci sunxi_mmc_reset_host(host); 153562306a36Sopenharmony_ci sunxi_mmc_disable(host); 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci return 0; 153862306a36Sopenharmony_ci} 153962306a36Sopenharmony_ci#endif 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_cistatic const struct dev_pm_ops sunxi_mmc_pm_ops = { 154262306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 154362306a36Sopenharmony_ci pm_runtime_force_resume) 154462306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(sunxi_mmc_runtime_suspend, 154562306a36Sopenharmony_ci sunxi_mmc_runtime_resume, 154662306a36Sopenharmony_ci NULL) 154762306a36Sopenharmony_ci}; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_cistatic struct platform_driver sunxi_mmc_driver = { 155062306a36Sopenharmony_ci .driver = { 155162306a36Sopenharmony_ci .name = "sunxi-mmc", 155262306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 155362306a36Sopenharmony_ci .of_match_table = sunxi_mmc_of_match, 155462306a36Sopenharmony_ci .pm = &sunxi_mmc_pm_ops, 155562306a36Sopenharmony_ci }, 155662306a36Sopenharmony_ci .probe = sunxi_mmc_probe, 155762306a36Sopenharmony_ci .remove_new = sunxi_mmc_remove, 155862306a36Sopenharmony_ci}; 155962306a36Sopenharmony_cimodule_platform_driver(sunxi_mmc_driver); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ciMODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver"); 156262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 156362306a36Sopenharmony_ciMODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer@o2s.ch>"); 156462306a36Sopenharmony_ciMODULE_ALIAS("platform:sunxi-mmc"); 1565