Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Ingenic XBurst SoCs SYSOST clocks driver
0004  * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
0005  */
0006 
0007 #include <linux/bitfield.h>
0008 #include <linux/bitops.h>
0009 #include <linux/clk.h>
0010 #include <linux/clk-provider.h>
0011 #include <linux/clockchips.h>
0012 #include <linux/clocksource.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/mfd/syscon.h>
0015 #include <linux/of_address.h>
0016 #include <linux/of_irq.h>
0017 #include <linux/sched_clock.h>
0018 #include <linux/slab.h>
0019 #include <linux/syscore_ops.h>
0020 
0021 #include <dt-bindings/clock/ingenic,sysost.h>
0022 
0023 /* OST register offsets */
0024 #define OST_REG_OSTCCR          0x00
0025 #define OST_REG_OSTCR           0x08
0026 #define OST_REG_OSTFR           0x0c
0027 #define OST_REG_OSTMR           0x10
0028 #define OST_REG_OST1DFR         0x14
0029 #define OST_REG_OST1CNT         0x18
0030 #define OST_REG_OST2CNTL        0x20
0031 #define OST_REG_OSTCNT2HBUF     0x24
0032 #define OST_REG_OSTESR          0x34
0033 #define OST_REG_OSTECR          0x38
0034 
0035 /* bits within the OSTCCR register */
0036 #define OSTCCR_PRESCALE1_MASK   0x3
0037 #define OSTCCR_PRESCALE2_MASK   0xc
0038 
0039 /* bits within the OSTCR register */
0040 #define OSTCR_OST1CLR           BIT(0)
0041 #define OSTCR_OST2CLR           BIT(1)
0042 
0043 /* bits within the OSTFR register */
0044 #define OSTFR_FFLAG             BIT(0)
0045 
0046 /* bits within the OSTMR register */
0047 #define OSTMR_FMASK             BIT(0)
0048 
0049 /* bits within the OSTESR register */
0050 #define OSTESR_OST1ENS          BIT(0)
0051 #define OSTESR_OST2ENS          BIT(1)
0052 
0053 /* bits within the OSTECR register */
0054 #define OSTECR_OST1ENC          BIT(0)
0055 #define OSTECR_OST2ENC          BIT(1)
0056 
0057 struct ingenic_soc_info {
0058     unsigned int num_channels;
0059 };
0060 
0061 struct ingenic_ost_clk_info {
0062     struct clk_init_data init_data;
0063     u8 ostccr_reg;
0064 };
0065 
0066 struct ingenic_ost_clk {
0067     struct clk_hw hw;
0068     unsigned int idx;
0069     struct ingenic_ost *ost;
0070     const struct ingenic_ost_clk_info *info;
0071 };
0072 
0073 struct ingenic_ost {
0074     void __iomem *base;
0075     const struct ingenic_soc_info *soc_info;
0076     struct clk *clk, *percpu_timer_clk, *global_timer_clk;
0077     struct clock_event_device cevt;
0078     struct clocksource cs;
0079     char name[20];
0080 
0081     struct clk_hw_onecell_data *clocks;
0082 };
0083 
0084 static struct ingenic_ost *ingenic_ost;
0085 
0086 static inline struct ingenic_ost_clk *to_ost_clk(struct clk_hw *hw)
0087 {
0088     return container_of(hw, struct ingenic_ost_clk, hw);
0089 }
0090 
0091 static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw *hw,
0092         unsigned long parent_rate)
0093 {
0094     struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
0095     const struct ingenic_ost_clk_info *info = ost_clk->info;
0096     unsigned int prescale;
0097 
0098     prescale = readl(ost_clk->ost->base + info->ostccr_reg);
0099 
0100     prescale = FIELD_GET(OSTCCR_PRESCALE1_MASK, prescale);
0101 
0102     return parent_rate >> (prescale * 2);
0103 }
0104 
0105 static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw *hw,
0106         unsigned long parent_rate)
0107 {
0108     struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
0109     const struct ingenic_ost_clk_info *info = ost_clk->info;
0110     unsigned int prescale;
0111 
0112     prescale = readl(ost_clk->ost->base + info->ostccr_reg);
0113 
0114     prescale = FIELD_GET(OSTCCR_PRESCALE2_MASK, prescale);
0115 
0116     return parent_rate >> (prescale * 2);
0117 }
0118 
0119 static u8 ingenic_ost_get_prescale(unsigned long rate, unsigned long req_rate)
0120 {
0121     u8 prescale;
0122 
0123     for (prescale = 0; prescale < 2; prescale++)
0124         if ((rate >> (prescale * 2)) <= req_rate)
0125             return prescale;
0126 
0127     return 2; /* /16 divider */
0128 }
0129 
0130 static long ingenic_ost_round_rate(struct clk_hw *hw, unsigned long req_rate,
0131         unsigned long *parent_rate)
0132 {
0133     unsigned long rate = *parent_rate;
0134     u8 prescale;
0135 
0136     if (req_rate > rate)
0137         return rate;
0138 
0139     prescale = ingenic_ost_get_prescale(rate, req_rate);
0140 
0141     return rate >> (prescale * 2);
0142 }
0143 
0144 static int ingenic_ost_percpu_timer_set_rate(struct clk_hw *hw, unsigned long req_rate,
0145         unsigned long parent_rate)
0146 {
0147     struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
0148     const struct ingenic_ost_clk_info *info = ost_clk->info;
0149     u8 prescale = ingenic_ost_get_prescale(parent_rate, req_rate);
0150     int val;
0151 
0152     val = readl(ost_clk->ost->base + info->ostccr_reg);
0153     val &= ~OSTCCR_PRESCALE1_MASK;
0154     val |= FIELD_PREP(OSTCCR_PRESCALE1_MASK, prescale);
0155     writel(val, ost_clk->ost->base + info->ostccr_reg);
0156 
0157     return 0;
0158 }
0159 
0160 static int ingenic_ost_global_timer_set_rate(struct clk_hw *hw, unsigned long req_rate,
0161         unsigned long parent_rate)
0162 {
0163     struct ingenic_ost_clk *ost_clk = to_ost_clk(hw);
0164     const struct ingenic_ost_clk_info *info = ost_clk->info;
0165     u8 prescale = ingenic_ost_get_prescale(parent_rate, req_rate);
0166     int val;
0167 
0168     val = readl(ost_clk->ost->base + info->ostccr_reg);
0169     val &= ~OSTCCR_PRESCALE2_MASK;
0170     val |= FIELD_PREP(OSTCCR_PRESCALE2_MASK, prescale);
0171     writel(val, ost_clk->ost->base + info->ostccr_reg);
0172 
0173     return 0;
0174 }
0175 
0176 static const struct clk_ops ingenic_ost_percpu_timer_ops = {
0177     .recalc_rate    = ingenic_ost_percpu_timer_recalc_rate,
0178     .round_rate     = ingenic_ost_round_rate,
0179     .set_rate       = ingenic_ost_percpu_timer_set_rate,
0180 };
0181 
0182 static const struct clk_ops ingenic_ost_global_timer_ops = {
0183     .recalc_rate    = ingenic_ost_global_timer_recalc_rate,
0184     .round_rate     = ingenic_ost_round_rate,
0185     .set_rate       = ingenic_ost_global_timer_set_rate,
0186 };
0187 
0188 static const char * const ingenic_ost_clk_parents[] = { "ext" };
0189 
0190 static const struct ingenic_ost_clk_info x1000_ost_clk_info[] = {
0191     [OST_CLK_PERCPU_TIMER] = {
0192         .init_data = {
0193             .name = "percpu timer",
0194             .parent_names = ingenic_ost_clk_parents,
0195             .num_parents = ARRAY_SIZE(ingenic_ost_clk_parents),
0196             .ops = &ingenic_ost_percpu_timer_ops,
0197             .flags = CLK_SET_RATE_UNGATE,
0198         },
0199         .ostccr_reg = OST_REG_OSTCCR,
0200     },
0201 
0202     [OST_CLK_GLOBAL_TIMER] = {
0203         .init_data = {
0204             .name = "global timer",
0205             .parent_names = ingenic_ost_clk_parents,
0206             .num_parents = ARRAY_SIZE(ingenic_ost_clk_parents),
0207             .ops = &ingenic_ost_global_timer_ops,
0208             .flags = CLK_SET_RATE_UNGATE,
0209         },
0210         .ostccr_reg = OST_REG_OSTCCR,
0211     },
0212 };
0213 
0214 static u64 notrace ingenic_ost_global_timer_read_cntl(void)
0215 {
0216     struct ingenic_ost *ost = ingenic_ost;
0217     unsigned int count;
0218 
0219     count = readl(ost->base + OST_REG_OST2CNTL);
0220 
0221     return count;
0222 }
0223 
0224 static u64 notrace ingenic_ost_clocksource_read(struct clocksource *cs)
0225 {
0226     return ingenic_ost_global_timer_read_cntl();
0227 }
0228 
0229 static inline struct ingenic_ost *to_ingenic_ost(struct clock_event_device *evt)
0230 {
0231     return container_of(evt, struct ingenic_ost, cevt);
0232 }
0233 
0234 static int ingenic_ost_cevt_set_state_shutdown(struct clock_event_device *evt)
0235 {
0236     struct ingenic_ost *ost = to_ingenic_ost(evt);
0237 
0238     writel(OSTECR_OST1ENC, ost->base + OST_REG_OSTECR);
0239 
0240     return 0;
0241 }
0242 
0243 static int ingenic_ost_cevt_set_next(unsigned long next,
0244                      struct clock_event_device *evt)
0245 {
0246     struct ingenic_ost *ost = to_ingenic_ost(evt);
0247 
0248     writel((u32)~OSTFR_FFLAG, ost->base + OST_REG_OSTFR);
0249     writel(next, ost->base + OST_REG_OST1DFR);
0250     writel(OSTCR_OST1CLR, ost->base + OST_REG_OSTCR);
0251     writel(OSTESR_OST1ENS, ost->base + OST_REG_OSTESR);
0252     writel((u32)~OSTMR_FMASK, ost->base + OST_REG_OSTMR);
0253 
0254     return 0;
0255 }
0256 
0257 static irqreturn_t ingenic_ost_cevt_cb(int irq, void *dev_id)
0258 {
0259     struct clock_event_device *evt = dev_id;
0260     struct ingenic_ost *ost = to_ingenic_ost(evt);
0261 
0262     writel(OSTECR_OST1ENC, ost->base + OST_REG_OSTECR);
0263 
0264     if (evt->event_handler)
0265         evt->event_handler(evt);
0266 
0267     return IRQ_HANDLED;
0268 }
0269 
0270 static int __init ingenic_ost_register_clock(struct ingenic_ost *ost,
0271             unsigned int idx, const struct ingenic_ost_clk_info *info,
0272             struct clk_hw_onecell_data *clocks)
0273 {
0274     struct ingenic_ost_clk *ost_clk;
0275     int val, err;
0276 
0277     ost_clk = kzalloc(sizeof(*ost_clk), GFP_KERNEL);
0278     if (!ost_clk)
0279         return -ENOMEM;
0280 
0281     ost_clk->hw.init = &info->init_data;
0282     ost_clk->idx = idx;
0283     ost_clk->info = info;
0284     ost_clk->ost = ost;
0285 
0286     /* Reset clock divider */
0287     val = readl(ost->base + info->ostccr_reg);
0288     val &= ~(OSTCCR_PRESCALE1_MASK | OSTCCR_PRESCALE2_MASK);
0289     writel(val, ost->base + info->ostccr_reg);
0290 
0291     err = clk_hw_register(NULL, &ost_clk->hw);
0292     if (err) {
0293         kfree(ost_clk);
0294         return err;
0295     }
0296 
0297     clocks->hws[idx] = &ost_clk->hw;
0298 
0299     return 0;
0300 }
0301 
0302 static struct clk * __init ingenic_ost_get_clock(struct device_node *np, int id)
0303 {
0304     struct of_phandle_args args;
0305 
0306     args.np = np;
0307     args.args_count = 1;
0308     args.args[0] = id;
0309 
0310     return of_clk_get_from_provider(&args);
0311 }
0312 
0313 static int __init ingenic_ost_percpu_timer_init(struct device_node *np,
0314                      struct ingenic_ost *ost)
0315 {
0316     unsigned int timer_virq, channel = OST_CLK_PERCPU_TIMER;
0317     unsigned long rate;
0318     int err;
0319 
0320     ost->percpu_timer_clk = ingenic_ost_get_clock(np, channel);
0321     if (IS_ERR(ost->percpu_timer_clk))
0322         return PTR_ERR(ost->percpu_timer_clk);
0323 
0324     err = clk_prepare_enable(ost->percpu_timer_clk);
0325     if (err)
0326         goto err_clk_put;
0327 
0328     rate = clk_get_rate(ost->percpu_timer_clk);
0329     if (!rate) {
0330         err = -EINVAL;
0331         goto err_clk_disable;
0332     }
0333 
0334     timer_virq = of_irq_get(np, 0);
0335     if (!timer_virq) {
0336         err = -EINVAL;
0337         goto err_clk_disable;
0338     }
0339 
0340     snprintf(ost->name, sizeof(ost->name), "OST percpu timer");
0341 
0342     err = request_irq(timer_virq, ingenic_ost_cevt_cb, IRQF_TIMER,
0343               ost->name, &ost->cevt);
0344     if (err)
0345         goto err_irq_dispose_mapping;
0346 
0347     ost->cevt.cpumask = cpumask_of(smp_processor_id());
0348     ost->cevt.features = CLOCK_EVT_FEAT_ONESHOT;
0349     ost->cevt.name = ost->name;
0350     ost->cevt.rating = 400;
0351     ost->cevt.set_state_shutdown = ingenic_ost_cevt_set_state_shutdown;
0352     ost->cevt.set_next_event = ingenic_ost_cevt_set_next;
0353 
0354     clockevents_config_and_register(&ost->cevt, rate, 4, 0xffffffff);
0355 
0356     return 0;
0357 
0358 err_irq_dispose_mapping:
0359     irq_dispose_mapping(timer_virq);
0360 err_clk_disable:
0361     clk_disable_unprepare(ost->percpu_timer_clk);
0362 err_clk_put:
0363     clk_put(ost->percpu_timer_clk);
0364     return err;
0365 }
0366 
0367 static int __init ingenic_ost_global_timer_init(struct device_node *np,
0368                            struct ingenic_ost *ost)
0369 {
0370     unsigned int channel = OST_CLK_GLOBAL_TIMER;
0371     struct clocksource *cs = &ost->cs;
0372     unsigned long rate;
0373     int err;
0374 
0375     ost->global_timer_clk = ingenic_ost_get_clock(np, channel);
0376     if (IS_ERR(ost->global_timer_clk))
0377         return PTR_ERR(ost->global_timer_clk);
0378 
0379     err = clk_prepare_enable(ost->global_timer_clk);
0380     if (err)
0381         goto err_clk_put;
0382 
0383     rate = clk_get_rate(ost->global_timer_clk);
0384     if (!rate) {
0385         err = -EINVAL;
0386         goto err_clk_disable;
0387     }
0388 
0389     /* Clear counter CNT registers */
0390     writel(OSTCR_OST2CLR, ost->base + OST_REG_OSTCR);
0391 
0392     /* Enable OST channel */
0393     writel(OSTESR_OST2ENS, ost->base + OST_REG_OSTESR);
0394 
0395     cs->name = "ingenic-ost";
0396     cs->rating = 400;
0397     cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
0398     cs->mask = CLOCKSOURCE_MASK(32);
0399     cs->read = ingenic_ost_clocksource_read;
0400 
0401     err = clocksource_register_hz(cs, rate);
0402     if (err)
0403         goto err_clk_disable;
0404 
0405     return 0;
0406 
0407 err_clk_disable:
0408     clk_disable_unprepare(ost->global_timer_clk);
0409 err_clk_put:
0410     clk_put(ost->global_timer_clk);
0411     return err;
0412 }
0413 
0414 static const struct ingenic_soc_info x1000_soc_info = {
0415     .num_channels = 2,
0416 };
0417 
0418 static const struct of_device_id __maybe_unused ingenic_ost_of_matches[] __initconst = {
0419     { .compatible = "ingenic,x1000-ost", .data = &x1000_soc_info },
0420     { /* sentinel */ }
0421 };
0422 
0423 static int __init ingenic_ost_probe(struct device_node *np)
0424 {
0425     const struct of_device_id *id = of_match_node(ingenic_ost_of_matches, np);
0426     struct ingenic_ost *ost;
0427     unsigned int i;
0428     int ret;
0429 
0430     ost = kzalloc(sizeof(*ost), GFP_KERNEL);
0431     if (!ost)
0432         return -ENOMEM;
0433 
0434     ost->base = of_io_request_and_map(np, 0, of_node_full_name(np));
0435     if (IS_ERR(ost->base)) {
0436         pr_err("%s: Failed to map OST registers\n", __func__);
0437         ret = PTR_ERR(ost->base);
0438         goto err_free_ost;
0439     }
0440 
0441     ost->clk = of_clk_get_by_name(np, "ost");
0442     if (IS_ERR(ost->clk)) {
0443         ret = PTR_ERR(ost->clk);
0444         pr_crit("%s: Cannot get OST clock\n", __func__);
0445         goto err_free_ost;
0446     }
0447 
0448     ret = clk_prepare_enable(ost->clk);
0449     if (ret) {
0450         pr_crit("%s: Unable to enable OST clock\n", __func__);
0451         goto err_put_clk;
0452     }
0453 
0454     ost->soc_info = id->data;
0455 
0456     ost->clocks = kzalloc(struct_size(ost->clocks, hws, ost->soc_info->num_channels),
0457                   GFP_KERNEL);
0458     if (!ost->clocks) {
0459         ret = -ENOMEM;
0460         goto err_clk_disable;
0461     }
0462 
0463     ost->clocks->num = ost->soc_info->num_channels;
0464 
0465     for (i = 0; i < ost->clocks->num; i++) {
0466         ret = ingenic_ost_register_clock(ost, i, &x1000_ost_clk_info[i], ost->clocks);
0467         if (ret) {
0468             pr_crit("%s: Cannot register clock %d\n", __func__, i);
0469             goto err_unregister_ost_clocks;
0470         }
0471     }
0472 
0473     ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, ost->clocks);
0474     if (ret) {
0475         pr_crit("%s: Cannot add OF clock provider\n", __func__);
0476         goto err_unregister_ost_clocks;
0477     }
0478 
0479     ingenic_ost = ost;
0480 
0481     return 0;
0482 
0483 err_unregister_ost_clocks:
0484     for (i = 0; i < ost->clocks->num; i++)
0485         if (ost->clocks->hws[i])
0486             clk_hw_unregister(ost->clocks->hws[i]);
0487     kfree(ost->clocks);
0488 err_clk_disable:
0489     clk_disable_unprepare(ost->clk);
0490 err_put_clk:
0491     clk_put(ost->clk);
0492 err_free_ost:
0493     kfree(ost);
0494     return ret;
0495 }
0496 
0497 static int __init ingenic_ost_init(struct device_node *np)
0498 {
0499     struct ingenic_ost *ost;
0500     unsigned long rate;
0501     int ret;
0502 
0503     ret = ingenic_ost_probe(np);
0504     if (ret) {
0505         pr_crit("%s: Failed to initialize OST clocks: %d\n", __func__, ret);
0506         return ret;
0507     }
0508 
0509     of_node_clear_flag(np, OF_POPULATED);
0510 
0511     ost = ingenic_ost;
0512     if (IS_ERR(ost))
0513         return PTR_ERR(ost);
0514 
0515     ret = ingenic_ost_global_timer_init(np, ost);
0516     if (ret) {
0517         pr_crit("%s: Unable to init global timer: %x\n", __func__, ret);
0518         goto err_free_ingenic_ost;
0519     }
0520 
0521     ret = ingenic_ost_percpu_timer_init(np, ost);
0522     if (ret)
0523         goto err_ost_global_timer_cleanup;
0524 
0525     /* Register the sched_clock at the end as there's no way to undo it */
0526     rate = clk_get_rate(ost->global_timer_clk);
0527     sched_clock_register(ingenic_ost_global_timer_read_cntl, 32, rate);
0528 
0529     return 0;
0530 
0531 err_ost_global_timer_cleanup:
0532     clocksource_unregister(&ost->cs);
0533     clk_disable_unprepare(ost->global_timer_clk);
0534     clk_put(ost->global_timer_clk);
0535 err_free_ingenic_ost:
0536     kfree(ost);
0537     return ret;
0538 }
0539 
0540 TIMER_OF_DECLARE(x1000_ost,  "ingenic,x1000-ost",  ingenic_ost_init);