Advertisement
Guest User

Untitled

a guest
Mar 9th, 2013
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.54 KB | None | 0 0
  1. /*
  2.  * arch/arm/mach-sun5i/core.c
  3.  *
  4.  * (C) Copyright 2007-2012
  5.  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  6.  * Benn Huang <benn@allwinnertech.com>
  7.  *
  8.  * SUN5I machine core implementations
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License as
  12.  * published by the Free Software Foundation; either version 2 of
  13.  * the License, or (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23.  * MA 02111-1307 USA
  24.  */
  25.  
  26. #include <linux/init.h>
  27. #include <linux/device.h>
  28. #include <linux/dma-mapping.h>
  29. #include <linux/platform_device.h>
  30. #include <linux/device.h>
  31. #include <linux/interrupt.h>
  32. #include <linux/amba/bus.h>
  33. #include <linux/amba/clcd.h>
  34. #include <linux/amba/pl061.h>
  35. #include <linux/amba/mmci.h>
  36. #include <linux/amba/pl022.h>
  37. #include <linux/io.h>
  38. #include <linux/gfp.h>
  39. #include <linux/clockchips.h>
  40. #include <linux/memblock.h>
  41. #include <linux/bootmem.h>
  42. #include <linux/export.h>
  43. #include <linux/clkdev.h>
  44.  
  45.  
  46. #include <linux/ipipe.h>
  47. #include <linux/ipipe_tickdev.h>
  48.  
  49. #include <asm/system.h>
  50. #include <asm/irq.h>
  51. #include <asm/leds.h>
  52. #include <asm/hardware/arm_timer.h>
  53. #include <asm/hardware/icst.h>
  54. #include <asm/hardware/vic.h>
  55. #include <asm/mach-types.h>
  56. #include <asm/setup.h>
  57. #include <asm/delay.h>
  58.  
  59. #include <asm/mach/arch.h>
  60. #include <asm/mach/flash.h>
  61. #include <asm/mach/irq.h>
  62. #include <asm/mach/time.h>
  63. #include <asm/mach/map.h>
  64. #include <mach/memory.h>
  65. #include <mach/system.h>
  66. #include <mach/timex.h>
  67.  
  68. #include <plat/core.h>
  69. #include <plat/sys_config.h>
  70.  
  71. /**
  72.  * Machine Implementations
  73.  *
  74.  */
  75.  
  76. static struct map_desc sw_io_desc[] __initdata = {
  77.     { SW_VA_SRAM_BASE, __phys_to_pfn(SW_PA_SRAM_BASE),  (SZ_128K + SZ_64K), MT_MEMORY_ITCM  },
  78.     { SW_VA_IO_BASE,   __phys_to_pfn(SW_PA_IO_BASE),    (SZ_1M + SZ_2M),    MT_DEVICE    },
  79.     { SW_VA_BROM_BASE, __phys_to_pfn(SW_PA_BROM_BASE),  (SZ_64K),           MT_MEMORY_ITCM  },
  80. };
  81.  
  82. void __init sw_core_map_io(void)
  83. {
  84.     iotable_init(sw_io_desc, ARRAY_SIZE(sw_io_desc));
  85.  
  86.     sunxi_pr_chip_id();
  87. }
  88.  
  89. #ifdef CONFIG_FB_SUNXI_RESERVED_MEM
  90. unsigned long fb_start = (PLAT_PHYS_OFFSET + SZ_512M - SZ_64M - SZ_32M);
  91. unsigned long fb_size = SZ_32M;
  92. EXPORT_SYMBOL(fb_start);
  93. EXPORT_SYMBOL(fb_size);
  94.  
  95. static inline void reserve_fb(void)
  96. {
  97.     memblock_reserve(fb_start, fb_size);
  98.     pr_reserve_info("LCD ", fb_start, fb_size);
  99. }
  100. #else
  101. static inline void reserve_fb(void) {}
  102. #endif
  103.  
  104. #if 0
  105. unsigned long g2d_start = (PLAT_PHYS_OFFSET + SZ_512M - SZ_128M);
  106. unsigned long g2d_size = SZ_1M * 16;
  107. EXPORT_SYMBOL(g2d_start);
  108. EXPORT_SYMBOL(g2d_size);
  109.  
  110. static inline void reserve_g2d(void)
  111. {
  112.     int g2d_used = 0;
  113.     char *script_base = (char *)(PAGE_OFFSET + 0x3000000);
  114.  
  115.     g2d_used = sw_cfg_get_int(script_base, "g2d_para", "g2d_used");
  116.     if (g2d_used > 0) {
  117.         int size = sw_cfg_get_int(script_base, "g2d_para", "g2d_size");
  118.         if (size < 0 || size > SW_G2D_MEM_MAX)
  119.             g2d_size = SW_G2D_MEM_MAX;
  120.         else
  121.             g2d_size = size;
  122.  
  123.         memblock_reserve(g2d_start, g2d_size);
  124.         pr_reserve_info("G2D ", g2d_start, g2d_size);
  125.     }
  126. }
  127. #else
  128. static inline void reserve_g2d(void) {}
  129. #endif
  130.  
  131. #if defined CONFIG_VIDEO_DECODER_SUN5I || defined CONFIG_VIDEO_DECODER_SUN5I_MODULE
  132. unsigned long ve_start = (PLAT_PHYS_OFFSET + SZ_64M);
  133. unsigned long ve_size = (SZ_64M + SZ_16M);
  134. EXPORT_SYMBOL(ve_start);
  135. EXPORT_SYMBOL(ve_size);
  136.  
  137. static inline void reserve_ve(void)
  138. {
  139.     memblock_reserve(ve_start, SZ_64M);
  140.     memblock_reserve(ve_start + SZ_64M, SZ_16M);
  141.     pr_reserve_info("VE  ", ve_start, ve_size);
  142. }
  143. #else
  144. static inline void reserve_ve(void) {}
  145. #endif
  146.  
  147. static inline void reserve_sys(void)
  148. {
  149.     memblock_reserve(SYS_CONFIG_MEMBASE, SYS_CONFIG_MEMSIZE);
  150.     pr_reserve_info("SYS ", SYS_CONFIG_MEMBASE, SYS_CONFIG_MEMSIZE);
  151. }
  152.  
  153. static void __init sw_core_reserve(void)
  154. {
  155.     pr_info("Memory Reserved:\n");
  156.     reserve_sys();
  157.     reserve_fb();
  158.     reserve_g2d();
  159.     reserve_ve();
  160. }
  161.  
  162. void sw_irq_ack(struct irq_data *irqd)
  163. {
  164.     unsigned int irq = irqd->irq;
  165.  
  166.     if (irq < 32){
  167.         writel(readl(SW_INT_ENABLE_REG0) & ~(1<<irq), SW_INT_ENABLE_REG0);
  168.         writel(readl(SW_INT_MASK_REG0) | (1 << irq), SW_INT_MASK_REG0);
  169.         writel(readl(SW_INT_IRQ_PENDING_REG0) | (1<<irq), SW_INT_IRQ_PENDING_REG0);
  170.     } else if(irq < 64){
  171.         irq -= 32;
  172.         writel(readl(SW_INT_ENABLE_REG1) & ~(1<<irq), SW_INT_ENABLE_REG1);
  173.         writel(readl(SW_INT_MASK_REG1) | (1 << irq), SW_INT_MASK_REG1);
  174.         writel(readl(SW_INT_IRQ_PENDING_REG1) | (1<<irq), SW_INT_IRQ_PENDING_REG1);
  175.     } else if(irq < 96){
  176.         irq -= 64;
  177.         writel(readl(SW_INT_ENABLE_REG2) & ~(1<<irq), SW_INT_ENABLE_REG2);
  178.         writel(readl(SW_INT_MASK_REG2) | (1 << irq), SW_INT_MASK_REG2);
  179.         writel(readl(SW_INT_IRQ_PENDING_REG2) | (1<<irq), SW_INT_IRQ_PENDING_REG2);
  180.     }
  181. }
  182.  
  183. /* Mask an IRQ line, which means disabling the IRQ line */
  184. static void sw_irq_mask(struct irq_data *irqd)
  185. {
  186.     unsigned int irq = irqd->irq;
  187.  
  188.     if(irq < 32){
  189.         writel(readl(SW_INT_ENABLE_REG0) & ~(1<<irq), SW_INT_ENABLE_REG0);
  190.         writel(readl(SW_INT_MASK_REG0) | (1 << irq), SW_INT_MASK_REG0);
  191.     } else if(irq < 64){
  192.         irq -= 32;
  193.         writel(readl(SW_INT_ENABLE_REG1) & ~(1<<irq), SW_INT_ENABLE_REG1);
  194.         writel(readl(SW_INT_MASK_REG1) | (1 << irq), SW_INT_MASK_REG1);
  195.     } else if(irq < 96){
  196.         irq -= 64;
  197.         writel(readl(SW_INT_ENABLE_REG2) & ~(1<<irq), SW_INT_ENABLE_REG2);
  198.         writel(readl(SW_INT_MASK_REG2) | (1 << irq), SW_INT_MASK_REG2);
  199.     }
  200. }
  201.  
  202. static void sw_irq_unmask(struct irq_data *irqd)
  203. {
  204.     unsigned int irq = irqd->irq;
  205.  
  206.     if(irq < 32){
  207.         writel(readl(SW_INT_ENABLE_REG0) | (1<<irq), SW_INT_ENABLE_REG0);
  208.         writel(readl(SW_INT_MASK_REG0) & ~(1 << irq), SW_INT_MASK_REG0);
  209.         if(irq == SW_INT_IRQNO_ENMI) /* must clear pending bit when enabled */
  210.             writel((1 << SW_INT_IRQNO_ENMI), SW_INT_IRQ_PENDING_REG0);
  211.     } else if(irq < 64){
  212.         irq -= 32;
  213.         writel(readl(SW_INT_ENABLE_REG1) | (1<<irq), SW_INT_ENABLE_REG1);
  214.         writel(readl(SW_INT_MASK_REG1) & ~(1 << irq), SW_INT_MASK_REG1);
  215.     } else if(irq < 96){
  216.         irq -= 64;
  217.         writel(readl(SW_INT_ENABLE_REG2) | (1<<irq), SW_INT_ENABLE_REG2);
  218.         writel(readl(SW_INT_MASK_REG2) & ~(1 << irq), SW_INT_MASK_REG2);
  219.     }
  220. }
  221.  
  222. static struct irq_chip sw_vic_chip = {
  223.     .name       = "sw_vic",
  224.     .irq_ack    = sw_irq_ack,
  225.     .irq_mask   = sw_irq_mask,
  226.     .irq_unmask = sw_irq_unmask,
  227. };
  228.  
  229. void __init sw_core_init_irq(void)
  230. {
  231.     u32 i = 0;
  232.  
  233.     /* Disable & clear all interrupts */
  234.     writel(0, SW_INT_ENABLE_REG0);
  235.     writel(0, SW_INT_ENABLE_REG1);
  236.     writel(0, SW_INT_ENABLE_REG2);
  237.  
  238.     writel(0xffffffff, SW_INT_MASK_REG0);
  239.     writel(0xffffffff, SW_INT_MASK_REG1);
  240.     writel(0xffffffff, SW_INT_MASK_REG2);
  241.  
  242.     writel(0xffffffff, SW_INT_IRQ_PENDING_REG0);
  243.     writel(0xffffffff, SW_INT_IRQ_PENDING_REG1);
  244.     writel(0xffffffff, SW_INT_IRQ_PENDING_REG2);
  245.     writel(0xffffffff, SW_INT_FIQ_PENDING_REG0);
  246.     writel(0xffffffff, SW_INT_FIQ_PENDING_REG1);
  247.     writel(0xffffffff, SW_INT_FIQ_PENDING_REG2);
  248.  
  249.     /*enable protection mode*/
  250.     writel(0x01, SW_INT_PROTECTION_REG);
  251.     /*config the external interrupt source type*/
  252.     writel(0x00, SW_INT_NMI_CTRL_REG);
  253.  
  254.     for (i = SW_INT_START; i < SW_INT_END; i++) {
  255.         irq_set_chip(i, &sw_vic_chip);
  256.         irq_set_handler(i, handle_level_irq);
  257.         set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
  258.     }
  259. }
  260.  
  261.  
  262.  
  263. /**
  264.  * Global vars definitions
  265.  *
  266.  */
  267. static void sun5i_restart(char mode, const char *cmd)
  268. {
  269.     /* use watch-dog to reset system */
  270.     #define WATCH_DOG_CTRL_REG  (SW_VA_TIMERC_IO_BASE + 0x0094)
  271.     *(volatile unsigned int *)WATCH_DOG_CTRL_REG = 0;
  272.     __delay(100000);
  273.     *(volatile unsigned int *)WATCH_DOG_CTRL_REG |= 2;
  274.     while(1) {
  275.         __delay(100);
  276.         *(volatile unsigned int *)WATCH_DOG_CTRL_REG |= 1;
  277.     }
  278. }
  279.  
  280. static void timer_set_mode(enum clock_event_mode mode, struct clock_event_device *clk)
  281. {
  282.     volatile u32 ctrl;
  283.  
  284.     switch (mode) {
  285.     case CLOCK_EVT_MODE_PERIODIC:
  286.         pr_info("timer2: Periodic Mode\n");
  287.         writel(TMR_INTER_VAL, SW_TIMER2_INTVAL_REG); /* interval (999+1) */
  288.         ctrl = readl(SW_TIMER2_CTL_REG);
  289.         ctrl &= ~(1<<7);    /* Continuous mode */
  290.         ctrl |= 1;  /* Enable this timer */
  291.         break;
  292.  
  293.     case CLOCK_EVT_MODE_ONESHOT:
  294.         pr_info("timer2: Oneshot Mode\n");
  295.         ctrl = readl(SW_TIMER2_CTL_REG);
  296.         ctrl |= (1<<7);     /* Single mode */
  297.         break;
  298.     case CLOCK_EVT_MODE_UNUSED:
  299.     case CLOCK_EVT_MODE_SHUTDOWN:
  300.     default:
  301.         ctrl = readl(SW_TIMER2_CTL_REG);
  302.         ctrl &= ~(1<<0);    /* Disable timer0 */
  303.         break;
  304.     }
  305.  
  306.     writel(ctrl, SW_TIMER2_CTL_REG);
  307. }
  308.  
  309. /* Useless when periodic mode */
  310. static int timer_set_next_event(unsigned long evt, struct clock_event_device *unused)
  311. {
  312.     volatile u32 ctrl;
  313.  
  314.     /* clear any pending before continue */
  315.     ctrl = readl(SW_TIMER2_CTL_REG);
  316.     writel(evt, SW_TIMER2_CNTVAL_REG);
  317.     ctrl |= (1<<1);
  318.     writel(ctrl, SW_TIMER2_CTL_REG);
  319.     writel(ctrl | 0x1, SW_TIMER2_CTL_REG);
  320.  
  321.     return 0;
  322. }
  323.  
  324. #if (0)
  325.     #define IPIPE_DBG(format,args...)  printk("[IPIPE] "format,##args)
  326.     #define IPIPE_ERR(format,args...)  printk("[IPIPE] "format,##args)
  327. #else
  328.     #define IPIPE_DBG(...)
  329.     #define IPIPE_ERR(...)
  330. #endif
  331.  
  332. #ifdef CONFIG_IPIPE
  333.  
  334. /* ***********************************************
  335.    The IPIPE TIMER
  336.    *********************************************** */
  337. void ipipe_ns_delay( u32 ns);
  338.  
  339. /*
  340.  * Reprogram the timer
  341.  */
  342. static int sun5i_set_timer0(unsigned long evt, void *timer)
  343. {
  344. IPIPE_DBG("sun5i_set_timer0()\n");
  345.   volatile u32  val = 0;
  346.   val = readl(SW_TIMER0_CTL_REG);
  347.   if( (val & 0x1) == 1)
  348.     {
  349.       val &= ~(0x1);  /* stop the timer */
  350.       writel(val, SW_TIMER0_CTL_REG);
  351.       ipipe_ns_delay(80); // wait for hardware synchronisation ?
  352.     }
  353.   /* set the timer */
  354.   writel( evt, SW_TIMER0_INTVAL_REG);// no reason to add it
  355.   writel( evt, SW_TIMER0_CNTVAL_REG);
  356.  
  357.   /* start the timer */
  358.   val |=  0x1<<1; // reload!
  359.   writel(val, SW_TIMER0_CTL_REG);
  360.   val |=  0x1 ; // start
  361.   writel(val, SW_TIMER0_CTL_REG);
  362.   return 0;
  363. }
  364.  
  365. /*
  366.  * IRQ handler for the timer.
  367.  */
  368. static void sun5i_ack_timer0(void)
  369. {
  370. IPIPE_DBG("sun5i_ack_timer0()\n");
  371.     writel(1<<0, SW_TIMER_INT_STA_REG);
  372. }
  373.  
  374. static void sun5i_request_timer0(struct ipipe_timer *timer, int steal)
  375. {
  376. IPIPE_DBG("sun5i_request_timer0()\n");
  377.     /* Set timer on  - Enable interrupt. */
  378.     volatile u32  val = 0;
  379.  
  380.     /* set clock source to PLL6/6 */
  381.     val = readl(SW_TIMER0_CTL_REG);
  382.     val &= ~(0x07<<4);
  383.     val &= ~(0x03<<2);
  384.     val |=  (2<<2) ;// PLL6/6 = 100 MHz
  385.     val &= ~(1<<1); // no autoload
  386.     val |= 1<<7; // single mode.
  387.     writel(val, SW_TIMER0_CTL_REG);
  388.  
  389.     __delay( 50 );
  390.     sun5i_ack_timer0();
  391.     /* Enable timer0 interrupt */
  392.     val = readl(SW_TIMER_INT_CTL_REG);
  393.     val |= (1<<0);
  394.     writel(val, SW_TIMER_INT_CTL_REG);
  395. }
  396.  
  397. static void sun5i_release_timer0(struct ipipe_timer *timer)
  398. {
  399. IPIPE_DBG("sun5i_release_timer0()\n");
  400.     volatile u32  val = 0;
  401.     /* Disable timer0 interrupt. */
  402.     val = readl(SW_TIMER_INT_CTL_REG);
  403.     val &= ~(1<<0);
  404.     writel(val, SW_TIMER_INT_CTL_REG);
  405.  
  406. }
  407.  
  408. static struct ipipe_timer sun5i_itimer = {
  409.   .irq = SW_INT_IRQNO_TIMER0 ,
  410.   .request = sun5i_request_timer0,
  411.   .set = sun5i_set_timer0,
  412.   .ack = sun5i_ack_timer0,
  413.   .release = sun5i_release_timer0,
  414.   .name = "sun5i_timer0",
  415.   .rating =  340 ,
  416.   .freq = 300000000 ,
  417.   .min_delay_ticks = 1 ,
  418.   //  .cpumask = ,
  419. };
  420.  
  421. /* ***********************************************
  422.    The IPIPE CLOCK
  423.    *********************************************** */
  424.  
  425. static struct __ipipe_tscinfo tsc_info = {
  426.   .type = IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN ,
  427.   .freq = 300000000 , // 100 MHz
  428.   .counter_vaddr = SW_TIMER1_CNTVAL_REG,
  429.   .u = {
  430.     {
  431.       .counter_paddr = SW_TIMER1_CNTVAL_REG - SW_VA_TIMERC_IO_BASE + SW_PA_TIMERC_IO_BASE ,
  432.       .mask = 0xffffffff,
  433.     },
  434.   },
  435. };
  436.  
  437. void ipipe_ns_delay( u32 ns)
  438. {
  439. IPIPE_DBG("ipipe_ns_delay()\n");
  440.   volatile u32  val ;
  441.   volatile u32  val0 ;
  442.   volatile i;
  443.   val0 = readl( SW_TIMER1_CNTVAL_REG);
  444.   i = ns * 10 ; // correct for a proc abble to do up to 10 loop per nanos ...
  445.   ns = ( ns * ( tsc_info.freq / 1000 ) )/1000000 +1; // now number of cycles
  446.   if( val0 > ns )  
  447.     {
  448.       ns = val0 - ns ;
  449.       for(; i > 0 ; i--)
  450.     {
  451.       val = readl( SW_TIMER1_CNTVAL_REG);
  452.       if(( val <= ns ) || ( val > val0 )) return;
  453.     };
  454.     }
  455.   else {
  456.     ns = ( 0xffffffff - ns ) + val0 ;
  457.       for(; i > 0 ; i--)
  458.     {
  459.       val = readl( SW_TIMER1_CNTVAL_REG);
  460.       if(( val <= ns ) && ( val > val0 )) return;
  461.     };
  462.   }
  463. }
  464.  
  465. void  sun5i_ipipe_tsc_timer1_init( void )
  466. {
  467. IPIPE_DBG("sun5i_ipipe_tsc_timer1_init()\n");
  468.     /* Set timer on  */
  469.     volatile u32  val = 0;
  470.  
  471.     /* set clock source to PLL6/6 */
  472.     val = readl(SW_TIMER1_CTL_REG);
  473.     val &= ~(0x1); // stop timer
  474.     val &= ~(0x07<<4); // clear divisor
  475.     val &= ~(0x03<<2); // clear source
  476.  
  477.     val &= ~(0x1<<7); // continous mode
  478.     val |=  (2<<2) ;  // PLL6/6 = 100 MHz
  479.     val |=  (0<<4) ;  // DIV/0
  480.  
  481.     writel(val, SW_TIMER1_CTL_REG);
  482.  
  483.     /* set value */
  484.     writel( tsc_info.u.mask, SW_TIMER1_INTVAL_REG);
  485.     /* start and auto reload */
  486.     __delay(50); // wait for hardware synchronisation
  487.     val = readl(SW_TIMER1_CTL_REG);
  488.     val |= 1 | (1<<1); 
  489.     writel(val, SW_TIMER1_CTL_REG);
  490.  
  491. }
  492.  
  493. /* ***********************************************
  494.    The IPIPE IRQ
  495.    *********************************************** */
  496.  
  497. /* ***********************************************
  498.    Register IPIPE
  499.    *********************************************** */
  500.  
  501.  
  502.  
  503. void sun5i_ipipe_init( void )
  504. {
  505. IPIPE_DBG("sun5i_ipipe_init()\n");
  506.   ipipe_timer_register(&sun5i_itimer); // register timer
  507.  
  508.   sun5i_ipipe_tsc_timer1_init();
  509.   __ipipe_tsc_register(&tsc_info); // register clock
  510. }
  511. #endif /* CONFIG_IPIPE */
  512.  
  513. static struct clock_event_device timer2_clockevent = {
  514.     .name = "timer2",
  515.     .shift = 32,
  516.     .rating = 300,
  517.     .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  518.     .set_mode = timer_set_mode,
  519.     .set_next_event = timer_set_next_event,
  520. };
  521.  
  522.  
  523. static irqreturn_t sw_timer_interrupt(int irq, void *dev_id)
  524. {
  525.     struct clock_event_device *evt = (struct clock_event_device *)dev_id;
  526.  
  527. #ifdef CONFIG_IPIPE
  528.  __ipipe_tsc_update();
  529. #endif /* CONFIG_IPIPE */
  530.  
  531.     writel((1<<2), SW_TIMER_INT_STA_REG);
  532.  
  533.     /*
  534.      * timer_set_next_event will be called only in ONESHOT mode
  535.      */
  536.     evt->event_handler(evt);
  537.  
  538.     return IRQ_HANDLED;
  539. }
  540.  
  541. static struct irqaction sw_timer_irq = {
  542.     .name = "timer2",
  543.     .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  544.     .handler = sw_timer_interrupt,
  545.     .dev_id = &timer2_clockevent,
  546.     .irq = SW_INT_IRQNO_TIMER2,
  547. };
  548.  
  549.  
  550. static void __init sw_timer_init(void)
  551. {
  552.     int ret;
  553.     volatile u32  val = 0;
  554.  
  555.     writel(TMR_INTER_VAL, SW_TIMER2_INTVAL_REG);
  556.     /* set clock sourch to HOSC, 16 pre-division */
  557.     val = readl(SW_TIMER2_CTL_REG);
  558.     val &= ~(0x07<<4);
  559.     val &= ~(0x03<<2);
  560.     val |= (4<<4) | (1<<2); // 24 MHz DIV/16 = 1.5 MHz
  561.     writel(val, SW_TIMER2_CTL_REG);
  562.     /* set mode to auto reload */
  563.     val = readl(SW_TIMER2_CTL_REG);
  564.     val |= (1<<1);
  565.     writel(val, SW_TIMER2_CTL_REG);
  566.  
  567.     ret = setup_irq(SW_INT_IRQNO_TIMER2, &sw_timer_irq);
  568.     if (ret) {
  569.         pr_warning("failed to setup irq %d\n", SW_INT_IRQNO_TIMER2);
  570.     }
  571.  
  572.     /* Enable time0 interrupt */
  573.     val = readl(SW_TIMER_INT_CTL_REG);
  574.     val |= (1<<2);
  575.     writel(val, SW_TIMER_INT_CTL_REG);
  576.  
  577.     timer2_clockevent.mult = div_sc(SYS_TIMER_CLKSRC/SYS_TIMER_SCAL, NSEC_PER_SEC, timer2_clockevent.shift);
  578.     timer2_clockevent.max_delta_ns = clockevent_delta2ns(0xff, &timer2_clockevent);
  579.     timer2_clockevent.min_delta_ns = clockevent_delta2ns(0x1, &timer2_clockevent);
  580.     timer2_clockevent.cpumask = cpumask_of(0);
  581.     timer2_clockevent.irq = sw_timer_irq.irq;
  582.     clockevents_register_device(&timer2_clockevent);
  583.  
  584. #ifdef CONFIG_IPIPE
  585.     sun5i_ipipe_init();
  586. #endif
  587. }
  588.  
  589. struct sys_timer sw_sys_timer = {
  590.     .init = sw_timer_init,
  591. };
  592.  
  593. extern void __init sw_pdev_init(void);
  594. void __init sw_core_init(void)
  595. {
  596.     sw_pdev_init();
  597. }
  598. enum sw_ic_ver sw_get_ic_ver(void)
  599. {
  600.     volatile u32 val = readl(SW_VA_TIMERC_IO_BASE + 0x13c);
  601.  
  602.     val = (val >> 6) & 0x3;
  603.  
  604.     if (val == 0x3) {
  605.         return MAGIC_VER_B;
  606.     }
  607.  
  608.     return MAGIC_VER_A;
  609. }
  610. EXPORT_SYMBOL(sw_get_ic_ver);
  611.  
  612. MACHINE_START(SUN5I, "sun5i")
  613.     .atag_offset    = 0x100,
  614.     .timer          = &sw_sys_timer,
  615. #ifdef CONFIG_SUNXI_MALI_RESERVED_MEM
  616.     .fixup          = sunxi_mali_core_fixup,
  617. #endif
  618.     .map_io         = sw_core_map_io,
  619.     .init_early     = NULL,
  620.     .init_irq       = sw_core_init_irq,
  621.     .init_machine   = sw_core_init,
  622.     .reserve        = sw_core_reserve,
  623.     .restart    = sun5i_restart,
  624. MACHINE_END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement