1 /* 2 * Emma Mobile Timer Support - STI 3 * 4 * Copyright (C) 2012 Magnus Damm 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 #include <linux/init.h> 21 #include <linux/platform_device.h> 22 #include <linux/spinlock.h> 23 #include <linux/interrupt.h> 24 #include <linux/ioport.h> 25 #include <linux/io.h> 26 #include <linux/clk.h> 27 #include <linux/irq.h> 28 #include <linux/err.h> 29 #include <linux/delay.h> 30 #include <linux/clocksource.h> 31 #include <linux/clockchips.h> 32 #include <linux/slab.h> 33 #include <linux/module.h> 34 35 enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR }; 36 37 struct em_sti_priv { 38 void __iomem *base; 39 struct clk *clk; 40 struct platform_device *pdev; 41 unsigned int active[USER_NR]; 42 unsigned long rate; 43 raw_spinlock_t lock; 44 struct clock_event_device ced; 45 struct clocksource cs; 46 }; 47 48 #define STI_CONTROL 0x00 49 #define STI_COMPA_H 0x10 50 #define STI_COMPA_L 0x14 51 #define STI_COMPB_H 0x18 52 #define STI_COMPB_L 0x1c 53 #define STI_COUNT_H 0x20 54 #define STI_COUNT_L 0x24 55 #define STI_COUNT_RAW_H 0x28 56 #define STI_COUNT_RAW_L 0x2c 57 #define STI_SET_H 0x30 58 #define STI_SET_L 0x34 59 #define STI_INTSTATUS 0x40 60 #define STI_INTRAWSTATUS 0x44 61 #define STI_INTENSET 0x48 62 #define STI_INTENCLR 0x4c 63 #define STI_INTFFCLR 0x50 64 65 static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs) 66 { 67 return ioread32(p->base + offs); 68 } 69 70 static inline void em_sti_write(struct em_sti_priv *p, int offs, 71 unsigned long value) 72 { 73 iowrite32(value, p->base + offs); 74 } 75 76 static int em_sti_enable(struct em_sti_priv *p) 77 { 78 int ret; 79 80 /* enable clock */ 81 ret = clk_prepare_enable(p->clk); 82 if (ret) { 83 dev_err(&p->pdev->dev, "cannot enable clock\n"); 84 return ret; 85 } 86 87 /* configure channel, periodic mode and maximum timeout */ 88 p->rate = clk_get_rate(p->clk); 89 90 /* reset the counter */ 91 em_sti_write(p, STI_SET_H, 0x40000000); 92 em_sti_write(p, STI_SET_L, 0x00000000); 93 94 /* mask and clear pending interrupts */ 95 em_sti_write(p, STI_INTENCLR, 3); 96 em_sti_write(p, STI_INTFFCLR, 3); 97 98 /* enable updates of counter registers */ 99 em_sti_write(p, STI_CONTROL, 1); 100 101 return 0; 102 } 103 104 static void em_sti_disable(struct em_sti_priv *p) 105 { 106 /* mask interrupts */ 107 em_sti_write(p, STI_INTENCLR, 3); 108 109 /* stop clock */ 110 clk_disable_unprepare(p->clk); 111 } 112 113 static u64 em_sti_count(struct em_sti_priv *p) 114 { 115 u64 ticks; 116 unsigned long flags; 117 118 /* the STI hardware buffers the 48-bit count, but to 119 * break it out into two 32-bit access the registers 120 * must be accessed in a certain order. 121 * Always read STI_COUNT_H before STI_COUNT_L. 122 */ 123 raw_spin_lock_irqsave(&p->lock, flags); 124 ticks = (u64)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32; 125 ticks |= em_sti_read(p, STI_COUNT_L); 126 raw_spin_unlock_irqrestore(&p->lock, flags); 127 128 return ticks; 129 } 130 131 static u64 em_sti_set_next(struct em_sti_priv *p, u64 next) 132 { 133 unsigned long flags; 134 135 raw_spin_lock_irqsave(&p->lock, flags); 136 137 /* mask compare A interrupt */ 138 em_sti_write(p, STI_INTENCLR, 1); 139 140 /* update compare A value */ 141 em_sti_write(p, STI_COMPA_H, next >> 32); 142 em_sti_write(p, STI_COMPA_L, next & 0xffffffff); 143 144 /* clear compare A interrupt source */ 145 em_sti_write(p, STI_INTFFCLR, 1); 146 147 /* unmask compare A interrupt */ 148 em_sti_write(p, STI_INTENSET, 1); 149 150 raw_spin_unlock_irqrestore(&p->lock, flags); 151 152 return next; 153 } 154 155 static irqreturn_t em_sti_interrupt(int irq, void *dev_id) 156 { 157 struct em_sti_priv *p = dev_id; 158 159 p->ced.event_handler(&p->ced); 160 return IRQ_HANDLED; 161 } 162 163 static int em_sti_start(struct em_sti_priv *p, unsigned int user) 164 { 165 unsigned long flags; 166 int used_before; 167 int ret = 0; 168 169 raw_spin_lock_irqsave(&p->lock, flags); 170 used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; 171 if (!used_before) 172 ret = em_sti_enable(p); 173 174 if (!ret) 175 p->active[user] = 1; 176 raw_spin_unlock_irqrestore(&p->lock, flags); 177 178 return ret; 179 } 180 181 static void em_sti_stop(struct em_sti_priv *p, unsigned int user) 182 { 183 unsigned long flags; 184 int used_before, used_after; 185 186 raw_spin_lock_irqsave(&p->lock, flags); 187 used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; 188 p->active[user] = 0; 189 used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; 190 191 if (used_before && !used_after) 192 em_sti_disable(p); 193 raw_spin_unlock_irqrestore(&p->lock, flags); 194 } 195 196 static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs) 197 { 198 return container_of(cs, struct em_sti_priv, cs); 199 } 200 201 static u64 em_sti_clocksource_read(struct clocksource *cs) 202 { 203 return em_sti_count(cs_to_em_sti(cs)); 204 } 205 206 static int em_sti_clocksource_enable(struct clocksource *cs) 207 { 208 int ret; 209 struct em_sti_priv *p = cs_to_em_sti(cs); 210 211 ret = em_sti_start(p, USER_CLOCKSOURCE); 212 if (!ret) 213 __clocksource_update_freq_hz(cs, p->rate); 214 return ret; 215 } 216 217 static void em_sti_clocksource_disable(struct clocksource *cs) 218 { 219 em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE); 220 } 221 222 static void em_sti_clocksource_resume(struct clocksource *cs) 223 { 224 em_sti_clocksource_enable(cs); 225 } 226 227 static int em_sti_register_clocksource(struct em_sti_priv *p) 228 { 229 struct clocksource *cs = &p->cs; 230 231 cs->name = dev_name(&p->pdev->dev); 232 cs->rating = 200; 233 cs->read = em_sti_clocksource_read; 234 cs->enable = em_sti_clocksource_enable; 235 cs->disable = em_sti_clocksource_disable; 236 cs->suspend = em_sti_clocksource_disable; 237 cs->resume = em_sti_clocksource_resume; 238 cs->mask = CLOCKSOURCE_MASK(48); 239 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 240 241 dev_info(&p->pdev->dev, "used as clock source\n"); 242 243 /* Register with dummy 1 Hz value, gets updated in ->enable() */ 244 clocksource_register_hz(cs, 1); 245 return 0; 246 } 247 248 static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) 249 { 250 return container_of(ced, struct em_sti_priv, ced); 251 } 252 253 static int em_sti_clock_event_shutdown(struct clock_event_device *ced) 254 { 255 struct em_sti_priv *p = ced_to_em_sti(ced); 256 em_sti_stop(p, USER_CLOCKEVENT); 257 return 0; 258 } 259 260 static int em_sti_clock_event_set_oneshot(struct clock_event_device *ced) 261 { 262 struct em_sti_priv *p = ced_to_em_sti(ced); 263 264 dev_info(&p->pdev->dev, "used for oneshot clock events\n"); 265 em_sti_start(p, USER_CLOCKEVENT); 266 clockevents_config(&p->ced, p->rate); 267 return 0; 268 } 269 270 static int em_sti_clock_event_next(unsigned long delta, 271 struct clock_event_device *ced) 272 { 273 struct em_sti_priv *p = ced_to_em_sti(ced); 274 u64 next; 275 int safe; 276 277 next = em_sti_set_next(p, em_sti_count(p) + delta); 278 safe = em_sti_count(p) < (next - 1); 279 280 return !safe; 281 } 282 283 static void em_sti_register_clockevent(struct em_sti_priv *p) 284 { 285 struct clock_event_device *ced = &p->ced; 286 287 ced->name = dev_name(&p->pdev->dev); 288 ced->features = CLOCK_EVT_FEAT_ONESHOT; 289 ced->rating = 200; 290 ced->cpumask = cpu_possible_mask; 291 ced->set_next_event = em_sti_clock_event_next; 292 ced->set_state_shutdown = em_sti_clock_event_shutdown; 293 ced->set_state_oneshot = em_sti_clock_event_set_oneshot; 294 295 dev_info(&p->pdev->dev, "used for clock events\n"); 296 297 /* Register with dummy 1 Hz value, gets updated in ->set_state_oneshot() */ 298 clockevents_config_and_register(ced, 1, 2, 0xffffffff); 299 } 300 301 static int em_sti_probe(struct platform_device *pdev) 302 { 303 struct em_sti_priv *p; 304 struct resource *res; 305 int irq; 306 307 p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); 308 if (p == NULL) 309 return -ENOMEM; 310 311 p->pdev = pdev; 312 platform_set_drvdata(pdev, p); 313 314 irq = platform_get_irq(pdev, 0); 315 if (irq < 0) { 316 dev_err(&pdev->dev, "failed to get irq\n"); 317 return -EINVAL; 318 } 319 320 /* map memory, let base point to the STI instance */ 321 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 322 p->base = devm_ioremap_resource(&pdev->dev, res); 323 if (IS_ERR(p->base)) 324 return PTR_ERR(p->base); 325 326 /* get hold of clock */ 327 p->clk = devm_clk_get(&pdev->dev, "sclk"); 328 if (IS_ERR(p->clk)) { 329 dev_err(&pdev->dev, "cannot get clock\n"); 330 return PTR_ERR(p->clk); 331 } 332 333 if (devm_request_irq(&pdev->dev, irq, em_sti_interrupt, 334 IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, 335 dev_name(&pdev->dev), p)) { 336 dev_err(&pdev->dev, "failed to request low IRQ\n"); 337 return -ENOENT; 338 } 339 340 raw_spin_lock_init(&p->lock); 341 em_sti_register_clockevent(p); 342 em_sti_register_clocksource(p); 343 return 0; 344 } 345 346 static int em_sti_remove(struct platform_device *pdev) 347 { 348 return -EBUSY; /* cannot unregister clockevent and clocksource */ 349 } 350 351 static const struct of_device_id em_sti_dt_ids[] = { 352 { .compatible = "renesas,em-sti", }, 353 {}, 354 }; 355 MODULE_DEVICE_TABLE(of, em_sti_dt_ids); 356 357 static struct platform_driver em_sti_device_driver = { 358 .probe = em_sti_probe, 359 .remove = em_sti_remove, 360 .driver = { 361 .name = "em_sti", 362 .of_match_table = em_sti_dt_ids, 363 } 364 }; 365 366 static int __init em_sti_init(void) 367 { 368 return platform_driver_register(&em_sti_device_driver); 369 } 370 371 static void __exit em_sti_exit(void) 372 { 373 platform_driver_unregister(&em_sti_device_driver); 374 } 375 376 subsys_initcall(em_sti_init); 377 module_exit(em_sti_exit); 378 379 MODULE_AUTHOR("Magnus Damm"); 380 MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); 381 MODULE_LICENSE("GPL v2"); 382