Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: ufs: ufs-renesas: Add support for Renesas R-Car UFS controller

Add support for Renesas R-Car UFS controller which needs vendor-specific
initialization.

Link: https://lore.kernel.org/r/20220603110524.1997825-5-yoshihiro.shimoda.uh@renesas.com
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Yoshihiro Shimoda and committed by
Martin K. Petersen
d6952028 2f11bbc2

+425
+12
drivers/ufs/host/Kconfig
··· 92 92 Select this if you have UFS controller on Hisilicon chipset. 93 93 If unsure, say N. 94 94 95 + config SCSI_UFS_RENESAS 96 + tristate "Renesas specific hooks to UFS controller platform driver" 97 + depends on (ARCH_RENESAS || COMPILE_TEST) && SCSI_UFSHCD_PLATFORM 98 + help 99 + This selects the Renesas specific additions to UFSHCD platform driver. 100 + UFS host on Renesas needs some vendor specific configuration before 101 + accessing the hardware. 102 + 103 + Select this if you have UFS controller on Renesas chipset. 104 + 105 + If unsure, say N. 106 + 95 107 config SCSI_UFS_TI_J721E 96 108 tristate "TI glue layer for Cadence UFS Controller" 97 109 depends on OF && HAS_IOMEM && (ARCH_K3 || COMPILE_TEST)
+1
drivers/ufs/host/Makefile
··· 11 11 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o 12 12 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o 13 13 obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o 14 + obj-$(CONFIG_SCSI_UFS_RENESAS) += ufs-renesas.o 14 15 obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
+412
drivers/ufs/host/ufs-renesas.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR MIT 2 + /* 3 + * Renesas UFS host controller driver 4 + * 5 + * Copyright (C) 2022 Renesas Electronics Corporation 6 + */ 7 + 8 + #include <linux/clk.h> 9 + #include <linux/delay.h> 10 + #include <linux/err.h> 11 + #include <linux/iopoll.h> 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/of.h> 15 + #include <linux/of_device.h> 16 + #include <linux/pm_runtime.h> 17 + #include <ufs/ufshcd.h> 18 + 19 + #include "ufshcd-pltfrm.h" 20 + 21 + struct ufs_renesas_priv { 22 + bool initialized; /* The hardware needs initialization once */ 23 + }; 24 + 25 + enum { 26 + SET_PHY_INDEX_LO = 0, 27 + SET_PHY_INDEX_HI, 28 + TIMER_INDEX, 29 + MAX_INDEX 30 + }; 31 + 32 + enum ufs_renesas_init_param_mode { 33 + MODE_RESTORE, 34 + MODE_SET, 35 + MODE_SAVE, 36 + MODE_POLL, 37 + MODE_WAIT, 38 + MODE_WRITE, 39 + }; 40 + 41 + #define PARAM_RESTORE(_reg, _index) \ 42 + { .mode = MODE_RESTORE, .reg = _reg, .index = _index } 43 + #define PARAM_SET(_index, _set) \ 44 + { .mode = MODE_SET, .index = _index, .u.set = _set } 45 + #define PARAM_SAVE(_reg, _mask, _index) \ 46 + { .mode = MODE_SAVE, .reg = _reg, .mask = (u32)(_mask), \ 47 + .index = _index } 48 + #define PARAM_POLL(_reg, _expected, _mask) \ 49 + { .mode = MODE_POLL, .reg = _reg, .u.expected = _expected, \ 50 + .mask = (u32)(_mask) } 51 + #define PARAM_WAIT(_delay_us) \ 52 + { .mode = MODE_WAIT, .u.delay_us = _delay_us } 53 + 54 + #define PARAM_WRITE(_reg, _val) \ 55 + { .mode = MODE_WRITE, .reg = _reg, .u.val = _val } 56 + 57 + #define PARAM_WRITE_D0_D4(_d0, _d4) \ 58 + PARAM_WRITE(0xd0, _d0), PARAM_WRITE(0xd4, _d4) 59 + 60 + #define PARAM_WRITE_800_80C_POLL(_addr, _data_800) \ 61 + PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), \ 62 + PARAM_WRITE_D0_D4(0x00000800, ((_data_800) << 16) | BIT(8) | (_addr)), \ 63 + PARAM_WRITE(0xd0, 0x0000080c), \ 64 + PARAM_POLL(0xd4, BIT(8), BIT(8)) 65 + 66 + #define PARAM_RESTORE_800_80C_POLL(_index) \ 67 + PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), \ 68 + PARAM_WRITE(0xd0, 0x00000800), \ 69 + PARAM_RESTORE(0xd4, _index), \ 70 + PARAM_WRITE(0xd0, 0x0000080c), \ 71 + PARAM_POLL(0xd4, BIT(8), BIT(8)) 72 + 73 + #define PARAM_WRITE_804_80C_POLL(_addr, _data_804) \ 74 + PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), \ 75 + PARAM_WRITE_D0_D4(0x00000804, ((_data_804) << 16) | BIT(8) | (_addr)), \ 76 + PARAM_WRITE(0xd0, 0x0000080c), \ 77 + PARAM_POLL(0xd4, BIT(8), BIT(8)) 78 + 79 + #define PARAM_WRITE_828_82C_POLL(_data_828) \ 80 + PARAM_WRITE_D0_D4(0x0000082c, 0x0f000000), \ 81 + PARAM_WRITE_D0_D4(0x00000828, _data_828), \ 82 + PARAM_WRITE(0xd0, 0x0000082c), \ 83 + PARAM_POLL(0xd4, _data_828, _data_828) 84 + 85 + #define PARAM_WRITE_PHY(_addr16, _data16) \ 86 + PARAM_WRITE(0xf0, 1), \ 87 + PARAM_WRITE_800_80C_POLL(0x16, (_addr16) & 0xff), \ 88 + PARAM_WRITE_800_80C_POLL(0x17, ((_addr16) >> 8) & 0xff), \ 89 + PARAM_WRITE_800_80C_POLL(0x18, (_data16) & 0xff), \ 90 + PARAM_WRITE_800_80C_POLL(0x19, ((_data16) >> 8) & 0xff), \ 91 + PARAM_WRITE_800_80C_POLL(0x1c, 0x01), \ 92 + PARAM_WRITE_828_82C_POLL(0x0f000000), \ 93 + PARAM_WRITE(0xf0, 0) 94 + 95 + #define PARAM_SET_PHY(_addr16, _data16) \ 96 + PARAM_WRITE(0xf0, 1), \ 97 + PARAM_WRITE_800_80C_POLL(0x16, (_addr16) & 0xff), \ 98 + PARAM_WRITE_800_80C_POLL(0x17, ((_addr16) >> 8) & 0xff), \ 99 + PARAM_WRITE_800_80C_POLL(0x1c, 0x01), \ 100 + PARAM_WRITE_828_82C_POLL(0x0f000000), \ 101 + PARAM_WRITE_804_80C_POLL(0x1a, 0), \ 102 + PARAM_WRITE(0xd0, 0x00000808), \ 103 + PARAM_SAVE(0xd4, 0xff, SET_PHY_INDEX_LO), \ 104 + PARAM_WRITE_804_80C_POLL(0x1b, 0), \ 105 + PARAM_WRITE(0xd0, 0x00000808), \ 106 + PARAM_SAVE(0xd4, 0xff, SET_PHY_INDEX_HI), \ 107 + PARAM_WRITE_828_82C_POLL(0x0f000000), \ 108 + PARAM_WRITE(0xf0, 0), \ 109 + PARAM_WRITE(0xf0, 1), \ 110 + PARAM_WRITE_800_80C_POLL(0x16, (_addr16) & 0xff), \ 111 + PARAM_WRITE_800_80C_POLL(0x17, ((_addr16) >> 8) & 0xff), \ 112 + PARAM_SET(SET_PHY_INDEX_LO, ((_data16 & 0xff) << 16) | BIT(8) | 0x18), \ 113 + PARAM_RESTORE_800_80C_POLL(SET_PHY_INDEX_LO), \ 114 + PARAM_SET(SET_PHY_INDEX_HI, (((_data16 >> 8) & 0xff) << 16) | BIT(8) | 0x19), \ 115 + PARAM_RESTORE_800_80C_POLL(SET_PHY_INDEX_HI), \ 116 + PARAM_WRITE_800_80C_POLL(0x1c, 0x01), \ 117 + PARAM_WRITE_828_82C_POLL(0x0f000000), \ 118 + PARAM_WRITE(0xf0, 0) 119 + 120 + #define PARAM_INDIRECT_WRITE(_gpio, _addr, _data_800) \ 121 + PARAM_WRITE(0xf0, _gpio), \ 122 + PARAM_WRITE_800_80C_POLL(_addr, _data_800), \ 123 + PARAM_WRITE_828_82C_POLL(0x0f000000), \ 124 + PARAM_WRITE(0xf0, 0) 125 + 126 + #define PARAM_INDIRECT_POLL(_gpio, _addr, _expected, _mask) \ 127 + PARAM_WRITE(0xf0, _gpio), \ 128 + PARAM_WRITE_800_80C_POLL(_addr, 0), \ 129 + PARAM_WRITE(0xd0, 0x00000808), \ 130 + PARAM_POLL(0xd4, _expected, _mask), \ 131 + PARAM_WRITE(0xf0, 0) 132 + 133 + struct ufs_renesas_init_param { 134 + enum ufs_renesas_init_param_mode mode; 135 + u32 reg; 136 + union { 137 + u32 expected; 138 + u32 delay_us; 139 + u32 set; 140 + u32 val; 141 + } u; 142 + u32 mask; 143 + u32 index; 144 + }; 145 + 146 + /* This setting is for SERIES B */ 147 + static const struct ufs_renesas_init_param ufs_param[] = { 148 + PARAM_WRITE(0xc0, 0x49425308), 149 + PARAM_WRITE_D0_D4(0x00000104, 0x00000002), 150 + PARAM_WAIT(1), 151 + PARAM_WRITE_D0_D4(0x00000828, 0x00000200), 152 + PARAM_WAIT(1), 153 + PARAM_WRITE_D0_D4(0x00000828, 0x00000000), 154 + PARAM_WRITE_D0_D4(0x00000104, 0x00000001), 155 + PARAM_WRITE_D0_D4(0x00000940, 0x00000001), 156 + PARAM_WAIT(1), 157 + PARAM_WRITE_D0_D4(0x00000940, 0x00000000), 158 + 159 + PARAM_WRITE(0xc0, 0x49425308), 160 + PARAM_WRITE(0xc0, 0x41584901), 161 + 162 + PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), 163 + PARAM_WRITE_D0_D4(0x00000804, 0x00000000), 164 + PARAM_WRITE(0xd0, 0x0000080c), 165 + PARAM_POLL(0xd4, BIT(8), BIT(8)), 166 + 167 + PARAM_WRITE(REG_CONTROLLER_ENABLE, 0x00000001), 168 + 169 + PARAM_WRITE(0xd0, 0x00000804), 170 + PARAM_POLL(0xd4, BIT(8) | BIT(6) | BIT(0), BIT(8) | BIT(6) | BIT(0)), 171 + 172 + PARAM_WRITE(0xd0, 0x00000d00), 173 + PARAM_SAVE(0xd4, 0x0000ffff, TIMER_INDEX), 174 + PARAM_WRITE(0xd4, 0x00000000), 175 + PARAM_WRITE_D0_D4(0x0000082c, 0x0f000000), 176 + PARAM_WRITE_D0_D4(0x00000828, 0x08000000), 177 + PARAM_WRITE(0xd0, 0x0000082c), 178 + PARAM_POLL(0xd4, BIT(27), BIT(27)), 179 + PARAM_WRITE(0xd0, 0x00000d2c), 180 + PARAM_POLL(0xd4, BIT(0), BIT(0)), 181 + 182 + /* phy setup */ 183 + PARAM_INDIRECT_WRITE(1, 0x01, 0x001f), 184 + PARAM_INDIRECT_WRITE(7, 0x5d, 0x0014), 185 + PARAM_INDIRECT_WRITE(7, 0x5e, 0x0014), 186 + PARAM_INDIRECT_WRITE(7, 0x0d, 0x0003), 187 + PARAM_INDIRECT_WRITE(7, 0x0e, 0x0007), 188 + PARAM_INDIRECT_WRITE(7, 0x5f, 0x0003), 189 + PARAM_INDIRECT_WRITE(7, 0x60, 0x0003), 190 + PARAM_INDIRECT_WRITE(7, 0x5b, 0x00a6), 191 + PARAM_INDIRECT_WRITE(7, 0x5c, 0x0003), 192 + 193 + PARAM_INDIRECT_POLL(7, 0x3c, 0, BIT(7)), 194 + PARAM_INDIRECT_POLL(7, 0x4c, 0, BIT(4)), 195 + 196 + PARAM_INDIRECT_WRITE(1, 0x32, 0x0080), 197 + PARAM_INDIRECT_WRITE(1, 0x1f, 0x0001), 198 + PARAM_INDIRECT_WRITE(0, 0x2c, 0x0001), 199 + PARAM_INDIRECT_WRITE(0, 0x32, 0x0087), 200 + 201 + PARAM_INDIRECT_WRITE(1, 0x4d, 0x0061), 202 + PARAM_INDIRECT_WRITE(4, 0x9b, 0x0009), 203 + PARAM_INDIRECT_WRITE(4, 0xa6, 0x0005), 204 + PARAM_INDIRECT_WRITE(4, 0xa5, 0x0058), 205 + PARAM_INDIRECT_WRITE(1, 0x39, 0x0027), 206 + PARAM_INDIRECT_WRITE(1, 0x47, 0x004c), 207 + 208 + PARAM_INDIRECT_WRITE(7, 0x0d, 0x0002), 209 + PARAM_INDIRECT_WRITE(7, 0x0e, 0x0007), 210 + 211 + PARAM_WRITE_PHY(0x0028, 0x0061), 212 + PARAM_WRITE_PHY(0x4014, 0x0061), 213 + PARAM_SET_PHY(0x401c, BIT(2)), 214 + PARAM_WRITE_PHY(0x4000, 0x0000), 215 + PARAM_WRITE_PHY(0x4001, 0x0000), 216 + 217 + PARAM_WRITE_PHY(0x10ae, 0x0001), 218 + PARAM_WRITE_PHY(0x10ad, 0x0000), 219 + PARAM_WRITE_PHY(0x10af, 0x0001), 220 + PARAM_WRITE_PHY(0x10b6, 0x0001), 221 + PARAM_WRITE_PHY(0x10ae, 0x0000), 222 + 223 + PARAM_WRITE_PHY(0x10ae, 0x0001), 224 + PARAM_WRITE_PHY(0x10ad, 0x0000), 225 + PARAM_WRITE_PHY(0x10af, 0x0002), 226 + PARAM_WRITE_PHY(0x10b6, 0x0001), 227 + PARAM_WRITE_PHY(0x10ae, 0x0000), 228 + 229 + PARAM_WRITE_PHY(0x10ae, 0x0001), 230 + PARAM_WRITE_PHY(0x10ad, 0x0080), 231 + PARAM_WRITE_PHY(0x10af, 0x0000), 232 + PARAM_WRITE_PHY(0x10b6, 0x0001), 233 + PARAM_WRITE_PHY(0x10ae, 0x0000), 234 + 235 + PARAM_WRITE_PHY(0x10ae, 0x0001), 236 + PARAM_WRITE_PHY(0x10ad, 0x0080), 237 + PARAM_WRITE_PHY(0x10af, 0x001a), 238 + PARAM_WRITE_PHY(0x10b6, 0x0001), 239 + PARAM_WRITE_PHY(0x10ae, 0x0000), 240 + 241 + PARAM_INDIRECT_WRITE(7, 0x70, 0x0016), 242 + PARAM_INDIRECT_WRITE(7, 0x71, 0x0016), 243 + PARAM_INDIRECT_WRITE(7, 0x72, 0x0014), 244 + PARAM_INDIRECT_WRITE(7, 0x73, 0x0014), 245 + PARAM_INDIRECT_WRITE(7, 0x74, 0x0000), 246 + PARAM_INDIRECT_WRITE(7, 0x75, 0x0000), 247 + PARAM_INDIRECT_WRITE(7, 0x76, 0x0010), 248 + PARAM_INDIRECT_WRITE(7, 0x77, 0x0010), 249 + PARAM_INDIRECT_WRITE(7, 0x78, 0x00ff), 250 + PARAM_INDIRECT_WRITE(7, 0x79, 0x0000), 251 + 252 + PARAM_INDIRECT_WRITE(7, 0x19, 0x0007), 253 + 254 + PARAM_INDIRECT_WRITE(7, 0x1a, 0x0007), 255 + 256 + PARAM_INDIRECT_WRITE(7, 0x24, 0x000c), 257 + 258 + PARAM_INDIRECT_WRITE(7, 0x25, 0x000c), 259 + 260 + PARAM_INDIRECT_WRITE(7, 0x62, 0x0000), 261 + PARAM_INDIRECT_WRITE(7, 0x63, 0x0000), 262 + PARAM_INDIRECT_WRITE(7, 0x5d, 0x0014), 263 + PARAM_INDIRECT_WRITE(7, 0x5e, 0x0017), 264 + PARAM_INDIRECT_WRITE(7, 0x5d, 0x0004), 265 + PARAM_INDIRECT_WRITE(7, 0x5e, 0x0017), 266 + PARAM_INDIRECT_POLL(7, 0x55, 0, BIT(6)), 267 + PARAM_INDIRECT_POLL(7, 0x41, 0, BIT(7)), 268 + /* end of phy setup */ 269 + 270 + PARAM_WRITE(0xf0, 0), 271 + PARAM_WRITE(0xd0, 0x00000d00), 272 + PARAM_RESTORE(0xd4, TIMER_INDEX), 273 + }; 274 + 275 + static void ufs_renesas_dbg_register_dump(struct ufs_hba *hba) 276 + { 277 + ufshcd_dump_regs(hba, 0xc0, 0x40, "regs: 0xc0 + "); 278 + } 279 + 280 + static void ufs_renesas_reg_control(struct ufs_hba *hba, 281 + const struct ufs_renesas_init_param *p) 282 + { 283 + static u32 save[MAX_INDEX]; 284 + int ret; 285 + u32 val; 286 + 287 + WARN_ON(p->index >= MAX_INDEX); 288 + 289 + switch (p->mode) { 290 + case MODE_RESTORE: 291 + ufshcd_writel(hba, save[p->index], p->reg); 292 + break; 293 + case MODE_SET: 294 + save[p->index] |= p->u.set; 295 + break; 296 + case MODE_SAVE: 297 + save[p->index] = ufshcd_readl(hba, p->reg) & p->mask; 298 + break; 299 + case MODE_POLL: 300 + ret = readl_poll_timeout_atomic(hba->mmio_base + p->reg, 301 + val, 302 + (val & p->mask) == p->u.expected, 303 + 10, 1000); 304 + if (ret) 305 + dev_err(hba->dev, "%s: poll failed %d (%08x, %08x, %08x)\n", 306 + __func__, ret, val, p->mask, p->u.expected); 307 + break; 308 + case MODE_WAIT: 309 + if (p->u.delay_us > 1000) 310 + mdelay(DIV_ROUND_UP(p->u.delay_us, 1000)); 311 + else 312 + udelay(p->u.delay_us); 313 + break; 314 + case MODE_WRITE: 315 + ufshcd_writel(hba, p->u.val, p->reg); 316 + break; 317 + default: 318 + break; 319 + } 320 + } 321 + 322 + static void ufs_renesas_pre_init(struct ufs_hba *hba) 323 + { 324 + const struct ufs_renesas_init_param *p = ufs_param; 325 + unsigned int i; 326 + 327 + for (i = 0; i < ARRAY_SIZE(ufs_param); i++) 328 + ufs_renesas_reg_control(hba, &p[i]); 329 + } 330 + 331 + static int ufs_renesas_hce_enable_notify(struct ufs_hba *hba, 332 + enum ufs_notify_change_status status) 333 + { 334 + struct ufs_renesas_priv *priv = ufshcd_get_variant(hba); 335 + 336 + if (priv->initialized) 337 + return 0; 338 + 339 + if (status == PRE_CHANGE) 340 + ufs_renesas_pre_init(hba); 341 + 342 + priv->initialized = true; 343 + 344 + return 0; 345 + } 346 + 347 + static int ufs_renesas_setup_clocks(struct ufs_hba *hba, bool on, 348 + enum ufs_notify_change_status status) 349 + { 350 + if (on && status == PRE_CHANGE) 351 + pm_runtime_get_sync(hba->dev); 352 + else if (!on && status == POST_CHANGE) 353 + pm_runtime_put(hba->dev); 354 + 355 + return 0; 356 + } 357 + 358 + static int ufs_renesas_init(struct ufs_hba *hba) 359 + { 360 + struct ufs_renesas_priv *priv; 361 + 362 + priv = devm_kmalloc(hba->dev, sizeof(*priv), GFP_KERNEL); 363 + if (!priv) 364 + return -ENOMEM; 365 + ufshcd_set_variant(hba, priv); 366 + 367 + hba->quirks |= UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS | UFSHCD_QUIRK_HIBERN_FASTAUTO; 368 + 369 + return 0; 370 + } 371 + 372 + static const struct ufs_hba_variant_ops ufs_renesas_vops = { 373 + .name = "renesas", 374 + .init = ufs_renesas_init, 375 + .setup_clocks = ufs_renesas_setup_clocks, 376 + .hce_enable_notify = ufs_renesas_hce_enable_notify, 377 + .dbg_register_dump = ufs_renesas_dbg_register_dump, 378 + }; 379 + 380 + static const struct of_device_id __maybe_unused ufs_renesas_of_match[] = { 381 + { .compatible = "renesas,r8a779f0-ufs" }, 382 + { /* sentinel */ } 383 + }; 384 + MODULE_DEVICE_TABLE(of, ufs_renesas_of_match); 385 + 386 + static int ufs_renesas_probe(struct platform_device *pdev) 387 + { 388 + return ufshcd_pltfrm_init(pdev, &ufs_renesas_vops); 389 + } 390 + 391 + static int ufs_renesas_remove(struct platform_device *pdev) 392 + { 393 + struct ufs_hba *hba = platform_get_drvdata(pdev); 394 + 395 + ufshcd_remove(hba); 396 + 397 + return 0; 398 + } 399 + 400 + static struct platform_driver ufs_renesas_platform = { 401 + .probe = ufs_renesas_probe, 402 + .remove = ufs_renesas_remove, 403 + .driver = { 404 + .name = "ufshcd-renesas", 405 + .of_match_table = of_match_ptr(ufs_renesas_of_match), 406 + }, 407 + }; 408 + module_platform_driver(ufs_renesas_platform); 409 + 410 + MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>"); 411 + MODULE_DESCRIPTION("Renesas UFS host controller driver"); 412 + MODULE_LICENSE("Dual MIT/GPL");