^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * sdhci-pci-arasan.c - Driver for Arasan PCI Controller with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * integrated phy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2017 Arasan Chip Systems Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Atul Garg <agarg@arasan.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "sdhci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "sdhci-pci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Extra registers for Arasan SD/SDIO/MMC Host Controller with PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define PHY_ADDR_REG 0x300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define PHY_DAT_REG 0x304
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define PHY_WRITE BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PHY_BUSY BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define DATA_MASK 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* PHY Specific Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DLL_STATUS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define IPAD_CTRL1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define IPAD_CTRL2 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define IPAD_STS 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define IOREN_CTRL1 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define IOREN_CTRL2 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define IOPU_CTRL1 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define IOPU_CTRL2 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ITAP_DELAY 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define OTAP_DELAY 0x0D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define STRB_SEL 0x0E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CLKBUF_SEL 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MODE_CTRL 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DLL_TRIM 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CMD_CTRL 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DATA_CTRL 0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define STRB_CTRL 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CLK_CTRL 0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define PHY_CTRL 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DLL_ENBL BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define RTRIM_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define PDB_ENBL BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define RETB_ENBL BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ODEN_CMD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define ODEN_DAT 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define REN_STRB BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define REN_CMND BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define REN_DATA 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define PU_CMD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PU_DAT 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define ITAPDLY_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define OTAPDLY_EN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define OD_REL_CMD BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define OD_REL_DAT 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define DLLTRM_ICP 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define PDB_CMND BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define PDB_DATA 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define PDB_STRB BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define PDB_CLOCK BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CALDONE_MASK 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define DLL_RDY_MASK 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MAX_CLK_BUF 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Mode Controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define ENHSTRB_MODE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define HS400_MODE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define LEGACY_MODE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define DDR50_MODE BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Controller has no specific bits for HS200/HS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Used BIT(4), BIT(5) for software programming.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define HS200_MODE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define HISPD_MODE BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define OTAPDLY(x) (((x) << 1) | OTAPDLY_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define ITAPDLY(x) (((x) << 1) | ITAPDLY_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define FREQSEL(x) (((x) << 5) | DLL_ENBL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define IOPAD(x, y) ((x) | ((y) << 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* Arasan private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct arasan_host {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 chg_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int arasan_phy_addr_poll(struct sdhci_host *host, u32 offset, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ktime_t timeout = ktime_add_us(ktime_get(), 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) bool failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) failed = ktime_after(ktime_get(), timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) val = sdhci_readw(host, PHY_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!(val & mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (failed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int arasan_phy_write(struct sdhci_host *host, u8 data, u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) sdhci_writew(host, data, PHY_DAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) sdhci_writew(host, (PHY_WRITE | offset), PHY_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int arasan_phy_read(struct sdhci_host *host, u8 offset, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) sdhci_writew(host, 0, PHY_DAT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) sdhci_writew(host, offset, PHY_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ret = arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* Masking valid data bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *data = sdhci_readw(host, PHY_DAT_REG) & DATA_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int arasan_phy_sts_poll(struct sdhci_host *host, u32 offset, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ktime_t timeout = ktime_add_us(ktime_get(), 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) bool failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u8 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) failed = ktime_after(ktime_get(), timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = arasan_phy_read(host, offset, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) else if (val & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (failed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Initialize the Arasan PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int arasan_phy_init(struct sdhci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* Program IOPADs and wait for calibration to be done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (arasan_phy_read(host, IPAD_CTRL1, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) arasan_phy_write(host, val | RETB_ENBL | PDB_ENBL, IPAD_CTRL1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) arasan_phy_read(host, IPAD_CTRL2, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) arasan_phy_write(host, val | RTRIM_EN, IPAD_CTRL2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ret = arasan_phy_sts_poll(host, IPAD_STS, CALDONE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* Program CMD/Data lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (arasan_phy_read(host, IOREN_CTRL1, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) arasan_phy_write(host, val | REN_CMND | REN_STRB, IOREN_CTRL1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) arasan_phy_read(host, IOPU_CTRL1, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) arasan_phy_write(host, val | PU_CMD, IOPU_CTRL1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) arasan_phy_read(host, CMD_CTRL, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) arasan_phy_write(host, val | PDB_CMND, CMD_CTRL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) arasan_phy_read(host, IOREN_CTRL2, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) arasan_phy_write(host, val | REN_DATA, IOREN_CTRL2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) arasan_phy_read(host, IOPU_CTRL2, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) arasan_phy_write(host, val | PU_DAT, IOPU_CTRL2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) arasan_phy_read(host, DATA_CTRL, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) arasan_phy_write(host, val | PDB_DATA, DATA_CTRL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) arasan_phy_read(host, STRB_CTRL, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) arasan_phy_write(host, val | PDB_STRB, STRB_CTRL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) arasan_phy_read(host, CLK_CTRL, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) arasan_phy_write(host, val | PDB_CLOCK, CLK_CTRL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) arasan_phy_read(host, CLKBUF_SEL, &val) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) arasan_phy_write(host, val | MAX_CLK_BUF, CLKBUF_SEL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) arasan_phy_write(host, LEGACY_MODE, MODE_CTRL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Set Arasan PHY for different modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int arasan_phy_set(struct sdhci_host *host, u8 mode, u8 otap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u8 drv_type, u8 itap, u8 trim, u8 clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (mode == HISPD_MODE || mode == HS200_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = arasan_phy_write(host, 0x0, MODE_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) ret = arasan_phy_write(host, mode, MODE_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (mode == HS400_MODE || mode == HS200_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = arasan_phy_read(host, IPAD_CTRL1, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ret = arasan_phy_write(host, IOPAD(val, drv_type), IPAD_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (mode == LEGACY_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ret = arasan_phy_write(host, 0x0, OTAP_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = arasan_phy_write(host, 0x0, ITAP_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ret = arasan_phy_write(host, OTAPDLY(otap), OTAP_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (mode != HS200_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ret = arasan_phy_write(host, ITAPDLY(itap), ITAP_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ret = arasan_phy_write(host, 0x0, ITAP_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (mode != LEGACY_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ret = arasan_phy_write(host, trim, DLL_TRIM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = arasan_phy_write(host, 0, DLL_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (mode != LEGACY_MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ret = arasan_phy_write(host, FREQSEL(clk), DLL_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ret = arasan_phy_sts_poll(host, DLL_STATUS, DLL_RDY_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int arasan_select_phy_clock(struct sdhci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct sdhci_pci_slot *slot = sdhci_priv(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct arasan_host *arasan_host = sdhci_pci_priv(slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) u8 clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (arasan_host->chg_clk == host->mmc->ios.clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) arasan_host->chg_clk = host->mmc->ios.clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (host->mmc->ios.clock == 200000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) clk = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) else if (host->mmc->ios.clock == 100000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) clk = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) else if (host->mmc->ios.clock == 50000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) clk = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) clk = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (host->mmc_host_ops.hs400_enhanced_strobe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) arasan_phy_set(host, ENHSTRB_MODE, 1, 0x0, 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) DLLTRM_ICP, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) switch (host->mmc->ios.timing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case MMC_TIMING_LEGACY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) arasan_phy_set(host, LEGACY_MODE, 0x0, 0x0, 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 0x0, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case MMC_TIMING_MMC_HS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case MMC_TIMING_SD_HS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) arasan_phy_set(host, HISPD_MODE, 0x3, 0x0, 0x2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) DLLTRM_ICP, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case MMC_TIMING_MMC_HS200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) case MMC_TIMING_UHS_SDR104:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) arasan_phy_set(host, HS200_MODE, 0x2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) host->mmc->ios.drv_type, 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) DLLTRM_ICP, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case MMC_TIMING_MMC_DDR52:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case MMC_TIMING_UHS_DDR50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) arasan_phy_set(host, DDR50_MODE, 0x1, 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 0x0, DLLTRM_ICP, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) case MMC_TIMING_MMC_HS400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) arasan_phy_set(host, HS400_MODE, 0x1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) host->mmc->ios.drv_type, 0xa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) DLLTRM_ICP, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int arasan_pci_probe_slot(struct sdhci_pci_slot *slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) slot->host->mmc->caps |= MMC_CAP_NONREMOVABLE | MMC_CAP_8_BIT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) err = arasan_phy_init(slot->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static void arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) sdhci_set_clock(host, clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Change phy settings for the new clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) arasan_select_phy_clock(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static const struct sdhci_ops arasan_sdhci_pci_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .set_clock = arasan_sdhci_set_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .enable_dma = sdhci_pci_enable_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .set_bus_width = sdhci_set_bus_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .reset = sdhci_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .set_uhs_signaling = sdhci_set_uhs_signaling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) const struct sdhci_pci_fixes sdhci_arasan = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .probe_slot = arasan_pci_probe_slot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .ops = &arasan_sdhci_pci_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .priv_size = sizeof(struct arasan_host),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };