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