1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Ingenic XBurst SoCs SYSOST clocks driver 4 * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> 5 */ 6 7 #include <linux/bitops.h> 8 #include <linux/clk.h> 9 #include <linux/clk-provider.h> 10 #include <linux/clockchips.h> 11 #include <linux/clocksource.h> 12 #include <linux/interrupt.h> 13 #include <linux/mfd/syscon.h> 14 #include <linux/of_address.h> 15 #include <linux/of_irq.h> 16 #include <linux/sched_clock.h> 17 #include <linux/slab.h> 18 #include <linux/syscore_ops.h> 19 20 #include <dt-bindings/clock/ingenic,sysost.h> 21 22 /* OST register offsets */ 23 #define OST_REG_OSTCCR 0x00 24 #define OST_REG_OSTCR 0x08 25 #define OST_REG_OSTFR 0x0c 26 #define OST_REG_OSTMR 0x10 27 #define OST_REG_OST1DFR 0x14 28 #define OST_REG_OST1CNT 0x18 29 #define OST_REG_OST2CNTL 0x20 30 #define OST_REG_OSTCNT2HBUF 0x24 31 #define OST_REG_OSTESR 0x34 32 #define OST_REG_OSTECR 0x38 33 34 /* bits within the OSTCCR register */ 35 #define OSTCCR_PRESCALE1_MASK 0x3 36 #define OSTCCR_PRESCALE2_MASK 0xc 37 #define OSTCCR_PRESCALE1_LSB 0 38 #define OSTCCR_PRESCALE2_LSB 2 39 40 /* bits within the OSTCR register */ 41 #define OSTCR_OST1CLR BIT(0) 42 #define OSTCR_OST2CLR BIT(1) 43 44 /* bits within the OSTFR register */ 45 #define OSTFR_FFLAG BIT(0) 46 47 /* bits within the OSTMR register */ 48 #define OSTMR_FMASK BIT(0) 49 50 /* bits within the OSTESR register */ 51 #define OSTESR_OST1ENS BIT(0) 52 #define OSTESR_OST2ENS BIT(1) 53 54 /* bits within the OSTECR register */ 55 #define OSTECR_OST1ENC BIT(0) 56 #define OSTECR_OST2ENC BIT(1) 57 58 struct ingenic_soc_info { 59 unsigned int num_channels; 60 }; 61 62 struct ingenic_ost_clk_info { 63 struct clk_init_data init_data; 64 u8 ostccr_reg; 65 }; 66 67 struct ingenic_ost_clk { 68 struct clk_hw hw; 69 unsigned int idx; 70 struct ingenic_ost *ost; 71 const struct ingenic_ost_clk_info *info; 72 }; 73 74 struct ingenic_ost { 75 void __iomem *base; 76 const struct ingenic_soc_info *soc_info; 77 struct clk *clk, *percpu_timer_clk, *global_timer_clk; 78 struct clock_event_device cevt; 79 struct clocksource cs; 80 char name[20]; 81 82 struct clk_hw_onecell_data *clocks; 83 }; 84 85 static struct ingenic_ost *ingenic_ost; 86 87 static inline struct ingenic_ost_clk *to_ost_clk(struct clk_hw *hw) 88 { 89 return container_of(hw, struct ingenic_ost_clk, hw); 90 } 91 92 static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw *hw, 93 unsigned long parent_rate) 94 { 95 struct ingenic_ost_clk *ost_clk = to_ost_clk(hw); 96 const struct ingenic_ost_clk_info *info = ost_clk->info; 97 unsigned int prescale; 98 99 prescale = readl(ost_clk->ost->base + info->ostccr_reg); 100 101 prescale = (prescale & OSTCCR_PRESCALE1_MASK) >> OSTCCR_PRESCALE1_LSB; 102 103 return parent_rate >> (prescale * 2); 104 } 105 106 static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw *hw, 107 unsigned long parent_rate) 108 { 109 struct ingenic_ost_clk *ost_clk = to_ost_clk(hw); 110 const struct ingenic_ost_clk_info *info = ost_clk->info; 111 unsigned int prescale; 112 113 prescale = readl(ost_clk->ost->base + info->ostccr_reg); 114 115 prescale = (prescale & OSTCCR_PRESCALE2_MASK) >> OSTCCR_PRESCALE2_LSB; 116 117 return parent_rate >> (prescale * 2); 118 } 119 120 static u8 ingenic_ost_get_prescale(unsigned long rate, unsigned long req_rate) 121 { 122 u8 prescale; 123 124 for (prescale = 0; prescale < 2; prescale++) 125 if ((rate >> (prescale * 2)) <= req_rate) 126 return prescale; 127 128 return 2; /* /16 divider */ 129 } 130 131 static long ingenic_ost_round_rate(struct clk_hw *hw, unsigned long req_rate, 132 unsigned long *parent_rate) 133 { 134 unsigned long rate = *parent_rate; 135 u8 prescale; 136 137 if (req_rate > rate) 138 return rate; 139 140 prescale = ingenic_ost_get_prescale(rate, req_rate); 141 142 return rate >> (prescale * 2); 143 } 144 145 static int ingenic_ost_percpu_timer_set_rate(struct clk_hw *hw, unsigned long req_rate, 146 unsigned long parent_rate) 147 { 148 struct ingenic_ost_clk *ost_clk = to_ost_clk(hw); 149 const struct ingenic_ost_clk_info *info = ost_clk->info; 150 u8 prescale = ingenic_ost_get_prescale(parent_rate, req_rate); 151 int val; 152 153 val = readl(ost_clk->ost->base + info->ostccr_reg); 154 val = (val & ~OSTCCR_PRESCALE1_MASK) | (prescale << OSTCCR_PRESCALE1_LSB); 155 writel(val, ost_clk->ost->base + info->ostccr_reg); 156 157 return 0; 158 } 159 160 static int ingenic_ost_global_timer_set_rate(struct clk_hw *hw, unsigned long req_rate, 161 unsigned long parent_rate) 162 { 163 struct ingenic_ost_clk *ost_clk = to_ost_clk(hw); 164 const struct ingenic_ost_clk_info *info = ost_clk->info; 165 u8 prescale = ingenic_ost_get_prescale(parent_rate, req_rate); 166 int val; 167 168 val = readl(ost_clk->ost->base + info->ostccr_reg); 169 val = (val & ~OSTCCR_PRESCALE2_MASK) | (prescale << OSTCCR_PRESCALE2_LSB); 170 writel(val, ost_clk->ost->base + info->ostccr_reg); 171 172 return 0; 173 } 174 175 static const struct clk_ops ingenic_ost_percpu_timer_ops = { 176 .recalc_rate = ingenic_ost_percpu_timer_recalc_rate, 177 .round_rate = ingenic_ost_round_rate, 178 .set_rate = ingenic_ost_percpu_timer_set_rate, 179 }; 180 181 static const struct clk_ops ingenic_ost_global_timer_ops = { 182 .recalc_rate = ingenic_ost_global_timer_recalc_rate, 183 .round_rate = ingenic_ost_round_rate, 184 .set_rate = ingenic_ost_global_timer_set_rate, 185 }; 186 187 static const char * const ingenic_ost_clk_parents[] = { "ext" }; 188 189 static const struct ingenic_ost_clk_info ingenic_ost_clk_info[] = { 190 [OST_CLK_PERCPU_TIMER] = { 191 .init_data = { 192 .name = "percpu timer", 193 .parent_names = ingenic_ost_clk_parents, 194 .num_parents = ARRAY_SIZE(ingenic_ost_clk_parents), 195 .ops = &ingenic_ost_percpu_timer_ops, 196 .flags = CLK_SET_RATE_UNGATE, 197 }, 198 .ostccr_reg = OST_REG_OSTCCR, 199 }, 200 201 [OST_CLK_GLOBAL_TIMER] = { 202 .init_data = { 203 .name = "global timer", 204 .parent_names = ingenic_ost_clk_parents, 205 .num_parents = ARRAY_SIZE(ingenic_ost_clk_parents), 206 .ops = &ingenic_ost_global_timer_ops, 207 .flags = CLK_SET_RATE_UNGATE, 208 }, 209 .ostccr_reg = OST_REG_OSTCCR, 210 }, 211 }; 212 213 static u64 notrace ingenic_ost_global_timer_read_cntl(void) 214 { 215 struct ingenic_ost *ost = ingenic_ost; 216 unsigned int count; 217 218 count = readl(ost->base + OST_REG_OST2CNTL); 219 220 return count; 221 } 222 223 static u64 notrace ingenic_ost_clocksource_read(struct clocksource *cs) 224 { 225 return ingenic_ost_global_timer_read_cntl(); 226 } 227 228 static inline struct ingenic_ost *to_ingenic_ost(struct clock_event_device *evt) 229 { 230 return container_of(evt, struct ingenic_ost, cevt); 231 } 232 233 static int ingenic_ost_cevt_set_state_shutdown(struct clock_event_device *evt) 234 { 235 struct ingenic_ost *ost = to_ingenic_ost(evt); 236 237 writel(OSTECR_OST1ENC, ost->base + OST_REG_OSTECR); 238 239 return 0; 240 } 241 242 static int ingenic_ost_cevt_set_next(unsigned long next, 243 struct clock_event_device *evt) 244 { 245 struct ingenic_ost *ost = to_ingenic_ost(evt); 246 247 writel((u32)~OSTFR_FFLAG, ost->base + OST_REG_OSTFR); 248 writel(next, ost->base + OST_REG_OST1DFR); 249 writel(OSTCR_OST1CLR, ost->base + OST_REG_OSTCR); 250 writel(OSTESR_OST1ENS, ost->base + OST_REG_OSTESR); 251 writel((u32)~OSTMR_FMASK, ost->base + OST_REG_OSTMR); 252 253 return 0; 254 } 255 256 static irqreturn_t ingenic_ost_cevt_cb(int irq, void *dev_id) 257 { 258 struct clock_event_device *evt = dev_id; 259 struct ingenic_ost *ost = to_ingenic_ost(evt); 260 261 writel(OSTECR_OST1ENC, ost->base + OST_REG_OSTECR); 262 263 if (evt->event_handler) 264 evt->event_handler(evt); 265 266 return IRQ_HANDLED; 267 } 268 269 static int __init ingenic_ost_register_clock(struct ingenic_ost *ost, 270 unsigned int idx, const struct ingenic_ost_clk_info *info, 271 struct clk_hw_onecell_data *clocks) 272 { 273 struct ingenic_ost_clk *ost_clk; 274 int val, err; 275 276 ost_clk = kzalloc(sizeof(*ost_clk), GFP_KERNEL); 277 if (!ost_clk) 278 return -ENOMEM; 279 280 ost_clk->hw.init = &info->init_data; 281 ost_clk->idx = idx; 282 ost_clk->info = info; 283 ost_clk->ost = ost; 284 285 /* Reset clock divider */ 286 val = readl(ost->base + info->ostccr_reg); 287 val &= ~(OSTCCR_PRESCALE1_MASK | OSTCCR_PRESCALE2_MASK); 288 writel(val, ost->base + info->ostccr_reg); 289 290 err = clk_hw_register(NULL, &ost_clk->hw); 291 if (err) { 292 kfree(ost_clk); 293 return err; 294 } 295 296 clocks->hws[idx] = &ost_clk->hw; 297 298 return 0; 299 } 300 301 static struct clk * __init ingenic_ost_get_clock(struct device_node *np, int id) 302 { 303 struct of_phandle_args args; 304 305 args.np = np; 306 args.args_count = 1; 307 args.args[0] = id; 308 309 return of_clk_get_from_provider(&args); 310 } 311 312 static int __init ingenic_ost_percpu_timer_init(struct device_node *np, 313 struct ingenic_ost *ost) 314 { 315 unsigned int timer_virq, channel = OST_CLK_PERCPU_TIMER; 316 unsigned long rate; 317 int err; 318 319 ost->percpu_timer_clk = ingenic_ost_get_clock(np, channel); 320 if (IS_ERR(ost->percpu_timer_clk)) 321 return PTR_ERR(ost->percpu_timer_clk); 322 323 err = clk_prepare_enable(ost->percpu_timer_clk); 324 if (err) 325 goto err_clk_put; 326 327 rate = clk_get_rate(ost->percpu_timer_clk); 328 if (!rate) { 329 err = -EINVAL; 330 goto err_clk_disable; 331 } 332 333 timer_virq = of_irq_get(np, 0); 334 if (!timer_virq) { 335 err = -EINVAL; 336 goto err_clk_disable; 337 } 338 339 snprintf(ost->name, sizeof(ost->name), "OST percpu timer"); 340 341 err = request_irq(timer_virq, ingenic_ost_cevt_cb, IRQF_TIMER, 342 ost->name, &ost->cevt); 343 if (err) 344 goto err_irq_dispose_mapping; 345 346 ost->cevt.cpumask = cpumask_of(smp_processor_id()); 347 ost->cevt.features = CLOCK_EVT_FEAT_ONESHOT; 348 ost->cevt.name = ost->name; 349 ost->cevt.rating = 400; 350 ost->cevt.set_state_shutdown = ingenic_ost_cevt_set_state_shutdown; 351 ost->cevt.set_next_event = ingenic_ost_cevt_set_next; 352 353 clockevents_config_and_register(&ost->cevt, rate, 4, 0xffffffff); 354 355 return 0; 356 357 err_irq_dispose_mapping: 358 irq_dispose_mapping(timer_virq); 359 err_clk_disable: 360 clk_disable_unprepare(ost->percpu_timer_clk); 361 err_clk_put: 362 clk_put(ost->percpu_timer_clk); 363 return err; 364 } 365 366 static int __init ingenic_ost_global_timer_init(struct device_node *np, 367 struct ingenic_ost *ost) 368 { 369 unsigned int channel = OST_CLK_GLOBAL_TIMER; 370 struct clocksource *cs = &ost->cs; 371 unsigned long rate; 372 int err; 373 374 ost->global_timer_clk = ingenic_ost_get_clock(np, channel); 375 if (IS_ERR(ost->global_timer_clk)) 376 return PTR_ERR(ost->global_timer_clk); 377 378 err = clk_prepare_enable(ost->global_timer_clk); 379 if (err) 380 goto err_clk_put; 381 382 rate = clk_get_rate(ost->global_timer_clk); 383 if (!rate) { 384 err = -EINVAL; 385 goto err_clk_disable; 386 } 387 388 /* Clear counter CNT registers */ 389 writel(OSTCR_OST2CLR, ost->base + OST_REG_OSTCR); 390 391 /* Enable OST channel */ 392 writel(OSTESR_OST2ENS, ost->base + OST_REG_OSTESR); 393 394 cs->name = "ingenic-ost"; 395 cs->rating = 400; 396 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 397 cs->mask = CLOCKSOURCE_MASK(32); 398 cs->read = ingenic_ost_clocksource_read; 399 400 err = clocksource_register_hz(cs, rate); 401 if (err) 402 goto err_clk_disable; 403 404 return 0; 405 406 err_clk_disable: 407 clk_disable_unprepare(ost->global_timer_clk); 408 err_clk_put: 409 clk_put(ost->global_timer_clk); 410 return err; 411 } 412 413 static const struct ingenic_soc_info x1000_soc_info = { 414 .num_channels = 2, 415 }; 416 417 static const struct of_device_id __maybe_unused ingenic_ost_of_match[] __initconst = { 418 { .compatible = "ingenic,x1000-ost", .data = &x1000_soc_info, }, 419 { /* sentinel */ } 420 }; 421 422 static int __init ingenic_ost_probe(struct device_node *np) 423 { 424 const struct of_device_id *id = of_match_node(ingenic_ost_of_match, np); 425 struct ingenic_ost *ost; 426 unsigned int i; 427 int ret; 428 429 ost = kzalloc(sizeof(*ost), GFP_KERNEL); 430 if (!ost) 431 return -ENOMEM; 432 433 ost->base = of_io_request_and_map(np, 0, of_node_full_name(np)); 434 if (IS_ERR(ost->base)) { 435 pr_err("%s: Failed to map OST registers\n", __func__); 436 ret = PTR_ERR(ost->base); 437 goto err_free_ost; 438 } 439 440 ost->clk = of_clk_get_by_name(np, "ost"); 441 if (IS_ERR(ost->clk)) { 442 ret = PTR_ERR(ost->clk); 443 pr_crit("%s: Cannot get OST clock\n", __func__); 444 goto err_free_ost; 445 } 446 447 ret = clk_prepare_enable(ost->clk); 448 if (ret) { 449 pr_crit("%s: Unable to enable OST clock\n", __func__); 450 goto err_put_clk; 451 } 452 453 ost->soc_info = id->data; 454 455 ost->clocks = kzalloc(struct_size(ost->clocks, hws, ost->soc_info->num_channels), 456 GFP_KERNEL); 457 if (!ost->clocks) { 458 ret = -ENOMEM; 459 goto err_clk_disable; 460 } 461 462 ost->clocks->num = ost->soc_info->num_channels; 463 464 for (i = 0; i < ost->clocks->num; i++) { 465 ret = ingenic_ost_register_clock(ost, i, &ingenic_ost_clk_info[i], ost->clocks); 466 if (ret) { 467 pr_crit("%s: Cannot register clock %d\n", __func__, i); 468 goto err_unregister_ost_clocks; 469 } 470 } 471 472 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, ost->clocks); 473 if (ret) { 474 pr_crit("%s: Cannot add OF clock provider\n", __func__); 475 goto err_unregister_ost_clocks; 476 } 477 478 ingenic_ost = ost; 479 480 return 0; 481 482 err_unregister_ost_clocks: 483 for (i = 0; i < ost->clocks->num; i++) 484 if (ost->clocks->hws[i]) 485 clk_hw_unregister(ost->clocks->hws[i]); 486 kfree(ost->clocks); 487 err_clk_disable: 488 clk_disable_unprepare(ost->clk); 489 err_put_clk: 490 clk_put(ost->clk); 491 err_free_ost: 492 kfree(ost); 493 return ret; 494 } 495 496 static int __init ingenic_ost_init(struct device_node *np) 497 { 498 struct ingenic_ost *ost; 499 unsigned long rate; 500 int ret; 501 502 ret = ingenic_ost_probe(np); 503 if (ret) { 504 pr_crit("%s: Failed to initialize OST clocks: %d\n", __func__, ret); 505 return ret; 506 } 507 508 of_node_clear_flag(np, OF_POPULATED); 509 510 ost = ingenic_ost; 511 if (IS_ERR(ost)) 512 return PTR_ERR(ost); 513 514 ret = ingenic_ost_global_timer_init(np, ost); 515 if (ret) { 516 pr_crit("%s: Unable to init global timer: %x\n", __func__, ret); 517 goto err_free_ingenic_ost; 518 } 519 520 ret = ingenic_ost_percpu_timer_init(np, ost); 521 if (ret) 522 goto err_ost_global_timer_cleanup; 523 524 /* Register the sched_clock at the end as there's no way to undo it */ 525 rate = clk_get_rate(ost->global_timer_clk); 526 sched_clock_register(ingenic_ost_global_timer_read_cntl, 32, rate); 527 528 return 0; 529 530 err_ost_global_timer_cleanup: 531 clocksource_unregister(&ost->cs); 532 clk_disable_unprepare(ost->global_timer_clk); 533 clk_put(ost->global_timer_clk); 534 err_free_ingenic_ost: 535 kfree(ost); 536 return ret; 537 } 538 539 TIMER_OF_DECLARE(x1000_ost, "ingenic,x1000-ost", ingenic_ost_init); 540