1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Rockchip UFS Host Controller driver 4 * 5 * Copyright (C) 2024 Rockchip Electronics Co.Ltd. 6 */ 7 8 #include <asm/io.h> 9 #include <clk.h> 10 #include <common.h> 11 #include <dm.h> 12 #include <linux/err.h> 13 #include <linux/ioport.h> 14 #include <ufs.h> 15 16 #include "ufs.h" 17 #include "unipro.h" 18 #include "ufs-rockchip.h" 19 20 extern int ufshcd_dme_enable(struct ufs_hba *hba); 21 22 static inline bool ufshcd_is_hba_active(struct ufs_hba *hba) 23 { 24 return ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & CONTROLLER_ENABLE; 25 } 26 27 static int ufs_rockchip_hce_enable_notify(struct ufs_hba *hba, 28 enum ufs_notify_change_status status) 29 { 30 int err = 0; 31 32 if (status == POST_CHANGE) { 33 ufshcd_dme_reset(hba); 34 ufshcd_dme_enable(hba); 35 if (hba->ops->phy_initialization) { 36 err = hba->ops->phy_initialization(hba); 37 if (err) { 38 dev_err(hba->dev, "Phy setup failed (%d)\n", err); 39 } 40 } 41 } 42 43 return err; 44 } 45 46 static const unsigned char rk3576_phy_value[15][4] = { 47 {0x03, 0x38, 0x50, 0x80}, 48 {0x03, 0x14, 0x58, 0x80}, 49 {0x03, 0x26, 0x58, 0x80}, 50 {0x03, 0x49, 0x58, 0x80}, 51 {0x03, 0x5A, 0x58, 0x80}, 52 {0xC3, 0x38, 0x50, 0xC0}, 53 {0xC3, 0x14, 0x58, 0xC0}, 54 {0xC3, 0x26, 0x58, 0xC0}, 55 {0xC3, 0x49, 0x58, 0xC0}, 56 {0xC3, 0x5A, 0x58, 0xC0}, 57 {0x43, 0x38, 0x50, 0xC0}, 58 {0x43, 0x14, 0x58, 0xC0}, 59 {0x43, 0x26, 0x58, 0xC0}, 60 {0x43, 0x49, 0x58, 0xC0}, 61 {0x43, 0x5A, 0x58, 0xC0} 62 }; 63 64 static int ufs_rockchip_rk3576_phy_init(struct ufs_hba *hba) 65 { 66 struct ufs_rockchip_host *host = dev_get_priv(hba->dev); 67 int try_case = host->phy_config_mode, value; 68 69 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(PA_LOCAL_TX_LCC_ENABLE, 0x0), 0x0); 70 /* enable the mphy DME_SET cfg */ 71 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x40); 72 for (int i = 0; i < 2; i++) { 73 /* Configuration M-TX */ 74 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xaa, SEL_TX_LANE0 + i), 0x06); 75 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xa9, SEL_TX_LANE0 + i), 0x02); 76 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xad, SEL_TX_LANE0 + i), 0x44); 77 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xac, SEL_TX_LANE0 + i), 0xe6); 78 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xab, SEL_TX_LANE0 + i), 0x07); 79 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x94, SEL_TX_LANE0 + i), 0x93); 80 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x93, SEL_TX_LANE0 + i), 0xc9); 81 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x7f, SEL_TX_LANE0 + i), 0x00); 82 /* Configuration M-RX */ 83 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x12, SEL_RX_LANE0 + i), 0x06); 84 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x11, SEL_RX_LANE0 + i), 0x00); 85 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1d, SEL_RX_LANE0 + i), 0x58); 86 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1c, SEL_RX_LANE0 + i), 0x8c); 87 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1b, SEL_RX_LANE0 + i), 0x02); 88 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x25, SEL_RX_LANE0 + i), 0xf6); 89 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x2f, SEL_RX_LANE0 + i), 0x69); 90 } 91 /* disable the mphy DME_SET cfg */ 92 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x00); 93 94 ufs_sys_writel(host->mphy_base, 0x80, 0x08C); 95 ufs_sys_writel(host->mphy_base, 0xB5, 0x110); 96 ufs_sys_writel(host->mphy_base, 0xB5, 0x250); 97 98 value = rk3576_phy_value[try_case][0]; 99 ufs_sys_writel(host->mphy_base, value, 0x134); 100 ufs_sys_writel(host->mphy_base, value, 0x274); 101 102 value = rk3576_phy_value[try_case][1]; 103 ufs_sys_writel(host->mphy_base, value, 0x0E0); 104 ufs_sys_writel(host->mphy_base, value, 0x220); 105 106 value = rk3576_phy_value[try_case][2]; 107 ufs_sys_writel(host->mphy_base, value, 0x164); 108 ufs_sys_writel(host->mphy_base, value, 0x2A4); 109 110 value = rk3576_phy_value[try_case][3]; 111 ufs_sys_writel(host->mphy_base, value, 0x178); 112 ufs_sys_writel(host->mphy_base, value, 0x2B8); 113 114 ufs_sys_writel(host->mphy_base, 0x18, 0x1B0); 115 ufs_sys_writel(host->mphy_base, 0x18, 0x2F0); 116 117 ufs_sys_writel(host->mphy_base, 0xC0, 0x120); 118 ufs_sys_writel(host->mphy_base, 0xC0, 0x260); 119 120 ufs_sys_writel(host->mphy_base, 0x03, 0x094); 121 122 ufs_sys_writel(host->mphy_base, 0x03, 0x1B4); 123 ufs_sys_writel(host->mphy_base, 0x03, 0x2F4); 124 125 ufs_sys_writel(host->mphy_base, 0xC0, 0x08C); 126 udelay(1); 127 ufs_sys_writel(host->mphy_base, 0x00, 0x08C); 128 129 udelay(200); 130 131 /* start link up */ 132 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_TX_ENDIAN, 0), 0x0); 133 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_RX_ENDIAN, 0), 0x0); 134 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID, 0), 0x0); 135 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID_VALID, 0), 0x1); 136 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_PEERDEVICEID, 0), 0x1); 137 ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_CONNECTIONSTATE, 0), 0x1); 138 139 return 0; 140 } 141 142 static int ufs_rockchip_common_init(struct ufs_hba *hba) 143 { 144 struct udevice *dev = hba->dev; 145 struct ufs_rockchip_host *host = dev_get_priv(dev); 146 struct resource res; 147 int err = 0; 148 149 /* system control register for hci */ 150 err = dev_read_resource_byname(dev, "hci_grf", &res); 151 if (err) { 152 dev_err(dev, "cannot ioremap for hci system control register\n"); 153 return -ENODEV; 154 } 155 host->ufs_sys_ctrl = (void *)(res.start); 156 157 /* system control register for mphy */ 158 err = dev_read_resource_byname(dev, "mphy_grf", &res); 159 if (err) { 160 dev_err(dev, "cannot ioremap for mphy system control register\n"); 161 return -ENODEV; 162 } 163 host->ufs_phy_ctrl = (void *)(res.start); 164 165 /* mphy base register */ 166 err = dev_read_resource_byname(dev, "mphy", &res); 167 if (err) { 168 dev_err(dev, "cannot ioremap for mphy base register\n"); 169 return -ENODEV; 170 } 171 host->mphy_base = (void *)(res.start); 172 173 host->phy_config_mode = dev_read_u32_default(dev, "ufs-phy-config-mode", 0); 174 175 host->hba = hba; 176 177 return 0; 178 } 179 180 static int ufs_rockchip_rk3576_init(struct ufs_hba *hba) 181 { 182 int ret = 0; 183 184 ret = ufs_rockchip_common_init(hba); 185 if (ret) { 186 dev_err(hba->dev, "%s: ufs common init fail\n", __func__); 187 return ret; 188 } 189 190 /* UFS PHY select 26M from ppll */ 191 writel(0x00030002, 0x2722030C); 192 /* set UFS_REFCLK, UFS_RSTN */ 193 writel(0x00FF0011, 0x2604B398); 194 udelay(20); 195 writel(0x00100010, 0x2604B400); 196 197 return 0; 198 } 199 200 static struct ufs_hba_ops ufs_hba_rk3576_vops = { 201 .init = ufs_rockchip_rk3576_init, 202 .phy_initialization = ufs_rockchip_rk3576_phy_init, 203 .hce_enable_notify = ufs_rockchip_hce_enable_notify, 204 }; 205 206 static const struct udevice_id ufs_rockchip_of_match[] = { 207 { .compatible = "rockchip,rk3576-ufs", .data = (ulong)&ufs_hba_rk3576_vops}, 208 {}, 209 }; 210 211 static int ufs_rockchip_probe(struct udevice *dev) 212 { 213 struct ufs_hba_ops *ops = (struct ufs_hba_ops *)dev_get_driver_data(dev); 214 int err; 215 216 err = ufshcd_probe(dev, ops); 217 if (err) 218 dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); 219 220 return err; 221 } 222 223 static int ufs_rockchip_bind(struct udevice *dev) 224 { 225 struct udevice *scsi_dev; 226 227 return ufs_scsi_bind(dev, &scsi_dev); 228 } 229 230 U_BOOT_DRIVER(ti_j721e_ufs) = { 231 .name = "ufshcd-rockchip", 232 .id = UCLASS_UFS, 233 .of_match = ufs_rockchip_of_match, 234 .probe = ufs_rockchip_probe, 235 .bind = ufs_rockchip_bind, 236 .priv_auto_alloc_size = sizeof(struct ufs_rockchip_host), 237 }; 238