1 /* 2 * This program is free software; you can redistribute it and/or modify it 3 * under the terms of the GNU General Public License version 2 as published 4 * by the Free Software Foundation. 5 * 6 * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/interrupt.h> 12 #include <linux/timer.h> 13 #include <linux/of_gpio.h> 14 #include <linux/clk.h> 15 16 #include <asm/mach-ralink/ralink_regs.h> 17 18 #define TIMER_REG_TMRSTAT 0x00 19 #define TIMER_REG_TMR0LOAD 0x10 20 #define TIMER_REG_TMR0CTL 0x18 21 22 #define TMRSTAT_TMR0INT BIT(0) 23 24 #define TMR0CTL_ENABLE BIT(7) 25 #define TMR0CTL_MODE_PERIODIC BIT(4) 26 #define TMR0CTL_PRESCALER 1 27 #define TMR0CTL_PRESCALE_VAL (0xf - TMR0CTL_PRESCALER) 28 #define TMR0CTL_PRESCALE_DIV (65536 / BIT(TMR0CTL_PRESCALER)) 29 30 struct rt_timer { 31 struct device *dev; 32 void __iomem *membase; 33 int irq; 34 unsigned long timer_freq; 35 unsigned long timer_div; 36 }; 37 38 static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val) 39 { 40 __raw_writel(val, rt->membase + reg); 41 } 42 43 static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg) 44 { 45 return __raw_readl(rt->membase + reg); 46 } 47 48 static irqreturn_t rt_timer_irq(int irq, void *_rt) 49 { 50 struct rt_timer *rt = (struct rt_timer *) _rt; 51 52 rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); 53 rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT); 54 55 return IRQ_HANDLED; 56 } 57 58 59 static int rt_timer_request(struct rt_timer *rt) 60 { 61 int err = request_irq(rt->irq, rt_timer_irq, 0, 62 dev_name(rt->dev), rt); 63 if (err) { 64 dev_err(rt->dev, "failed to request irq\n"); 65 } else { 66 u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL; 67 rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); 68 } 69 return err; 70 } 71 72 static void rt_timer_free(struct rt_timer *rt) 73 { 74 free_irq(rt->irq, rt); 75 } 76 77 static int rt_timer_config(struct rt_timer *rt, unsigned long divisor) 78 { 79 if (rt->timer_freq < divisor) 80 rt->timer_div = rt->timer_freq; 81 else 82 rt->timer_div = divisor; 83 84 rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); 85 86 return 0; 87 } 88 89 static int rt_timer_enable(struct rt_timer *rt) 90 { 91 u32 t; 92 93 rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); 94 95 t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); 96 t |= TMR0CTL_ENABLE; 97 rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); 98 99 return 0; 100 } 101 102 static void rt_timer_disable(struct rt_timer *rt) 103 { 104 u32 t; 105 106 t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); 107 t &= ~TMR0CTL_ENABLE; 108 rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); 109 } 110 111 static int rt_timer_probe(struct platform_device *pdev) 112 { 113 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 114 struct rt_timer *rt; 115 struct clk *clk; 116 117 rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL); 118 if (!rt) { 119 dev_err(&pdev->dev, "failed to allocate memory\n"); 120 return -ENOMEM; 121 } 122 123 rt->irq = platform_get_irq(pdev, 0); 124 if (!rt->irq) { 125 dev_err(&pdev->dev, "failed to load irq\n"); 126 return -ENOENT; 127 } 128 129 rt->membase = devm_ioremap_resource(&pdev->dev, res); 130 if (IS_ERR(rt->membase)) 131 return PTR_ERR(rt->membase); 132 133 clk = devm_clk_get(&pdev->dev, NULL); 134 if (IS_ERR(clk)) { 135 dev_err(&pdev->dev, "failed get clock rate\n"); 136 return PTR_ERR(clk); 137 } 138 139 rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV; 140 if (!rt->timer_freq) 141 return -EINVAL; 142 143 rt->dev = &pdev->dev; 144 platform_set_drvdata(pdev, rt); 145 146 rt_timer_request(rt); 147 rt_timer_config(rt, 2); 148 rt_timer_enable(rt); 149 150 dev_info(&pdev->dev, "maximum frequency is %luHz\n", rt->timer_freq); 151 152 return 0; 153 } 154 155 static int rt_timer_remove(struct platform_device *pdev) 156 { 157 struct rt_timer *rt = platform_get_drvdata(pdev); 158 159 rt_timer_disable(rt); 160 rt_timer_free(rt); 161 162 return 0; 163 } 164 165 static const struct of_device_id rt_timer_match[] = { 166 { .compatible = "ralink,rt2880-timer" }, 167 {}, 168 }; 169 MODULE_DEVICE_TABLE(of, rt_timer_match); 170 171 static struct platform_driver rt_timer_driver = { 172 .probe = rt_timer_probe, 173 .remove = rt_timer_remove, 174 .driver = { 175 .name = "rt-timer", 176 .of_match_table = rt_timer_match 177 }, 178 }; 179 180 module_platform_driver(rt_timer_driver); 181 182 MODULE_DESCRIPTION("Ralink RT2880 timer"); 183 MODULE_AUTHOR("John Crispin <blogic@openwrt.org"); 184 MODULE_LICENSE("GPL"); 185