crunch.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * arch/arm/kernel/crunch.c
  3. * Cirrus MaverickCrunch context switching and handling
  4. *
  5. * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/config.h>
  13. #include <linux/types.h>
  14. #include <linux/kernel.h>
  15. #include <linux/signal.h>
  16. #include <linux/sched.h>
  17. #include <linux/init.h>
  18. #include <asm/arch/ep93xx-regs.h>
  19. #include <asm/thread_notify.h>
  20. #include <asm/io.h>
  21. struct crunch_state *crunch_owner;
  22. void crunch_task_release(struct thread_info *thread)
  23. {
  24. local_irq_disable();
  25. if (crunch_owner == &thread->crunchstate)
  26. crunch_owner = NULL;
  27. local_irq_enable();
  28. }
  29. static int crunch_enabled(u32 devcfg)
  30. {
  31. return !!(devcfg & EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE);
  32. }
  33. static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
  34. {
  35. struct thread_info *thread = (struct thread_info *)t;
  36. struct crunch_state *crunch_state;
  37. u32 devcfg;
  38. crunch_state = &thread->crunchstate;
  39. switch (cmd) {
  40. case THREAD_NOTIFY_FLUSH:
  41. memset(crunch_state, 0, sizeof(*crunch_state));
  42. /*
  43. * FALLTHROUGH: Ensure we don't try to overwrite our newly
  44. * initialised state information on the first fault.
  45. */
  46. case THREAD_NOTIFY_RELEASE:
  47. crunch_task_release(thread);
  48. break;
  49. case THREAD_NOTIFY_SWITCH:
  50. devcfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG);
  51. if (crunch_enabled(devcfg) || crunch_owner == crunch_state) {
  52. devcfg ^= EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE;
  53. __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
  54. __raw_writel(devcfg, EP93XX_SYSCON_DEVICE_CONFIG);
  55. }
  56. break;
  57. }
  58. return NOTIFY_DONE;
  59. }
  60. static struct notifier_block crunch_notifier_block = {
  61. .notifier_call = crunch_do,
  62. };
  63. static int __init crunch_init(void)
  64. {
  65. thread_register_notifier(&crunch_notifier_block);
  66. return 0;
  67. }
  68. late_initcall(crunch_init);