1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * BCM63268 Timer Clock and Reset Controller Driver 4 * 5 * Copyright (C) 2023 Álvaro Fernández Rojas <noltari@gmail.com> 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/container_of.h> 10 #include <linux/delay.h> 11 #include <linux/device.h> 12 #include <linux/io.h> 13 #include <linux/platform_device.h> 14 #include <linux/reset-controller.h> 15 #include <linux/spinlock.h> 16 17 #include <dt-bindings/clock/bcm63268-clock.h> 18 19 #define BCM63268_TIMER_RESET_SLEEP_MIN_US 10000 20 #define BCM63268_TIMER_RESET_SLEEP_MAX_US 20000 21 22 struct bcm63268_tclkrst_hw { 23 void __iomem *regs; 24 spinlock_t lock; 25 26 struct reset_controller_dev rcdev; 27 struct clk_hw_onecell_data data; 28 }; 29 30 struct bcm63268_tclk_table_entry { 31 const char * const name; 32 u8 bit; 33 }; 34 35 static const struct bcm63268_tclk_table_entry bcm63268_timer_clocks[] = { 36 { 37 .name = "ephy1", 38 .bit = BCM63268_TCLK_EPHY1, 39 }, { 40 .name = "ephy2", 41 .bit = BCM63268_TCLK_EPHY2, 42 }, { 43 .name = "ephy3", 44 .bit = BCM63268_TCLK_EPHY3, 45 }, { 46 .name = "gphy1", 47 .bit = BCM63268_TCLK_GPHY1, 48 }, { 49 .name = "dsl", 50 .bit = BCM63268_TCLK_DSL, 51 }, { 52 .name = "wakeon_ephy", 53 .bit = BCM63268_TCLK_WAKEON_EPHY, 54 }, { 55 .name = "wakeon_dsl", 56 .bit = BCM63268_TCLK_WAKEON_DSL, 57 }, { 58 .name = "fap1_pll", 59 .bit = BCM63268_TCLK_FAP1, 60 }, { 61 .name = "fap2_pll", 62 .bit = BCM63268_TCLK_FAP2, 63 }, { 64 .name = "uto_50", 65 .bit = BCM63268_TCLK_UTO_50, 66 }, { 67 .name = "uto_extin", 68 .bit = BCM63268_TCLK_UTO_EXTIN, 69 }, { 70 .name = "usb_ref", 71 .bit = BCM63268_TCLK_USB_REF, 72 }, { 73 /* sentinel */ 74 } 75 }; 76 77 static inline struct bcm63268_tclkrst_hw * 78 to_bcm63268_timer_reset(struct reset_controller_dev *rcdev) 79 { 80 return container_of(rcdev, struct bcm63268_tclkrst_hw, rcdev); 81 } 82 83 static int bcm63268_timer_reset_update(struct reset_controller_dev *rcdev, 84 unsigned long id, bool assert) 85 { 86 struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev); 87 unsigned long flags; 88 uint32_t val; 89 90 spin_lock_irqsave(&reset->lock, flags); 91 val = __raw_readl(reset->regs); 92 if (assert) 93 val &= ~BIT(id); 94 else 95 val |= BIT(id); 96 __raw_writel(val, reset->regs); 97 spin_unlock_irqrestore(&reset->lock, flags); 98 99 return 0; 100 } 101 102 static int bcm63268_timer_reset_assert(struct reset_controller_dev *rcdev, 103 unsigned long id) 104 { 105 return bcm63268_timer_reset_update(rcdev, id, true); 106 } 107 108 static int bcm63268_timer_reset_deassert(struct reset_controller_dev *rcdev, 109 unsigned long id) 110 { 111 return bcm63268_timer_reset_update(rcdev, id, false); 112 } 113 114 static int bcm63268_timer_reset_reset(struct reset_controller_dev *rcdev, 115 unsigned long id) 116 { 117 bcm63268_timer_reset_update(rcdev, id, true); 118 usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US, 119 BCM63268_TIMER_RESET_SLEEP_MAX_US); 120 121 bcm63268_timer_reset_update(rcdev, id, false); 122 /* 123 * Ensure component is taken out reset state by sleeping also after 124 * deasserting the reset. Otherwise, the component may not be ready 125 * for operation. 126 */ 127 usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US, 128 BCM63268_TIMER_RESET_SLEEP_MAX_US); 129 130 return 0; 131 } 132 133 static int bcm63268_timer_reset_status(struct reset_controller_dev *rcdev, 134 unsigned long id) 135 { 136 struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev); 137 138 return !(__raw_readl(reset->regs) & BIT(id)); 139 } 140 141 static const struct reset_control_ops bcm63268_timer_reset_ops = { 142 .assert = bcm63268_timer_reset_assert, 143 .deassert = bcm63268_timer_reset_deassert, 144 .reset = bcm63268_timer_reset_reset, 145 .status = bcm63268_timer_reset_status, 146 }; 147 148 static int bcm63268_tclk_probe(struct platform_device *pdev) 149 { 150 struct device *dev = &pdev->dev; 151 const struct bcm63268_tclk_table_entry *entry; 152 struct bcm63268_tclkrst_hw *hw; 153 struct clk_hw *clk; 154 u8 maxbit = 0; 155 int i, ret; 156 157 for (entry = bcm63268_timer_clocks; entry->name; entry++) 158 maxbit = max(maxbit, entry->bit); 159 maxbit++; 160 161 hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit), 162 GFP_KERNEL); 163 if (!hw) 164 return -ENOMEM; 165 166 platform_set_drvdata(pdev, hw); 167 168 spin_lock_init(&hw->lock); 169 170 hw->data.num = maxbit; 171 for (i = 0; i < maxbit; i++) 172 hw->data.hws[i] = ERR_PTR(-ENODEV); 173 174 hw->regs = devm_platform_ioremap_resource(pdev, 0); 175 if (IS_ERR(hw->regs)) 176 return PTR_ERR(hw->regs); 177 178 for (entry = bcm63268_timer_clocks; entry->name; entry++) { 179 clk = devm_clk_hw_register_gate(dev, entry->name, NULL, 0, 180 hw->regs, entry->bit, 181 CLK_GATE_BIG_ENDIAN, 182 &hw->lock); 183 if (IS_ERR(clk)) 184 return PTR_ERR(clk); 185 186 hw->data.hws[entry->bit] = clk; 187 } 188 189 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, 190 &hw->data); 191 if (ret) 192 return ret; 193 194 hw->rcdev.of_node = dev->of_node; 195 hw->rcdev.ops = &bcm63268_timer_reset_ops; 196 197 ret = devm_reset_controller_register(dev, &hw->rcdev); 198 if (ret) 199 dev_err(dev, "Failed to register reset controller\n"); 200 201 return 0; 202 } 203 204 static const struct of_device_id bcm63268_tclk_dt_ids[] = { 205 { .compatible = "brcm,bcm63268-timer-clocks" }, 206 { /* sentinel */ } 207 }; 208 209 static struct platform_driver bcm63268_tclk = { 210 .probe = bcm63268_tclk_probe, 211 .driver = { 212 .name = "bcm63268-timer-clock", 213 .of_match_table = bcm63268_tclk_dt_ids, 214 }, 215 }; 216 builtin_platform_driver(bcm63268_tclk); 217