s3c2450.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* linux/arch/arm/mach-s3c2450/s3c2450.c
  2. *
  3. * Copyright (c) 2007 Simtec Electronics
  4. * Ben Dooks <ben@simtec.co.uk>
  5. * Ryu Euiyoul <ryu.real@gmail.com>
  6. *
  7. * Samsung S3C2450 Mobile CPU support
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/types.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/list.h>
  17. #include <linux/timer.h>
  18. #include <linux/init.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/serial_core.h>
  21. #include <linux/sysdev.h>
  22. #include <linux/clk.h>
  23. #include <asm/mach/arch.h>
  24. #include <asm/mach/map.h>
  25. #include <asm/mach/irq.h>
  26. #include <asm/hardware.h>
  27. #include <asm/io.h>
  28. #include <asm/irq.h>
  29. #include <asm/proc-fns.h>
  30. #include <asm/arch/idle.h>
  31. #include <asm/arch/regs-s3c2450-clock.h>
  32. #include <asm/arch/reset.h>
  33. #include <asm/plat-s3c24xx/s3c2450.h>
  34. #include <asm/plat-s3c24xx/devs.h>
  35. #include <asm/plat-s3c24xx/cpu.h>
  36. #include <asm/arch/regs-gpio.h>
  37. #undef DVS_IDLE
  38. static struct map_desc s3c2450_iodesc[] __initdata = {
  39. IODESC_ENT(WATCHDOG),
  40. IODESC_ENT(CLKPWR),
  41. IODESC_ENT(TIMER),
  42. IODESC_ENT(LCD),
  43. IODESC_ENT(USBDEV),
  44. IODESC_ENT(CAMIF),
  45. IODESC_ENT(EBI),
  46. IODESC_ENT(SROMC),
  47. };
  48. struct sysdev_class s3c2450_sysclass = {
  49. set_kset_name("s3c2450-core"),
  50. };
  51. static struct sys_device s3c2450_sysdev = {
  52. .cls = &s3c2450_sysclass,
  53. };
  54. static void s3c2450_hard_reset(void)
  55. {
  56. __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
  57. }
  58. int __init s3c2450_init(void)
  59. {
  60. printk("S3C2450: Initialising architecture\n");
  61. s3c24xx_reset_hook = s3c2450_hard_reset;
  62. s3c_device_nand.name = "s3c2412-nand";
  63. // For S3C nand
  64. s3c_device_nand.name = "s3c-nand";
  65. return sysdev_register(&s3c2450_sysdev);
  66. }
  67. #undef IDLE_PROBE
  68. static void s3c2450_idle(void)
  69. {
  70. unsigned long tmp;
  71. /*if you want to reduce CPU clock with idle */
  72. #ifdef DVS_IDLE
  73. tmp = __raw_readl(S3C2443_CLKDIV0);
  74. tmp &= ~(0x1<<13);
  75. tmp |= (0x1<<13);
  76. __raw_writel(tmp, S3C2443_CLKDIV0);
  77. #else
  78. /* ensure our idle mode is to go to idle */
  79. tmp = __raw_readl(S3C2443_PWRMODE);
  80. tmp &= ~(0x1<<17);
  81. tmp |= (0x1<<17);
  82. __raw_writel(tmp, S3C2443_PWRMODE);
  83. #endif
  84. /* in SMDK2450 you can probe the idle status through the TP11(GPB2) by Laputa*/
  85. #ifdef IDLE_PROBE
  86. tmp = __raw_readl(S3C2410_GPBDAT);
  87. tmp |= (0x1<<2);
  88. __raw_writel(tmp, S3C2410_GPBDAT);
  89. tmp &= ~(0x1<<2);
  90. __raw_writel(tmp, S3C2410_GPBDAT);
  91. #endif
  92. cpu_do_idle();
  93. }
  94. void __init s3c2450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
  95. {
  96. s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
  97. /* rename devices that are s3c2413/s3c2443/s3c6400 specific */
  98. #if defined (CONFIG_S3C_SIR)
  99. s3c24xx_uart_src[2]->name = "s3c-irda";
  100. #endif
  101. s3c_device_lcd.name = "s3c-lcd";
  102. }
  103. /* s3c2443_map_io
  104. *
  105. * register the standard cpu IO areas, and any passed in from the
  106. * machine specific initialisation.
  107. */
  108. void __init s3c2450_map_io(struct map_desc *mach_desc, int mach_size)
  109. {
  110. iotable_init(s3c2450_iodesc, ARRAY_SIZE(s3c2450_iodesc));
  111. iotable_init(mach_desc, mach_size);
  112. s3c24xx_idle = s3c2450_idle;
  113. }
  114. /* need to register class before we actually register the device, and
  115. * we also need to ensure that it has been initialised before any of the
  116. * drivers even try to use it (even if not on an s3c2443 based system)
  117. * as a driver which may support both 2443 and 2440 may try and use it.
  118. */
  119. static int __init s3c2450_core_init(void)
  120. {
  121. return sysdev_class_register(&s3c2450_sysclass);
  122. }
  123. core_initcall(s3c2450_core_init);
  124. #define CAMDIV_val 26
  125. int s3c_camif_set_clock (unsigned int camclk)
  126. {
  127. unsigned int camclk_div, val, hclkcon;
  128. struct clk *src_clk = clk_get(NULL, "hclk");
  129. if (camclk == 4800000) {
  130. printk(KERN_INFO "External camera clock is set to 48MHz\n");
  131. }
  132. else if (camclk > 48000000) {
  133. printk(KERN_ERR "Invalid camera clock\n");
  134. }
  135. writel(readl(S3C2443_CLKSRC) | (1 << 20), S3C2443_CLKSRC);
  136. camclk_div = clk_get_rate(src_clk) / camclk;
  137. printk("Parent clock = %ld, CAMDIV = %d\n", clk_get_rate(src_clk), camclk_div);
  138. // CAMIF HCLK Enable
  139. hclkcon = __raw_readl(S3C2443_HCLKCON);
  140. hclkcon |= S3C2443_HCLKCON_CAMIF;
  141. __raw_writel(hclkcon, S3C2443_HCLKCON);
  142. /* CAMCLK Enable */
  143. val = readl(S3C2443_SCLKCON);
  144. val |= S3C2443_SCLKCON_CAMCLK;
  145. writel(val, S3C2443_SCLKCON);
  146. val = readl(S3C2443_CLKDIV1);
  147. val &= ~(0xf<<CAMDIV_val);
  148. writel(val, S3C2443_CLKDIV1);
  149. val |= ((camclk_div -1) << CAMDIV_val);
  150. writel(val, S3C2443_CLKDIV1);
  151. val = readl(S3C2443_CLKDIV1);
  152. return 0;
  153. }
  154. void s3c_camif_disable_clock (void)
  155. {
  156. unsigned int val;
  157. val = readl(S3C2443_SCLKCON);
  158. val &= ~S3C2443_SCLKCON_CAMCLK;
  159. writel(val, S3C2443_SCLKCON);
  160. }