1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Microchip LAN966x SoC Clock driver. 4 * 5 * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries 6 * 7 * Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com> 8 */ 9 10 #include <linux/bitfield.h> 11 #include <linux/clk-provider.h> 12 #include <linux/io.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/slab.h> 18 19 #include <dt-bindings/clock/microchip,lan966x.h> 20 21 #define GCK_ENA BIT(0) 22 #define GCK_SRC_SEL GENMASK(9, 8) 23 #define GCK_PRESCALER GENMASK(23, 16) 24 25 #define DIV_MAX 255 26 27 static const char *clk_names[N_CLOCKS] = { 28 "qspi0", "qspi1", "qspi2", "sdmmc0", 29 "pi", "mcan0", "mcan1", "flexcom0", 30 "flexcom1", "flexcom2", "flexcom3", 31 "flexcom4", "timer1", "usb_refclk", 32 }; 33 34 struct lan966x_gck { 35 struct clk_hw hw; 36 void __iomem *reg; 37 }; 38 #define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw) 39 40 static const struct clk_parent_data lan966x_gck_pdata[] = { 41 { .fw_name = "cpu", }, 42 { .fw_name = "ddr", }, 43 { .fw_name = "sys", }, 44 }; 45 46 static struct clk_init_data init = { 47 .parent_data = lan966x_gck_pdata, 48 .num_parents = ARRAY_SIZE(lan966x_gck_pdata), 49 }; 50 51 struct clk_gate_soc_desc { 52 const char *name; 53 int bit_idx; 54 }; 55 56 static const struct clk_gate_soc_desc clk_gate_desc[] = { 57 { "uhphs", 11 }, 58 { "udphs", 10 }, 59 { "mcramc", 9 }, 60 { "hmatrix", 8 }, 61 { } 62 }; 63 64 static DEFINE_SPINLOCK(clk_gate_lock); 65 static void __iomem *base; 66 67 static int lan966x_gck_enable(struct clk_hw *hw) 68 { 69 struct lan966x_gck *gck = to_lan966x_gck(hw); 70 u32 val = readl(gck->reg); 71 72 val |= GCK_ENA; 73 writel(val, gck->reg); 74 75 return 0; 76 } 77 78 static void lan966x_gck_disable(struct clk_hw *hw) 79 { 80 struct lan966x_gck *gck = to_lan966x_gck(hw); 81 u32 val = readl(gck->reg); 82 83 val &= ~GCK_ENA; 84 writel(val, gck->reg); 85 } 86 87 static int lan966x_gck_set_rate(struct clk_hw *hw, 88 unsigned long rate, 89 unsigned long parent_rate) 90 { 91 struct lan966x_gck *gck = to_lan966x_gck(hw); 92 u32 div, val = readl(gck->reg); 93 94 if (rate == 0 || parent_rate == 0) 95 return -EINVAL; 96 97 /* Set Prescalar */ 98 div = parent_rate / rate; 99 val &= ~GCK_PRESCALER; 100 val |= FIELD_PREP(GCK_PRESCALER, (div - 1)); 101 writel(val, gck->reg); 102 103 return 0; 104 } 105 106 static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw, 107 unsigned long parent_rate) 108 { 109 struct lan966x_gck *gck = to_lan966x_gck(hw); 110 u32 div, val = readl(gck->reg); 111 112 div = FIELD_GET(GCK_PRESCALER, val); 113 114 return parent_rate / (div + 1); 115 } 116 117 static int lan966x_gck_determine_rate(struct clk_hw *hw, 118 struct clk_rate_request *req) 119 { 120 struct clk_hw *parent; 121 int i; 122 123 for (i = 0; i < clk_hw_get_num_parents(hw); ++i) { 124 parent = clk_hw_get_parent_by_index(hw, i); 125 if (!parent) 126 continue; 127 128 /* Allowed prescaler divider range is 0-255 */ 129 if (clk_hw_get_rate(parent) / req->rate <= DIV_MAX) { 130 req->best_parent_hw = parent; 131 req->best_parent_rate = clk_hw_get_rate(parent); 132 133 return 0; 134 } 135 } 136 137 return -EINVAL; 138 } 139 140 static u8 lan966x_gck_get_parent(struct clk_hw *hw) 141 { 142 struct lan966x_gck *gck = to_lan966x_gck(hw); 143 u32 val = readl(gck->reg); 144 145 return FIELD_GET(GCK_SRC_SEL, val); 146 } 147 148 static int lan966x_gck_set_parent(struct clk_hw *hw, u8 index) 149 { 150 struct lan966x_gck *gck = to_lan966x_gck(hw); 151 u32 val = readl(gck->reg); 152 153 val &= ~GCK_SRC_SEL; 154 val |= FIELD_PREP(GCK_SRC_SEL, index); 155 writel(val, gck->reg); 156 157 return 0; 158 } 159 160 static const struct clk_ops lan966x_gck_ops = { 161 .enable = lan966x_gck_enable, 162 .disable = lan966x_gck_disable, 163 .set_rate = lan966x_gck_set_rate, 164 .recalc_rate = lan966x_gck_recalc_rate, 165 .determine_rate = lan966x_gck_determine_rate, 166 .set_parent = lan966x_gck_set_parent, 167 .get_parent = lan966x_gck_get_parent, 168 }; 169 170 static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i) 171 { 172 struct lan966x_gck *priv; 173 int ret; 174 175 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 176 if (!priv) 177 return ERR_PTR(-ENOMEM); 178 179 priv->reg = base + (i * 4); 180 priv->hw.init = &init; 181 ret = devm_clk_hw_register(dev, &priv->hw); 182 if (ret) 183 return ERR_PTR(ret); 184 185 return &priv->hw; 186 }; 187 188 static int lan966x_gate_clk_register(struct device *dev, 189 struct clk_hw_onecell_data *hw_data, 190 void __iomem *gate_base) 191 { 192 int i; 193 194 for (i = GCK_GATE_UHPHS; i < N_CLOCKS; ++i) { 195 int idx = i - GCK_GATE_UHPHS; 196 197 hw_data->hws[i] = 198 devm_clk_hw_register_gate(dev, clk_gate_desc[idx].name, 199 "lan966x", 0, gate_base, 200 clk_gate_desc[idx].bit_idx, 201 0, &clk_gate_lock); 202 203 if (IS_ERR(hw_data->hws[i])) 204 return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]), 205 "failed to register %s clock\n", 206 clk_gate_desc[idx].name); 207 } 208 209 return 0; 210 } 211 212 static int lan966x_clk_probe(struct platform_device *pdev) 213 { 214 struct clk_hw_onecell_data *hw_data; 215 struct device *dev = &pdev->dev; 216 void __iomem *gate_base; 217 struct resource *res; 218 int i, ret; 219 220 hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, N_CLOCKS), 221 GFP_KERNEL); 222 if (!hw_data) 223 return -ENOMEM; 224 225 base = devm_platform_ioremap_resource(pdev, 0); 226 if (IS_ERR(base)) 227 return PTR_ERR(base); 228 229 init.ops = &lan966x_gck_ops; 230 231 hw_data->num = GCK_GATE_UHPHS; 232 233 for (i = 0; i < GCK_GATE_UHPHS; i++) { 234 init.name = clk_names[i]; 235 hw_data->hws[i] = lan966x_gck_clk_register(dev, i); 236 if (IS_ERR(hw_data->hws[i])) { 237 dev_err(dev, "failed to register %s clock\n", 238 init.name); 239 return PTR_ERR(hw_data->hws[i]); 240 } 241 } 242 243 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 244 if (res) { 245 gate_base = devm_ioremap_resource(&pdev->dev, res); 246 if (IS_ERR(gate_base)) 247 return PTR_ERR(gate_base); 248 249 hw_data->num = N_CLOCKS; 250 251 ret = lan966x_gate_clk_register(dev, hw_data, gate_base); 252 if (ret) 253 return ret; 254 } 255 256 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data); 257 } 258 259 static const struct of_device_id lan966x_clk_dt_ids[] = { 260 { .compatible = "microchip,lan966x-gck", }, 261 { } 262 }; 263 MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids); 264 265 static struct platform_driver lan966x_clk_driver = { 266 .probe = lan966x_clk_probe, 267 .driver = { 268 .name = "lan966x-clk", 269 .of_match_table = lan966x_clk_dt_ids, 270 }, 271 }; 272 module_platform_driver(lan966x_clk_driver); 273 274 MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>"); 275 MODULE_DESCRIPTION("LAN966X clock driver"); 276 MODULE_LICENSE("GPL v2"); 277