1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/slab.h> 3 #include <linux/io.h> 4 #include <linux/of.h> 5 #include <linux/of_address.h> 6 #include <linux/reset-controller.h> 7 8 #include "reset.h" 9 10 #define rcdev_to_unit(rcdev) container_of(rcdev, struct mmp_clk_reset_unit, rcdev) 11 12 static int mmp_of_reset_xlate(struct reset_controller_dev *rcdev, 13 const struct of_phandle_args *reset_spec) 14 { 15 struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev); 16 struct mmp_clk_reset_cell *cell; 17 int i; 18 19 if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) 20 return -EINVAL; 21 22 for (i = 0; i < rcdev->nr_resets; i++) { 23 cell = &unit->cells[i]; 24 if (cell->clk_id == reset_spec->args[0]) 25 break; 26 } 27 28 if (i == rcdev->nr_resets) 29 return -EINVAL; 30 31 return i; 32 } 33 34 static int mmp_clk_reset_assert(struct reset_controller_dev *rcdev, 35 unsigned long id) 36 { 37 struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev); 38 struct mmp_clk_reset_cell *cell; 39 unsigned long flags = 0; 40 u32 val; 41 42 cell = &unit->cells[id]; 43 if (cell->lock) 44 spin_lock_irqsave(cell->lock, flags); 45 46 val = readl(cell->reg); 47 val |= cell->bits; 48 writel(val, cell->reg); 49 50 if (cell->lock) 51 spin_unlock_irqrestore(cell->lock, flags); 52 53 return 0; 54 } 55 56 static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev, 57 unsigned long id) 58 { 59 struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev); 60 struct mmp_clk_reset_cell *cell; 61 unsigned long flags = 0; 62 u32 val; 63 64 cell = &unit->cells[id]; 65 if (cell->lock) 66 spin_lock_irqsave(cell->lock, flags); 67 68 val = readl(cell->reg); 69 val &= ~cell->bits; 70 writel(val, cell->reg); 71 72 if (cell->lock) 73 spin_unlock_irqrestore(cell->lock, flags); 74 75 return 0; 76 } 77 78 static const struct reset_control_ops mmp_clk_reset_ops = { 79 .assert = mmp_clk_reset_assert, 80 .deassert = mmp_clk_reset_deassert, 81 }; 82 83 void mmp_clk_reset_register(struct device_node *np, 84 struct mmp_clk_reset_cell *cells, int nr_resets) 85 { 86 struct mmp_clk_reset_unit *unit; 87 88 unit = kzalloc(sizeof(*unit), GFP_KERNEL); 89 if (!unit) 90 return; 91 92 unit->cells = cells; 93 unit->rcdev.of_reset_n_cells = 1; 94 unit->rcdev.nr_resets = nr_resets; 95 unit->rcdev.ops = &mmp_clk_reset_ops; 96 unit->rcdev.of_node = np; 97 unit->rcdev.of_xlate = mmp_of_reset_xlate; 98 99 reset_controller_register(&unit->rcdev); 100 } 101