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 #define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \ 54 UNIPHIER_RESETX((id), 0x2000, 10) 55 56 #define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \ 57 UNIPHIER_RESETX((id), 0x200c, 8) 58 59 #define UNIPHIER_PRO4_SYS_RESET_GIO(id) \ 60 UNIPHIER_RESETX((id), 0x2000, 6) 61 62 #define UNIPHIER_LD20_SYS_RESET_GIO(id) \ 63 UNIPHIER_RESETX((id), 0x200c, 5) 64 65 #define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \ 66 UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17) 67 68 const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { 69 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */ 70 UNIPHIER_RESET_END, 71 }; 72 73 const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { 74 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */ 75 UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */ 76 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), 77 UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), 78 UNIPHIER_RESET_END, 79 }; 80 81 const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { 82 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */ 83 UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */ 84 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), 85 UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), 86 UNIPHIER_RESET_END, 87 }; 88 89 const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { 90 UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */ 91 UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), 92 UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), 93 UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */ 94 UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */ 95 UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */ 96 UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */ 97 UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */ 98 UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */ 99 UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */ 100 UNIPHIER_RESET_END, 101 }; 102 103 const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { 104 UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */ 105 UNIPHIER_RESET_END, 106 }; 107 108 const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { 109 UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */ 110 UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */ 111 UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */ 112 UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */ 113 UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */ 114 UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */ 115 UNIPHIER_RESET_END, 116 }; 117 118 /* Media I/O reset data */ 119 #define UNIPHIER_MIO_RESET_SD(id, ch) \ 120 UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0) 121 122 #define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch) \ 123 UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26) 124 125 #define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch) \ 126 UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0) 127 128 #define UNIPHIER_MIO_RESET_USB2(id, ch) \ 129 UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0) 130 131 #define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch) \ 132 UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24) 133 134 #define UNIPHIER_MIO_RESET_DMAC(id) \ 135 UNIPHIER_RESETX((id), 0x110, 17) 136 137 const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = { 138 UNIPHIER_MIO_RESET_SD(0, 0), 139 UNIPHIER_MIO_RESET_SD(1, 1), 140 UNIPHIER_MIO_RESET_SD(2, 2), 141 UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0), 142 UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1), 143 UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2), 144 UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), 145 UNIPHIER_MIO_RESET_DMAC(7), 146 UNIPHIER_MIO_RESET_USB2(8, 0), 147 UNIPHIER_MIO_RESET_USB2(9, 1), 148 UNIPHIER_MIO_RESET_USB2(10, 2), 149 UNIPHIER_MIO_RESET_USB2(11, 3), 150 UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0), 151 UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1), 152 UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2), 153 UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3), 154 UNIPHIER_RESET_END, 155 }; 156 157 const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = { 158 UNIPHIER_MIO_RESET_SD(0, 0), 159 UNIPHIER_MIO_RESET_SD(1, 1), 160 UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), 161 UNIPHIER_RESET_END, 162 }; 163 164 /* Peripheral reset data */ 165 #define UNIPHIER_PERI_RESET_UART(id, ch) \ 166 UNIPHIER_RESETX((id), 0x114, 19 + (ch)) 167 168 #define UNIPHIER_PERI_RESET_I2C(id, ch) \ 169 UNIPHIER_RESETX((id), 0x114, 5 + (ch)) 170 171 #define UNIPHIER_PERI_RESET_FI2C(id, ch) \ 172 UNIPHIER_RESETX((id), 0x114, 24 + (ch)) 173 174 const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { 175 UNIPHIER_PERI_RESET_UART(0, 0), 176 UNIPHIER_PERI_RESET_UART(1, 1), 177 UNIPHIER_PERI_RESET_UART(2, 2), 178 UNIPHIER_PERI_RESET_UART(3, 3), 179 UNIPHIER_PERI_RESET_I2C(4, 0), 180 UNIPHIER_PERI_RESET_I2C(5, 1), 181 UNIPHIER_PERI_RESET_I2C(6, 2), 182 UNIPHIER_PERI_RESET_I2C(7, 3), 183 UNIPHIER_PERI_RESET_I2C(8, 4), 184 UNIPHIER_RESET_END, 185 }; 186 187 const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { 188 UNIPHIER_PERI_RESET_UART(0, 0), 189 UNIPHIER_PERI_RESET_UART(1, 1), 190 UNIPHIER_PERI_RESET_UART(2, 2), 191 UNIPHIER_PERI_RESET_UART(3, 3), 192 UNIPHIER_PERI_RESET_FI2C(4, 0), 193 UNIPHIER_PERI_RESET_FI2C(5, 1), 194 UNIPHIER_PERI_RESET_FI2C(6, 2), 195 UNIPHIER_PERI_RESET_FI2C(7, 3), 196 UNIPHIER_PERI_RESET_FI2C(8, 4), 197 UNIPHIER_PERI_RESET_FI2C(9, 5), 198 UNIPHIER_PERI_RESET_FI2C(10, 6), 199 UNIPHIER_RESET_END, 200 }; 201 202 /* core implementaton */ 203 struct uniphier_reset_priv { 204 struct reset_controller_dev rcdev; 205 struct device *dev; 206 struct regmap *regmap; 207 const struct uniphier_reset_data *data; 208 }; 209 210 #define to_uniphier_reset_priv(_rcdev) \ 211 container_of(_rcdev, struct uniphier_reset_priv, rcdev) 212 213 static int uniphier_reset_update(struct reset_controller_dev *rcdev, 214 unsigned long id, int assert) 215 { 216 struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev); 217 const struct uniphier_reset_data *p; 218 219 for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) { 220 unsigned int mask, val; 221 222 if (p->id != id) 223 continue; 224 225 mask = BIT(p->bit); 226 227 if (assert) 228 val = mask; 229 else 230 val = ~mask; 231 232 if (p->flags & UNIPHIER_RESET_ACTIVE_LOW) 233 val = ~val; 234 235 return regmap_write_bits(priv->regmap, p->reg, mask, val); 236 } 237 238 dev_err(priv->dev, "reset_id=%lu was not handled\n", id); 239 return -EINVAL; 240 } 241 242 static int uniphier_reset_assert(struct reset_controller_dev *rcdev, 243 unsigned long id) 244 { 245 return uniphier_reset_update(rcdev, id, 1); 246 } 247 248 static int uniphier_reset_deassert(struct reset_controller_dev *rcdev, 249 unsigned long id) 250 { 251 return uniphier_reset_update(rcdev, id, 0); 252 } 253 254 static int uniphier_reset_status(struct reset_controller_dev *rcdev, 255 unsigned long id) 256 { 257 struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev); 258 const struct uniphier_reset_data *p; 259 260 for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) { 261 unsigned int val; 262 int ret, asserted; 263 264 if (p->id != id) 265 continue; 266 267 ret = regmap_read(priv->regmap, p->reg, &val); 268 if (ret) 269 return ret; 270 271 asserted = !!(val & BIT(p->bit)); 272 273 if (p->flags & UNIPHIER_RESET_ACTIVE_LOW) 274 asserted = !asserted; 275 276 return asserted; 277 } 278 279 dev_err(priv->dev, "reset_id=%lu was not found\n", id); 280 return -EINVAL; 281 } 282 283 static const struct reset_control_ops uniphier_reset_ops = { 284 .assert = uniphier_reset_assert, 285 .deassert = uniphier_reset_deassert, 286 .status = uniphier_reset_status, 287 }; 288 289 static int uniphier_reset_probe(struct platform_device *pdev) 290 { 291 struct device *dev = &pdev->dev; 292 struct uniphier_reset_priv *priv; 293 const struct uniphier_reset_data *p, *data; 294 struct regmap *regmap; 295 struct device_node *parent; 296 unsigned int nr_resets = 0; 297 298 data = of_device_get_match_data(dev); 299 if (WARN_ON(!data)) 300 return -EINVAL; 301 302 parent = of_get_parent(dev->of_node); /* parent should be syscon node */ 303 regmap = syscon_node_to_regmap(parent); 304 of_node_put(parent); 305 if (IS_ERR(regmap)) { 306 dev_err(dev, "failed to get regmap (error %ld)\n", 307 PTR_ERR(regmap)); 308 return PTR_ERR(regmap); 309 } 310 311 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 312 if (!priv) 313 return -ENOMEM; 314 315 for (p = data; p->id != UNIPHIER_RESET_ID_END; p++) 316 nr_resets = max(nr_resets, p->id + 1); 317 318 priv->rcdev.ops = &uniphier_reset_ops; 319 priv->rcdev.owner = dev->driver->owner; 320 priv->rcdev.of_node = dev->of_node; 321 priv->rcdev.nr_resets = nr_resets; 322 priv->dev = dev; 323 priv->regmap = regmap; 324 priv->data = data; 325 326 return devm_reset_controller_register(&pdev->dev, &priv->rcdev); 327 } 328 329 static const struct of_device_id uniphier_reset_match[] = { 330 /* System reset */ 331 { 332 .compatible = "socionext,uniphier-sld3-reset", 333 .data = uniphier_sld3_sys_reset_data, 334 }, 335 { 336 .compatible = "socionext,uniphier-ld4-reset", 337 .data = uniphier_sld3_sys_reset_data, 338 }, 339 { 340 .compatible = "socionext,uniphier-pro4-reset", 341 .data = uniphier_pro4_sys_reset_data, 342 }, 343 { 344 .compatible = "socionext,uniphier-sld8-reset", 345 .data = uniphier_sld3_sys_reset_data, 346 }, 347 { 348 .compatible = "socionext,uniphier-pro5-reset", 349 .data = uniphier_pro5_sys_reset_data, 350 }, 351 { 352 .compatible = "socionext,uniphier-pxs2-reset", 353 .data = uniphier_pxs2_sys_reset_data, 354 }, 355 { 356 .compatible = "socionext,uniphier-ld11-reset", 357 .data = uniphier_ld11_sys_reset_data, 358 }, 359 { 360 .compatible = "socionext,uniphier-ld20-reset", 361 .data = uniphier_ld20_sys_reset_data, 362 }, 363 /* Media I/O reset, SD reset */ 364 { 365 .compatible = "socionext,uniphier-sld3-mio-reset", 366 .data = uniphier_sld3_mio_reset_data, 367 }, 368 { 369 .compatible = "socionext,uniphier-ld4-mio-reset", 370 .data = uniphier_sld3_mio_reset_data, 371 }, 372 { 373 .compatible = "socionext,uniphier-pro4-mio-reset", 374 .data = uniphier_sld3_mio_reset_data, 375 }, 376 { 377 .compatible = "socionext,uniphier-sld8-mio-reset", 378 .data = uniphier_sld3_mio_reset_data, 379 }, 380 { 381 .compatible = "socionext,uniphier-pro5-sd-reset", 382 .data = uniphier_pro5_sd_reset_data, 383 }, 384 { 385 .compatible = "socionext,uniphier-pxs2-sd-reset", 386 .data = uniphier_pro5_sd_reset_data, 387 }, 388 { 389 .compatible = "socionext,uniphier-ld11-mio-reset", 390 .data = uniphier_sld3_mio_reset_data, 391 }, 392 { 393 .compatible = "socionext,uniphier-ld20-sd-reset", 394 .data = uniphier_pro5_sd_reset_data, 395 }, 396 /* Peripheral reset */ 397 { 398 .compatible = "socionext,uniphier-ld4-peri-reset", 399 .data = uniphier_ld4_peri_reset_data, 400 }, 401 { 402 .compatible = "socionext,uniphier-pro4-peri-reset", 403 .data = uniphier_pro4_peri_reset_data, 404 }, 405 { 406 .compatible = "socionext,uniphier-sld8-peri-reset", 407 .data = uniphier_ld4_peri_reset_data, 408 }, 409 { 410 .compatible = "socionext,uniphier-pro5-peri-reset", 411 .data = uniphier_pro4_peri_reset_data, 412 }, 413 { 414 .compatible = "socionext,uniphier-pxs2-peri-reset", 415 .data = uniphier_pro4_peri_reset_data, 416 }, 417 { 418 .compatible = "socionext,uniphier-ld11-peri-reset", 419 .data = uniphier_pro4_peri_reset_data, 420 }, 421 { 422 .compatible = "socionext,uniphier-ld20-peri-reset", 423 .data = uniphier_pro4_peri_reset_data, 424 }, 425 { /* sentinel */ } 426 }; 427 MODULE_DEVICE_TABLE(of, uniphier_reset_match); 428 429 static struct platform_driver uniphier_reset_driver = { 430 .probe = uniphier_reset_probe, 431 .driver = { 432 .name = "uniphier-reset", 433 .of_match_table = uniphier_reset_match, 434 }, 435 }; 436 module_platform_driver(uniphier_reset_driver); 437 438 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 439 MODULE_DESCRIPTION("UniPhier Reset Controller Driver"); 440 MODULE_LICENSE("GPL"); 441