1 /* 2 * Copyright (C) 2016 Socionext Inc. 3 * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/mfd/syscon.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/of_device.h> 20 #include <linux/platform_device.h> 21 #include <linux/regmap.h> 22 #include <linux/reset-controller.h> 23 24 struct uniphier_reset_data { 25 unsigned int id; 26 unsigned int reg; 27 unsigned int bit; 28 unsigned int flags; 29 #define UNIPHIER_RESET_ACTIVE_LOW BIT(0) 30 }; 31 32 #define UNIPHIER_RESET_ID_END (unsigned int)(-1) 33 34 #define UNIPHIER_RESET_END \ 35 { .id = UNIPHIER_RESET_ID_END } 36 37 #define UNIPHIER_RESET(_id, _reg, _bit) \ 38 { \ 39 .id = (_id), \ 40 .reg = (_reg), \ 41 .bit = (_bit), \ 42 } 43 44 #define UNIPHIER_RESETX(_id, _reg, _bit) \ 45 { \ 46 .id = (_id), \ 47 .reg = (_reg), \ 48 .bit = (_bit), \ 49 .flags = UNIPHIER_RESET_ACTIVE_LOW, \ 50 } 51 52 /* System reset data */ 53 static const struct uniphier_reset_data uniphier_ld4_sys_reset_data[] = { 54 UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ 55 UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (Ether, HSC, MIO) */ 56 UNIPHIER_RESET_END, 57 }; 58 59 static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { 60 UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ 61 UNIPHIER_RESETX(6, 0x2000, 12), /* Ether */ 62 UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, MIO, RLE) */ 63 UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (Ether, SATA, USB3) */ 64 UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */ 65 UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */ 66 UNIPHIER_RESETX(40, 0x2000, 13), /* AIO */ 67 UNIPHIER_RESET_END, 68 }; 69 70 static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { 71 UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ 72 UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC) */ 73 UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (PCIe, USB3) */ 74 UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */ 75 UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */ 76 UNIPHIER_RESETX(40, 0x2000, 13), /* AIO */ 77 UNIPHIER_RESET_END, 78 }; 79 80 static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { 81 UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ 82 UNIPHIER_RESETX(6, 0x2000, 12), /* Ether */ 83 UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, RLE) */ 84 UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */ 85 UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */ 86 UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */ 87 UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */ 88 UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */ 89 UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */ 90 UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */ 91 UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */ 92 UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */ 93 UNIPHIER_RESETX(40, 0x2000, 13), /* AIO */ 94 UNIPHIER_RESET_END, 95 }; 96 97 static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { 98 UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */ 99 UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */ 100 UNIPHIER_RESETX(6, 0x200c, 6), /* Ether */ 101 UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC, MIO) */ 102 UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */ 103 UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */ 104 UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */ 105 UNIPHIER_RESET_END, 106 }; 107 108 static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { 109 UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */ 110 UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */ 111 UNIPHIER_RESETX(6, 0x200c, 6), /* Ether */ 112 UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC) */ 113 UNIPHIER_RESETX(12, 0x200c, 5), /* GIO (PCIe, USB3) */ 114 UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */ 115 UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */ 116 UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */ 117 UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */ 118 UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */ 119 UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */ 120 UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */ 121 UNIPHIER_RESET_END, 122 }; 123 124 static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = { 125 UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */ 126 UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */ 127 UNIPHIER_RESETX(6, 0x200c, 9), /* Ether0 */ 128 UNIPHIER_RESETX(7, 0x200c, 10), /* Ether1 */ 129 UNIPHIER_RESETX(8, 0x200c, 12), /* STDMAC */ 130 UNIPHIER_RESETX(12, 0x200c, 4), /* USB30 link (GIO0) */ 131 UNIPHIER_RESETX(13, 0x200c, 5), /* USB31 link (GIO1) */ 132 UNIPHIER_RESETX(16, 0x200c, 16), /* USB30-PHY0 */ 133 UNIPHIER_RESETX(17, 0x200c, 18), /* USB30-PHY1 */ 134 UNIPHIER_RESETX(18, 0x200c, 20), /* USB30-PHY2 */ 135 UNIPHIER_RESETX(20, 0x200c, 17), /* USB31-PHY0 */ 136 UNIPHIER_RESETX(21, 0x200c, 19), /* USB31-PHY1 */ 137 UNIPHIER_RESET_END, 138 }; 139 140 /* Media I/O reset data */ 141 #define UNIPHIER_MIO_RESET_SD(id, ch) \ 142 UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0) 143 144 #define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch) \ 145 UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26) 146 147 #define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch) \ 148 UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0) 149 150 #define UNIPHIER_MIO_RESET_USB2(id, ch) \ 151 UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0) 152 153 #define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch) \ 154 UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24) 155 156 #define UNIPHIER_MIO_RESET_DMAC(id) \ 157 UNIPHIER_RESETX((id), 0x110, 17) 158 159 static const struct uniphier_reset_data uniphier_ld4_mio_reset_data[] = { 160 UNIPHIER_MIO_RESET_SD(0, 0), 161 UNIPHIER_MIO_RESET_SD(1, 1), 162 UNIPHIER_MIO_RESET_SD(2, 2), 163 UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0), 164 UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1), 165 UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2), 166 UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), 167 UNIPHIER_MIO_RESET_DMAC(7), 168 UNIPHIER_MIO_RESET_USB2(8, 0), 169 UNIPHIER_MIO_RESET_USB2(9, 1), 170 UNIPHIER_MIO_RESET_USB2(10, 2), 171 UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0), 172 UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1), 173 UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2), 174 UNIPHIER_RESET_END, 175 }; 176 177 static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = { 178 UNIPHIER_MIO_RESET_SD(0, 0), 179 UNIPHIER_MIO_RESET_SD(1, 1), 180 UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), 181 UNIPHIER_RESET_END, 182 }; 183 184 /* Peripheral reset data */ 185 #define UNIPHIER_PERI_RESET_UART(id, ch) \ 186 UNIPHIER_RESETX((id), 0x114, 19 + (ch)) 187 188 #define UNIPHIER_PERI_RESET_I2C(id, ch) \ 189 UNIPHIER_RESETX((id), 0x114, 5 + (ch)) 190 191 #define UNIPHIER_PERI_RESET_FI2C(id, ch) \ 192 UNIPHIER_RESETX((id), 0x114, 24 + (ch)) 193 194 static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { 195 UNIPHIER_PERI_RESET_UART(0, 0), 196 UNIPHIER_PERI_RESET_UART(1, 1), 197 UNIPHIER_PERI_RESET_UART(2, 2), 198 UNIPHIER_PERI_RESET_UART(3, 3), 199 UNIPHIER_PERI_RESET_I2C(4, 0), 200 UNIPHIER_PERI_RESET_I2C(5, 1), 201 UNIPHIER_PERI_RESET_I2C(6, 2), 202 UNIPHIER_PERI_RESET_I2C(7, 3), 203 UNIPHIER_PERI_RESET_I2C(8, 4), 204 UNIPHIER_RESET_END, 205 }; 206 207 static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { 208 UNIPHIER_PERI_RESET_UART(0, 0), 209 UNIPHIER_PERI_RESET_UART(1, 1), 210 UNIPHIER_PERI_RESET_UART(2, 2), 211 UNIPHIER_PERI_RESET_UART(3, 3), 212 UNIPHIER_PERI_RESET_FI2C(4, 0), 213 UNIPHIER_PERI_RESET_FI2C(5, 1), 214 UNIPHIER_PERI_RESET_FI2C(6, 2), 215 UNIPHIER_PERI_RESET_FI2C(7, 3), 216 UNIPHIER_PERI_RESET_FI2C(8, 4), 217 UNIPHIER_PERI_RESET_FI2C(9, 5), 218 UNIPHIER_PERI_RESET_FI2C(10, 6), 219 UNIPHIER_RESET_END, 220 }; 221 222 /* Analog signal amplifiers reset data */ 223 static const struct uniphier_reset_data uniphier_ld11_adamv_reset_data[] = { 224 UNIPHIER_RESETX(0, 0x10, 6), /* EVEA */ 225 UNIPHIER_RESET_END, 226 }; 227 228 /* core implementaton */ 229 struct uniphier_reset_priv { 230 struct reset_controller_dev rcdev; 231 struct device *dev; 232 struct regmap *regmap; 233 const struct uniphier_reset_data *data; 234 }; 235 236 #define to_uniphier_reset_priv(_rcdev) \ 237 container_of(_rcdev, struct uniphier_reset_priv, rcdev) 238 239 static int uniphier_reset_update(struct reset_controller_dev *rcdev, 240 unsigned long id, int assert) 241 { 242 struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev); 243 const struct uniphier_reset_data *p; 244 245 for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) { 246 unsigned int mask, val; 247 248 if (p->id != id) 249 continue; 250 251 mask = BIT(p->bit); 252 253 if (assert) 254 val = mask; 255 else 256 val = ~mask; 257 258 if (p->flags & UNIPHIER_RESET_ACTIVE_LOW) 259 val = ~val; 260 261 return regmap_write_bits(priv->regmap, p->reg, mask, val); 262 } 263 264 dev_err(priv->dev, "reset_id=%lu was not handled\n", id); 265 return -EINVAL; 266 } 267 268 static int uniphier_reset_assert(struct reset_controller_dev *rcdev, 269 unsigned long id) 270 { 271 return uniphier_reset_update(rcdev, id, 1); 272 } 273 274 static int uniphier_reset_deassert(struct reset_controller_dev *rcdev, 275 unsigned long id) 276 { 277 return uniphier_reset_update(rcdev, id, 0); 278 } 279 280 static int uniphier_reset_status(struct reset_controller_dev *rcdev, 281 unsigned long id) 282 { 283 struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev); 284 const struct uniphier_reset_data *p; 285 286 for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) { 287 unsigned int val; 288 int ret, asserted; 289 290 if (p->id != id) 291 continue; 292 293 ret = regmap_read(priv->regmap, p->reg, &val); 294 if (ret) 295 return ret; 296 297 asserted = !!(val & BIT(p->bit)); 298 299 if (p->flags & UNIPHIER_RESET_ACTIVE_LOW) 300 asserted = !asserted; 301 302 return asserted; 303 } 304 305 dev_err(priv->dev, "reset_id=%lu was not found\n", id); 306 return -EINVAL; 307 } 308 309 static const struct reset_control_ops uniphier_reset_ops = { 310 .assert = uniphier_reset_assert, 311 .deassert = uniphier_reset_deassert, 312 .status = uniphier_reset_status, 313 }; 314 315 static int uniphier_reset_probe(struct platform_device *pdev) 316 { 317 struct device *dev = &pdev->dev; 318 struct uniphier_reset_priv *priv; 319 const struct uniphier_reset_data *p, *data; 320 struct regmap *regmap; 321 struct device_node *parent; 322 unsigned int nr_resets = 0; 323 324 data = of_device_get_match_data(dev); 325 if (WARN_ON(!data)) 326 return -EINVAL; 327 328 parent = of_get_parent(dev->of_node); /* parent should be syscon node */ 329 regmap = syscon_node_to_regmap(parent); 330 of_node_put(parent); 331 if (IS_ERR(regmap)) { 332 dev_err(dev, "failed to get regmap (error %ld)\n", 333 PTR_ERR(regmap)); 334 return PTR_ERR(regmap); 335 } 336 337 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 338 if (!priv) 339 return -ENOMEM; 340 341 for (p = data; p->id != UNIPHIER_RESET_ID_END; p++) 342 nr_resets = max(nr_resets, p->id + 1); 343 344 priv->rcdev.ops = &uniphier_reset_ops; 345 priv->rcdev.owner = dev->driver->owner; 346 priv->rcdev.of_node = dev->of_node; 347 priv->rcdev.nr_resets = nr_resets; 348 priv->dev = dev; 349 priv->regmap = regmap; 350 priv->data = data; 351 352 return devm_reset_controller_register(&pdev->dev, &priv->rcdev); 353 } 354 355 static const struct of_device_id uniphier_reset_match[] = { 356 /* System reset */ 357 { 358 .compatible = "socionext,uniphier-ld4-reset", 359 .data = uniphier_ld4_sys_reset_data, 360 }, 361 { 362 .compatible = "socionext,uniphier-pro4-reset", 363 .data = uniphier_pro4_sys_reset_data, 364 }, 365 { 366 .compatible = "socionext,uniphier-sld8-reset", 367 .data = uniphier_ld4_sys_reset_data, 368 }, 369 { 370 .compatible = "socionext,uniphier-pro5-reset", 371 .data = uniphier_pro5_sys_reset_data, 372 }, 373 { 374 .compatible = "socionext,uniphier-pxs2-reset", 375 .data = uniphier_pxs2_sys_reset_data, 376 }, 377 { 378 .compatible = "socionext,uniphier-ld11-reset", 379 .data = uniphier_ld11_sys_reset_data, 380 }, 381 { 382 .compatible = "socionext,uniphier-ld20-reset", 383 .data = uniphier_ld20_sys_reset_data, 384 }, 385 { 386 .compatible = "socionext,uniphier-pxs3-reset", 387 .data = uniphier_pxs3_sys_reset_data, 388 }, 389 /* Media I/O reset, SD reset */ 390 { 391 .compatible = "socionext,uniphier-ld4-mio-reset", 392 .data = uniphier_ld4_mio_reset_data, 393 }, 394 { 395 .compatible = "socionext,uniphier-pro4-mio-reset", 396 .data = uniphier_ld4_mio_reset_data, 397 }, 398 { 399 .compatible = "socionext,uniphier-sld8-mio-reset", 400 .data = uniphier_ld4_mio_reset_data, 401 }, 402 { 403 .compatible = "socionext,uniphier-pro5-sd-reset", 404 .data = uniphier_pro5_sd_reset_data, 405 }, 406 { 407 .compatible = "socionext,uniphier-pxs2-sd-reset", 408 .data = uniphier_pro5_sd_reset_data, 409 }, 410 { 411 .compatible = "socionext,uniphier-ld11-mio-reset", 412 .data = uniphier_ld4_mio_reset_data, 413 }, 414 { 415 .compatible = "socionext,uniphier-ld11-sd-reset", 416 .data = uniphier_pro5_sd_reset_data, 417 }, 418 { 419 .compatible = "socionext,uniphier-ld20-sd-reset", 420 .data = uniphier_pro5_sd_reset_data, 421 }, 422 { 423 .compatible = "socionext,uniphier-pxs3-sd-reset", 424 .data = uniphier_pro5_sd_reset_data, 425 }, 426 /* Peripheral reset */ 427 { 428 .compatible = "socionext,uniphier-ld4-peri-reset", 429 .data = uniphier_ld4_peri_reset_data, 430 }, 431 { 432 .compatible = "socionext,uniphier-pro4-peri-reset", 433 .data = uniphier_pro4_peri_reset_data, 434 }, 435 { 436 .compatible = "socionext,uniphier-sld8-peri-reset", 437 .data = uniphier_ld4_peri_reset_data, 438 }, 439 { 440 .compatible = "socionext,uniphier-pro5-peri-reset", 441 .data = uniphier_pro4_peri_reset_data, 442 }, 443 { 444 .compatible = "socionext,uniphier-pxs2-peri-reset", 445 .data = uniphier_pro4_peri_reset_data, 446 }, 447 { 448 .compatible = "socionext,uniphier-ld11-peri-reset", 449 .data = uniphier_pro4_peri_reset_data, 450 }, 451 { 452 .compatible = "socionext,uniphier-ld20-peri-reset", 453 .data = uniphier_pro4_peri_reset_data, 454 }, 455 { 456 .compatible = "socionext,uniphier-pxs3-peri-reset", 457 .data = uniphier_pro4_peri_reset_data, 458 }, 459 /* Analog signal amplifiers reset */ 460 { 461 .compatible = "socionext,uniphier-ld11-adamv-reset", 462 .data = uniphier_ld11_adamv_reset_data, 463 }, 464 { 465 .compatible = "socionext,uniphier-ld20-adamv-reset", 466 .data = uniphier_ld11_adamv_reset_data, 467 }, 468 { /* sentinel */ } 469 }; 470 MODULE_DEVICE_TABLE(of, uniphier_reset_match); 471 472 static struct platform_driver uniphier_reset_driver = { 473 .probe = uniphier_reset_probe, 474 .driver = { 475 .name = "uniphier-reset", 476 .of_match_table = uniphier_reset_match, 477 }, 478 }; 479 module_platform_driver(uniphier_reset_driver); 480 481 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 482 MODULE_DESCRIPTION("UniPhier Reset Controller Driver"); 483 MODULE_LICENSE("GPL"); 484