1*75a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 28a56736aSDamien Horsley /* 38a56736aSDamien Horsley * Pistachio SoC Reset Controller driver 48a56736aSDamien Horsley * 58a56736aSDamien Horsley * Copyright (C) 2015 Imagination Technologies Ltd. 68a56736aSDamien Horsley * 78a56736aSDamien Horsley * Author: Damien Horsley <Damien.Horsley@imgtec.com> 88a56736aSDamien Horsley */ 98a56736aSDamien Horsley 1001db1cb1SPaul Gortmaker #include <linux/init.h> 118a56736aSDamien Horsley #include <linux/of.h> 128a56736aSDamien Horsley #include <linux/platform_device.h> 138a56736aSDamien Horsley #include <linux/regmap.h> 148a56736aSDamien Horsley #include <linux/reset-controller.h> 158a56736aSDamien Horsley #include <linux/slab.h> 168a56736aSDamien Horsley #include <linux/mfd/syscon.h> 178a56736aSDamien Horsley 188a56736aSDamien Horsley #include <dt-bindings/reset/pistachio-resets.h> 198a56736aSDamien Horsley 208a56736aSDamien Horsley #define PISTACHIO_SOFT_RESET 0 218a56736aSDamien Horsley 228a56736aSDamien Horsley struct pistachio_reset_data { 238a56736aSDamien Horsley struct reset_controller_dev rcdev; 248a56736aSDamien Horsley struct regmap *periph_regs; 258a56736aSDamien Horsley }; 268a56736aSDamien Horsley 278a56736aSDamien Horsley static inline int pistachio_reset_shift(unsigned long id) 288a56736aSDamien Horsley { 298a56736aSDamien Horsley switch (id) { 308a56736aSDamien Horsley case PISTACHIO_RESET_I2C0: 318a56736aSDamien Horsley case PISTACHIO_RESET_I2C1: 328a56736aSDamien Horsley case PISTACHIO_RESET_I2C2: 338a56736aSDamien Horsley case PISTACHIO_RESET_I2C3: 348a56736aSDamien Horsley case PISTACHIO_RESET_I2S_IN: 358a56736aSDamien Horsley case PISTACHIO_RESET_PRL_OUT: 368a56736aSDamien Horsley case PISTACHIO_RESET_SPDIF_OUT: 378a56736aSDamien Horsley case PISTACHIO_RESET_SPI: 388a56736aSDamien Horsley case PISTACHIO_RESET_PWM_PDM: 398a56736aSDamien Horsley case PISTACHIO_RESET_UART0: 408a56736aSDamien Horsley case PISTACHIO_RESET_UART1: 418a56736aSDamien Horsley case PISTACHIO_RESET_QSPI: 428a56736aSDamien Horsley case PISTACHIO_RESET_MDC: 438a56736aSDamien Horsley case PISTACHIO_RESET_SDHOST: 448a56736aSDamien Horsley case PISTACHIO_RESET_ETHERNET: 458a56736aSDamien Horsley case PISTACHIO_RESET_IR: 468a56736aSDamien Horsley case PISTACHIO_RESET_HASH: 478a56736aSDamien Horsley case PISTACHIO_RESET_TIMER: 488a56736aSDamien Horsley return id; 498a56736aSDamien Horsley case PISTACHIO_RESET_I2S_OUT: 508a56736aSDamien Horsley case PISTACHIO_RESET_SPDIF_IN: 518a56736aSDamien Horsley case PISTACHIO_RESET_EVT: 528a56736aSDamien Horsley return id + 6; 538a56736aSDamien Horsley case PISTACHIO_RESET_USB_H: 548a56736aSDamien Horsley case PISTACHIO_RESET_USB_PR: 558a56736aSDamien Horsley case PISTACHIO_RESET_USB_PHY_PR: 568a56736aSDamien Horsley case PISTACHIO_RESET_USB_PHY_PON: 578a56736aSDamien Horsley return id + 7; 588a56736aSDamien Horsley default: 598a56736aSDamien Horsley return -EINVAL; 608a56736aSDamien Horsley } 618a56736aSDamien Horsley } 628a56736aSDamien Horsley 638a56736aSDamien Horsley static int pistachio_reset_assert(struct reset_controller_dev *rcdev, 648a56736aSDamien Horsley unsigned long id) 658a56736aSDamien Horsley { 668a56736aSDamien Horsley struct pistachio_reset_data *rd; 678a56736aSDamien Horsley u32 mask; 688a56736aSDamien Horsley int shift; 698a56736aSDamien Horsley 708a56736aSDamien Horsley rd = container_of(rcdev, struct pistachio_reset_data, rcdev); 718a56736aSDamien Horsley shift = pistachio_reset_shift(id); 728a56736aSDamien Horsley if (shift < 0) 738a56736aSDamien Horsley return shift; 748a56736aSDamien Horsley mask = BIT(shift); 758a56736aSDamien Horsley 768a56736aSDamien Horsley return regmap_update_bits(rd->periph_regs, PISTACHIO_SOFT_RESET, 778a56736aSDamien Horsley mask, mask); 788a56736aSDamien Horsley } 798a56736aSDamien Horsley 808a56736aSDamien Horsley static int pistachio_reset_deassert(struct reset_controller_dev *rcdev, 818a56736aSDamien Horsley unsigned long id) 828a56736aSDamien Horsley { 838a56736aSDamien Horsley struct pistachio_reset_data *rd; 848a56736aSDamien Horsley u32 mask; 858a56736aSDamien Horsley int shift; 868a56736aSDamien Horsley 878a56736aSDamien Horsley rd = container_of(rcdev, struct pistachio_reset_data, rcdev); 888a56736aSDamien Horsley shift = pistachio_reset_shift(id); 898a56736aSDamien Horsley if (shift < 0) 908a56736aSDamien Horsley return shift; 918a56736aSDamien Horsley mask = BIT(shift); 928a56736aSDamien Horsley 938a56736aSDamien Horsley return regmap_update_bits(rd->periph_regs, PISTACHIO_SOFT_RESET, 948a56736aSDamien Horsley mask, 0); 958a56736aSDamien Horsley } 968a56736aSDamien Horsley 97c0cc2609SPhilipp Zabel static const struct reset_control_ops pistachio_reset_ops = { 988a56736aSDamien Horsley .assert = pistachio_reset_assert, 998a56736aSDamien Horsley .deassert = pistachio_reset_deassert, 1008a56736aSDamien Horsley }; 1018a56736aSDamien Horsley 1028a56736aSDamien Horsley static int pistachio_reset_probe(struct platform_device *pdev) 1038a56736aSDamien Horsley { 1048a56736aSDamien Horsley struct pistachio_reset_data *rd; 1058a56736aSDamien Horsley struct device *dev = &pdev->dev; 1068a56736aSDamien Horsley struct device_node *np = pdev->dev.of_node; 1078a56736aSDamien Horsley 1088a56736aSDamien Horsley rd = devm_kzalloc(dev, sizeof(*rd), GFP_KERNEL); 1098a56736aSDamien Horsley if (!rd) 1108a56736aSDamien Horsley return -ENOMEM; 1118a56736aSDamien Horsley 1128a56736aSDamien Horsley rd->periph_regs = syscon_node_to_regmap(np->parent); 1138a56736aSDamien Horsley if (IS_ERR(rd->periph_regs)) 1148a56736aSDamien Horsley return PTR_ERR(rd->periph_regs); 1158a56736aSDamien Horsley 1168a56736aSDamien Horsley rd->rcdev.owner = THIS_MODULE; 1178a56736aSDamien Horsley rd->rcdev.nr_resets = PISTACHIO_RESET_MAX + 1; 1188a56736aSDamien Horsley rd->rcdev.ops = &pistachio_reset_ops; 1198a56736aSDamien Horsley rd->rcdev.of_node = np; 1208a56736aSDamien Horsley 1211b1447f4SMasahiro Yamada return devm_reset_controller_register(dev, &rd->rcdev); 1228a56736aSDamien Horsley } 1238a56736aSDamien Horsley 1248a56736aSDamien Horsley static const struct of_device_id pistachio_reset_dt_ids[] = { 1258a56736aSDamien Horsley { .compatible = "img,pistachio-reset", }, 1268a56736aSDamien Horsley { /* sentinel */ }, 1278a56736aSDamien Horsley }; 1288a56736aSDamien Horsley 1298a56736aSDamien Horsley static struct platform_driver pistachio_reset_driver = { 1308a56736aSDamien Horsley .probe = pistachio_reset_probe, 1318a56736aSDamien Horsley .driver = { 1328a56736aSDamien Horsley .name = "pistachio-reset", 1338a56736aSDamien Horsley .of_match_table = pistachio_reset_dt_ids, 1348a56736aSDamien Horsley }, 1358a56736aSDamien Horsley }; 13601db1cb1SPaul Gortmaker builtin_platform_driver(pistachio_reset_driver); 137