0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/clockchips.h>
0012 #include <linux/clocksource.h>
0013 #include <linux/delay.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irq.h>
0016 #include <linux/irqreturn.h>
0017 #include <linux/reset.h>
0018 #include <linux/slab.h>
0019 #include <linux/of.h>
0020 #include <linux/of_address.h>
0021 #include <linux/of_irq.h>
0022
0023 #define TIMER_IRQ_EN_REG 0x00
0024 #define TIMER_IRQ_EN(val) BIT(val)
0025 #define TIMER_IRQ_ST_REG 0x04
0026 #define TIMER_CTL_REG(val) (0x20 * (val) + 0x10)
0027 #define TIMER_CTL_ENABLE BIT(0)
0028 #define TIMER_CTL_RELOAD BIT(1)
0029 #define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4)
0030 #define TIMER_CTL_ONESHOT BIT(7)
0031 #define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14)
0032 #define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18)
0033 #define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c)
0034 #define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20)
0035
0036 #define TIMER_SYNC_TICKS 3
0037
0038 struct sun5i_timer {
0039 void __iomem *base;
0040 struct clk *clk;
0041 struct notifier_block clk_rate_cb;
0042 u32 ticks_per_jiffy;
0043 };
0044
0045 #define to_sun5i_timer(x) \
0046 container_of(x, struct sun5i_timer, clk_rate_cb)
0047
0048 struct sun5i_timer_clksrc {
0049 struct sun5i_timer timer;
0050 struct clocksource clksrc;
0051 };
0052
0053 #define to_sun5i_timer_clksrc(x) \
0054 container_of(x, struct sun5i_timer_clksrc, clksrc)
0055
0056 struct sun5i_timer_clkevt {
0057 struct sun5i_timer timer;
0058 struct clock_event_device clkevt;
0059 };
0060
0061 #define to_sun5i_timer_clkevt(x) \
0062 container_of(x, struct sun5i_timer_clkevt, clkevt)
0063
0064
0065
0066
0067
0068
0069
0070 static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce)
0071 {
0072 u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1));
0073
0074 while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
0075 cpu_relax();
0076 }
0077
0078 static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer)
0079 {
0080 u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
0081 writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer));
0082
0083 sun5i_clkevt_sync(ce);
0084 }
0085
0086 static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay)
0087 {
0088 writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer));
0089 }
0090
0091 static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic)
0092 {
0093 u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
0094
0095 if (periodic)
0096 val &= ~TIMER_CTL_ONESHOT;
0097 else
0098 val |= TIMER_CTL_ONESHOT;
0099
0100 writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
0101 ce->timer.base + TIMER_CTL_REG(timer));
0102 }
0103
0104 static int sun5i_clkevt_shutdown(struct clock_event_device *clkevt)
0105 {
0106 struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
0107
0108 sun5i_clkevt_time_stop(ce, 0);
0109 return 0;
0110 }
0111
0112 static int sun5i_clkevt_set_oneshot(struct clock_event_device *clkevt)
0113 {
0114 struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
0115
0116 sun5i_clkevt_time_stop(ce, 0);
0117 sun5i_clkevt_time_start(ce, 0, false);
0118 return 0;
0119 }
0120
0121 static int sun5i_clkevt_set_periodic(struct clock_event_device *clkevt)
0122 {
0123 struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
0124
0125 sun5i_clkevt_time_stop(ce, 0);
0126 sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
0127 sun5i_clkevt_time_start(ce, 0, true);
0128 return 0;
0129 }
0130
0131 static int sun5i_clkevt_next_event(unsigned long evt,
0132 struct clock_event_device *clkevt)
0133 {
0134 struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
0135
0136 sun5i_clkevt_time_stop(ce, 0);
0137 sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS);
0138 sun5i_clkevt_time_start(ce, 0, false);
0139
0140 return 0;
0141 }
0142
0143 static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
0144 {
0145 struct sun5i_timer_clkevt *ce = dev_id;
0146
0147 writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG);
0148 ce->clkevt.event_handler(&ce->clkevt);
0149
0150 return IRQ_HANDLED;
0151 }
0152
0153 static u64 sun5i_clksrc_read(struct clocksource *clksrc)
0154 {
0155 struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
0156
0157 return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
0158 }
0159
0160 static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
0161 unsigned long event, void *data)
0162 {
0163 struct clk_notifier_data *ndata = data;
0164 struct sun5i_timer *timer = to_sun5i_timer(nb);
0165 struct sun5i_timer_clksrc *cs = container_of(timer, struct sun5i_timer_clksrc, timer);
0166
0167 switch (event) {
0168 case PRE_RATE_CHANGE:
0169 clocksource_unregister(&cs->clksrc);
0170 break;
0171
0172 case POST_RATE_CHANGE:
0173 clocksource_register_hz(&cs->clksrc, ndata->new_rate);
0174 break;
0175
0176 default:
0177 break;
0178 }
0179
0180 return NOTIFY_DONE;
0181 }
0182
0183 static int __init sun5i_setup_clocksource(struct device_node *node,
0184 void __iomem *base,
0185 struct clk *clk, int irq)
0186 {
0187 struct sun5i_timer_clksrc *cs;
0188 unsigned long rate;
0189 int ret;
0190
0191 cs = kzalloc(sizeof(*cs), GFP_KERNEL);
0192 if (!cs)
0193 return -ENOMEM;
0194
0195 ret = clk_prepare_enable(clk);
0196 if (ret) {
0197 pr_err("Couldn't enable parent clock\n");
0198 goto err_free;
0199 }
0200
0201 rate = clk_get_rate(clk);
0202 if (!rate) {
0203 pr_err("Couldn't get parent clock rate\n");
0204 ret = -EINVAL;
0205 goto err_disable_clk;
0206 }
0207
0208 cs->timer.base = base;
0209 cs->timer.clk = clk;
0210 cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc;
0211 cs->timer.clk_rate_cb.next = NULL;
0212
0213 ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb);
0214 if (ret) {
0215 pr_err("Unable to register clock notifier.\n");
0216 goto err_disable_clk;
0217 }
0218
0219 writel(~0, base + TIMER_INTVAL_LO_REG(1));
0220 writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
0221 base + TIMER_CTL_REG(1));
0222
0223 cs->clksrc.name = node->name;
0224 cs->clksrc.rating = 340;
0225 cs->clksrc.read = sun5i_clksrc_read;
0226 cs->clksrc.mask = CLOCKSOURCE_MASK(32);
0227 cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
0228
0229 ret = clocksource_register_hz(&cs->clksrc, rate);
0230 if (ret) {
0231 pr_err("Couldn't register clock source.\n");
0232 goto err_remove_notifier;
0233 }
0234
0235 return 0;
0236
0237 err_remove_notifier:
0238 clk_notifier_unregister(clk, &cs->timer.clk_rate_cb);
0239 err_disable_clk:
0240 clk_disable_unprepare(clk);
0241 err_free:
0242 kfree(cs);
0243 return ret;
0244 }
0245
0246 static int sun5i_rate_cb_clkevt(struct notifier_block *nb,
0247 unsigned long event, void *data)
0248 {
0249 struct clk_notifier_data *ndata = data;
0250 struct sun5i_timer *timer = to_sun5i_timer(nb);
0251 struct sun5i_timer_clkevt *ce = container_of(timer, struct sun5i_timer_clkevt, timer);
0252
0253 if (event == POST_RATE_CHANGE) {
0254 clockevents_update_freq(&ce->clkevt, ndata->new_rate);
0255 ce->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ);
0256 }
0257
0258 return NOTIFY_DONE;
0259 }
0260
0261 static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base,
0262 struct clk *clk, int irq)
0263 {
0264 struct sun5i_timer_clkevt *ce;
0265 unsigned long rate;
0266 int ret;
0267 u32 val;
0268
0269 ce = kzalloc(sizeof(*ce), GFP_KERNEL);
0270 if (!ce)
0271 return -ENOMEM;
0272
0273 ret = clk_prepare_enable(clk);
0274 if (ret) {
0275 pr_err("Couldn't enable parent clock\n");
0276 goto err_free;
0277 }
0278
0279 rate = clk_get_rate(clk);
0280 if (!rate) {
0281 pr_err("Couldn't get parent clock rate\n");
0282 ret = -EINVAL;
0283 goto err_disable_clk;
0284 }
0285
0286 ce->timer.base = base;
0287 ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
0288 ce->timer.clk = clk;
0289 ce->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clkevt;
0290 ce->timer.clk_rate_cb.next = NULL;
0291
0292 ret = clk_notifier_register(clk, &ce->timer.clk_rate_cb);
0293 if (ret) {
0294 pr_err("Unable to register clock notifier.\n");
0295 goto err_disable_clk;
0296 }
0297
0298 ce->clkevt.name = node->name;
0299 ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
0300 ce->clkevt.set_next_event = sun5i_clkevt_next_event;
0301 ce->clkevt.set_state_shutdown = sun5i_clkevt_shutdown;
0302 ce->clkevt.set_state_periodic = sun5i_clkevt_set_periodic;
0303 ce->clkevt.set_state_oneshot = sun5i_clkevt_set_oneshot;
0304 ce->clkevt.tick_resume = sun5i_clkevt_shutdown;
0305 ce->clkevt.rating = 340;
0306 ce->clkevt.irq = irq;
0307 ce->clkevt.cpumask = cpu_possible_mask;
0308
0309
0310 val = readl(base + TIMER_IRQ_EN_REG);
0311 writel(val | TIMER_IRQ_EN(0), base + TIMER_IRQ_EN_REG);
0312
0313 clockevents_config_and_register(&ce->clkevt, rate,
0314 TIMER_SYNC_TICKS, 0xffffffff);
0315
0316 ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
0317 "sun5i_timer0", ce);
0318 if (ret) {
0319 pr_err("Unable to register interrupt\n");
0320 goto err_remove_notifier;
0321 }
0322
0323 return 0;
0324
0325 err_remove_notifier:
0326 clk_notifier_unregister(clk, &ce->timer.clk_rate_cb);
0327 err_disable_clk:
0328 clk_disable_unprepare(clk);
0329 err_free:
0330 kfree(ce);
0331 return ret;
0332 }
0333
0334 static int __init sun5i_timer_init(struct device_node *node)
0335 {
0336 struct reset_control *rstc;
0337 void __iomem *timer_base;
0338 struct clk *clk;
0339 int irq, ret;
0340
0341 timer_base = of_io_request_and_map(node, 0, of_node_full_name(node));
0342 if (IS_ERR(timer_base)) {
0343 pr_err("Can't map registers\n");
0344 return PTR_ERR(timer_base);
0345 }
0346
0347 irq = irq_of_parse_and_map(node, 0);
0348 if (irq <= 0) {
0349 pr_err("Can't parse IRQ\n");
0350 return -EINVAL;
0351 }
0352
0353 clk = of_clk_get(node, 0);
0354 if (IS_ERR(clk)) {
0355 pr_err("Can't get timer clock\n");
0356 return PTR_ERR(clk);
0357 }
0358
0359 rstc = of_reset_control_get(node, NULL);
0360 if (!IS_ERR(rstc))
0361 reset_control_deassert(rstc);
0362
0363 ret = sun5i_setup_clocksource(node, timer_base, clk, irq);
0364 if (ret)
0365 return ret;
0366
0367 return sun5i_setup_clockevent(node, timer_base, clk, irq);
0368 }
0369 TIMER_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
0370 sun5i_timer_init);
0371 TIMER_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
0372 sun5i_timer_init);