Guest
Public paste!

Woz

By: a guest | Sep 7th, 2010 | Syntax: None | Size: 27.70 KB | Hits: 49 | Expires: Never
Copy text to clipboard
  1. /* arch/arm/mach-msm/clock.c
  2.  *
  3.  * Copyright (C) 2007 Google, Inc.
  4.  * Copyright (c) 2007 QUALCOMM Incorporated
  5.  *
  6.  * This software is licensed under the terms of the GNU General Public
  7.  * License version 2, as published by the Free Software Foundation, and
  8.  * may be copied, distributed, and modified under those terms.
  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.  */
  16.  
  17. #include <linux/version.h>
  18. #include <linux/kernel.h>
  19. #include <linux/init.h>
  20. #include <linux/module.h>
  21. #include <linux/list.h>
  22. #include <linux/err.h>
  23. #include <linux/clk.h>
  24. #include <linux/delay.h>
  25. #include <linux/spinlock.h>
  26. #include <mach/msm_rpcrouter.h>
  27.  
  28. #include <mach/msm_iomap.h>
  29. #include <mach/amss_para.h>
  30. #include <asm/io.h>
  31.  
  32. #include "clock.h"
  33. #include "proc_comm.h"
  34.  
  35. static DEFINE_MUTEX(clocks_mutex);
  36. static DEFINE_SPINLOCK(clocks_lock);
  37. static LIST_HEAD(clocks);
  38.  
  39. enum {
  40.         DEBUG_UNKNOWN_ID        = 1<<0,
  41.         DEBUG_UNKNOWN_FREQ      = 1<<1,
  42.         DEBUG_MDNS              = 1<<2,
  43.         DEBUG_UNKNOWN_CMD       = 1<<3,
  44. };
  45. static int debug_mask=0;
  46. module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
  47.  
  48. #if 1
  49. #define D(x...) printk(KERN_DEBUG "clock-wince: " x)
  50. #else
  51. #define D(x...) do {} while (0)
  52. #endif
  53.  
  54. struct mdns_clock_params
  55. {
  56.         unsigned long freq;
  57.         uint32_t calc_freq;
  58.         uint32_t md;
  59.         uint32_t ns;
  60.         uint32_t pll_freq;
  61.         uint32_t clk_id;
  62. };
  63.  
  64. struct msm_clock_params
  65. {
  66.         unsigned clk_id;
  67.         unsigned idx;
  68.         unsigned offset;  // Offset points to .ns register
  69.         unsigned ns_only; // value to fill in ns register, rather than using mdns_clock_params look-up table
  70.         char    *name;
  71. };
  72.  
  73. static int max_clk_rate[NR_CLKS], min_clk_rate[NR_CLKS];
  74.  
  75. #define PLLn_BASE(n)            (MSM_CLK_CTL_BASE + 0x300 + 28 * (n))
  76. #define TCX0                    19200000 // Hz
  77. #define PLL_FREQ(l, m, n)       (TCX0 * (l) + TCX0 * (m) / (n))
  78.  
  79. void clock_poop() {
  80.         int i=0;
  81.         do {
  82.                 D("%8.8x | %8.8x %8.8x %8.8x %8.8x\n",MSM_CLK_CTL_PHYS+i, \
  83.                 readl(MSM_CLK_CTL_BASE+i),readl(MSM_CLK_CTL_BASE+(i+0x04)), \
  84.                 readl(MSM_CLK_CTL_BASE+(i+0x08)),readl(MSM_CLK_CTL_BASE+(i+0x0C)));
  85.                 i=i+16;
  86.         } while(i<1024);
  87. }
  88.  
  89.  
  90. unsigned int get_amss_s_version(void)
  91. {
  92.         char amss_ver[20];
  93.         char amss_dump[20];
  94.         char *dot1, *dot2;
  95.         int len = 0;
  96.  
  97.         /* Detection doesn't work on 'old' CDMA, there's no
  98.          * version string to be found anywhere in SHARED_RAM_BASE
  99.          
  100.         if (machine_is_htcdiamond_cdma() || machine_is_htcraphael_cdma() || machine_is_htcraphael_cdma500())
  101.                 return 6150;
  102.         */
  103.  
  104.         // Dump AMMS version
  105.         *(unsigned int *) (amss_dump + 0x0) = readl(MSM_SHARED_RAM_BASE + 0xfc030 + 0x0);
  106.         *(unsigned int *) (amss_dump + 0x4) = readl(MSM_SHARED_RAM_BASE + 0xfc030 + 0x4);
  107.         *(unsigned int *) (amss_dump + 0x8) = readl(MSM_SHARED_RAM_BASE + 0xfc030 + 0x8);
  108.         *(unsigned int *) (amss_dump + 0xc) = readl(MSM_SHARED_RAM_BASE + 0xfc030 + 0xc);
  109.         *(unsigned int *) (amss_dump + 0x10) = readl(MSM_SHARED_RAM_BASE + 0xfc030 + 0x10);
  110.         amss_dump[19] = '\0';
  111.  
  112.         dot1 = strchr(amss_dump, '.');
  113.         if(dot1 == NULL) {      // CDMA
  114.                 dot1 = strchr(amss_dump, '-');
  115.                 if(dot1 == NULL)
  116.                         return 0;
  117.                 strncpy(amss_ver, dot1+1, 4);
  118.                 amss_ver[4] = '\0';
  119.                 return  simple_strtoul(amss_ver, NULL, 10);
  120.         }
  121.         else { // GSM
  122.                 len = (dot1-amss_dump);
  123.                 strncpy(amss_ver, amss_dump, len);
  124.                 dot1 = strchr(dot1+1, '.');
  125.                 if(dot1 == NULL)
  126.                         return 0;
  127.                 dot2 = strchr(dot1+1, '.');
  128.                 if(dot2 == NULL)
  129.                         return 0;
  130.                 strncpy(amss_ver+len, dot1+1, (dot2-dot1)-1);
  131.                 len+= (int)(dot2-dot1)-1;
  132.                 amss_ver[len] = '\0';
  133.                 return  simple_strtoul(amss_ver, NULL, 10);
  134.         }
  135. }
  136.  
  137.  
  138. static unsigned int pll_get_rate(int n)
  139. {
  140.         unsigned int mode, L, M, N, freq;
  141.  
  142.  if (n == -1) return TCX0;
  143.  if (n > 3)
  144.   return 0;
  145.  else
  146.  {
  147.         mode = readl(PLLn_BASE(n) + 0x0);
  148.         L = readl(PLLn_BASE(n) + 0x4);
  149.         M = readl(PLLn_BASE(n) + 0x8);
  150.         N = readl(PLLn_BASE(n) + 0xc);
  151.         freq = PLL_FREQ(L, M, N);
  152.         printk(KERN_INFO "PLL%d: MODE=%08x L=%08x M=%08x N=%08x freq=%u Hz (%u MHz)\n",
  153.                 n, mode, L, M, N, freq, freq / 1000000); \
  154.  }
  155.  
  156.  return freq;
  157. }
  158.  
  159. static unsigned int idx2pll(uint32_t idx)
  160. {
  161.  int ret;
  162.  
  163.  switch(idx)
  164.  {
  165.   case 0: /* TCX0 */
  166.    ret=-1;
  167.   break;
  168.   case 1: /* PLL1 */
  169.    ret=1;
  170.   break;
  171.   case 4: /* PLL0 */
  172.    ret=0;
  173.   break;
  174.   default:
  175.    ret=4; /* invalid */
  176.  }
  177.  
  178.  return ret;
  179. }
  180.  
  181. static struct msm_clock_params msm_clock_parameters_def[] = {
  182.         // Full ena/md/ns clock
  183.         { .clk_id = SDC1_CLK,           .idx =  7,      .offset =       0xa4,   .name=  "SDC1_CLK",},
  184.         { .clk_id = SDC2_CLK,           .idx =  8,      .offset =       0xac,   .name=  "SDC2_CLK",},
  185.         { .clk_id = SDC3_CLK,           .idx = 27,      .offset =       0xb4,   .name=  "SDC3_CLK",},
  186.         { .clk_id = SDC4_CLK,           .idx = 28,      .offset =       0xbc,   .name=  "SDC4_CLK",},
  187.         { .clk_id = UART1DM_CLK,        .idx = 17,      .offset =       0xd4,   .name=  "UART1DM_CLK",},
  188.         { .clk_id = UART2DM_CLK,        .idx = 26,      .offset =       0xdc,   .name=  "UART2DM_CLK",},
  189.  
  190.         { .clk_id = USB_HS_CLK,         .idx = 25,.offset=0x2c0,.ns_only =0xb00,.name=  "USB_HS_CLK",},
  191.         { .clk_id = GRP_CLK,            .idx = 3,                               .name=  "GRP_CLK", },
  192.         { .clk_id = IMEM_CLK,           .idx =  3,                              .name=  "IMEM_CLK", },
  193.  
  194.  
  195.         // MD/NS only; offset = Ns reg
  196.         { .clk_id = VFE_CLK,            .offset = 0x44,                         .name=  "VFE_CLK", },
  197.  
  198.         // Enable bit only; bit = 1U << idx
  199.         { .clk_id = MDP_CLK,            .idx = 9,                               .name=  "MDP_CLK",},
  200.  
  201.         // NS-reg only; offset = Ns reg, ns_only = Ns value
  202.         { .clk_id = GP_CLK,                     .offset = 0x5c, .ns_only = 0xa06,.name= "GP_CLK" },
  203. /*#if defined(CONFIG_MACH_HTCBLACKSTONE) || defined(CONFIG_MACH_HTCKOVSKY)
  204.         { .clk_id = PMDH_CLK,           .offset = 0x8c,.ns_only = 0xa19,        .name=  "PMDH_CLK"},
  205. #else*/
  206.         { .clk_id = PMDH_CLK,           .offset = 0x8c, .ns_only = 0xa0c,       .name=  "PMDH_CLK"},
  207. //#endif
  208.  
  209.         { .clk_id = I2C_CLK,            .offset = 0x68, .ns_only = 0xa00,       .name=  "I2C_CLK"},
  210. //      { .clk_id = UART1_CLK,          .offset = 0xe0, .ns_only = 0xa00,       .name=  "UART1_CLK"},
  211. };
  212.  
  213. /*
  214. static struct msm_clock_params msm_clock_parameters_6125[] = {
  215.         // Full ena/md/ns clock
  216.         { .clk_id = SDC1_CLK,           .idx =  7, .offset = 0xa4,                              .name="SDC1_CLK",},
  217.         { .clk_id = SDC2_CLK,           .idx =  8, .offset = 0xac,      .ns_only = 0xB44,       .name="SDC2_CLK",},
  218.         { .clk_id = SDC3_CLK,           .idx = 27, .offset = 0xb4,      .ns_only = 0x5C,        .name="SDC3_CLK",},
  219.         { .clk_id = SDC4_CLK,           .idx = 28, .offset = 0xbc,      .ns_only = 0x5C,        .name="SDC4_CLK",},
  220.  
  221.         { .clk_id = UART1DM_CLK,        .idx = 17, .offset = 0xd4,                              .name="UART1DM_CLK",},
  222.         { .clk_id = UART2DM_CLK,        .idx = 26, .offset = 0xdc,                              .name="UART2DM_CLK",},
  223.  
  224.         { .clk_id = USB_HS_CLK,         .idx = 25, .offset = 0x2c0,     .ns_only = 0xb59,       .name="USB_HS_CLK",},
  225.         { .clk_id = USB_HS_PCLK,        .idx = 25, .offset = 0xE8,      .ns_only = 0xfa,        .name="USB_HS_PCLK",},
  226.        
  227.  
  228.         // these both enable the GRP and IMEM clocks.
  229.         { .clk_id = GRP_CLK,            .idx = 3,  .offset = 0x84,      .ns_only = 0xa80,       .name="GRP_CLK", },
  230.         { .clk_id = IMEM_CLK,           .idx = 3,  .offset = 0x84,      .ns_only = 0xa80,       .name="IMEM_CLK", },
  231.  
  232.         // MD/NS only; offset = Ns reg
  233.         { .clk_id = VFE_CLK,                       .offset = 0x44,      .ns_only = (1<<9),      .name="VFE_CLK", },
  234.         { .clk_id = VFE_MDC_CLK,                   .offset = 0x44,      .ns_only = (1<<11),     .name="VFE_MDC_CLK", },
  235.  
  236.         // Enable bit only; bit = 1U << idx
  237.         { .clk_id = MDP_CLK,            .idx = 9,                                               .name="MDP_CLK",},
  238.        
  239.         // NS-reg only; offset = Ns reg, ns_only = Ns value
  240.         { .clk_id = GP_CLK,                        .offset = 0x5c,      .ns_only = 0x000,       .name="GP_CLK" },
  241.         { .clk_id = PMDH_CLK,                      .offset = 0x8c,      .ns_only = 0xa21,       .name="PMDH_CLK"},
  242.         { .clk_id = I2C_CLK,                       .offset = 0x68,      .ns_only = 0xa00,       .name="I2C_CLK"},
  243.  
  244.         // experimental
  245.         { .clk_id = EMDH_CLK,                      .offset = 0x50,      .ns_only = 0x814,       .name="EMDH_CLK"},
  246.         { .clk_id = SDAC_CLK,                      .offset = 0x9C,      .ns_only = 0x040,       .name="SDAC_CLK"},
  247.         { .clk_id = VDC_CLK,                       .offset = 0xF0,      .ns_only = 0x01C,       .name="VDC_CLK"},
  248. //      { .clk_id = SDC1_PCLK,          .idx =  7,      .name="SDC1_PCLK",},
  249. //      { .clk_id = SDC2_PCLK,          .idx =  8,      .name="SDC2_PCLK",},
  250. //      { .clk_id = SDC3_PCLK,          .idx = 27,      .name="SDC3_PCLK",},
  251. //      { .clk_id = SDC4_PCLK,          .idx = 28,      .name="SDC4_PCLK",},   
  252. };
  253. */
  254.  
  255. //orig clocks
  256. static struct msm_clock_params msm_clock_parameters_6125[] = {
  257.         // Full ena/md/ns clock
  258.         { .clk_id = SDC1_CLK,           .idx =  7,      .offset = 0xa4, .name="SDC1_CLK",},
  259.         { .clk_id = SDC2_CLK,           .idx =  8,      .offset = 0xac, .name="SDC2_CLK",},
  260.         { .clk_id = SDC3_CLK,           .idx = 27,      .offset = 0xb4, .name="SDC3_CLK",},
  261.         { .clk_id = SDC4_CLK,           .idx = 28,      .offset = 0xbc, .name="SDC4_CLK",},
  262.         { .clk_id = UART1DM_CLK,        .idx = 17,      .offset = 0xd4, .name="UART1DM_CLK",},
  263.         { .clk_id = UART2DM_CLK,        .idx = 26,      .offset = 0xdc, .name="UART2DM_CLK",},
  264.  
  265.         { .clk_id = USB_HS_CLK,         .idx = 25,.offset = 0x2c0,.ns_only = 0xb59,.name="USB_HS_CLK",},
  266.         { .clk_id = GRP_CLK,            .idx = 3,                       .name="GRP_CLK", },
  267.         { .clk_id = IMEM_CLK,           .idx = 3,                       .name="IMEM_CLK", },
  268.  
  269.  
  270.         // MD/NS only; offset = Ns reg
  271.         { .clk_id = VFE_CLK,                            .offset = 0x44, .name="VFE_CLK", },
  272.  
  273.         // Enable bit only; bit = 1U << idx
  274.         { .clk_id = MDP_CLK,            .idx = 9,                       .name="MDP_CLK",},
  275.  
  276.  
  277.         // NS-reg only; offset = Ns reg, ns_only = Ns value
  278.         { .clk_id = GP_CLK,             .offset = 0x5c, .ns_only = 0xa06,.name="GP_CLK" },
  279. //#if defined(CONFIG_MACH_HTCBLACKSTONE) || defined(CONFIG_MACH_HTCKOVSKY)
  280. //      { .clk_id = PMDH_CLK,           .offset = 0x8c, .ns_only = 0xa19,.name="PMDH_CLK"},
  281. //#else
  282.         { .clk_id = PMDH_CLK,           .offset = 0x8c, .ns_only = 0xa21,.name="PMDH_CLK"},
  283. //#endif
  284.  
  285.         { .clk_id = I2C_CLK,            .offset = 0x68, .ns_only = 0xa00,.name="I2C_CLK"},
  286. //      { .clk_id = UART1_CLK,          .offset = 0xe0, .ns_only = 0xa00,.name="UART1_CLK"},
  287. };
  288.  
  289.  
  290. static struct msm_clock_params* msm_clock_parameters;
  291.  
  292.  
  293. void fix_mddi_clk_black(void) {
  294.                 int i;
  295.                 for (i = 0; i < ARRAY_SIZE(msm_clock_parameters_def); i++)
  296.                                 if (msm_clock_parameters_def[i].clk_id == PMDH_CLK) {
  297.                                         msm_clock_parameters_def[i].ns_only=0xa19;
  298.                                         break;
  299.                 }
  300. }
  301.  
  302. // This formula is used to generate md and ns reg values
  303. #define MSM_CLOCK_REG(frequency,M,N,D,PRE,a5,SRC,MNE,pll_frequency) { \
  304.         .freq = (frequency), \
  305.         .md = ((0xffff & (M)) << 16) | (0xffff & ~((D) << 1)), \
  306.         .ns = ((0xffff & ~((N) - (M))) << 16) \
  307.             | ((0xff & (0xa | (MNE))) << 8) \
  308.             | ((0x7 & (a5)) << 5) \
  309.             | ((0x3 & (PRE)) << 3) \
  310.             | (0x7 & (SRC)), \
  311.         .pll_freq = (pll_frequency), \
  312.         .calc_freq = (pll_frequency*M/((PRE+1)*N)), \
  313. }
  314.  
  315. static struct mdns_clock_params *msm_clock_freq_parameters;
  316.  
  317. // GSM phones typically use a 245 MHz PLL0
  318. struct mdns_clock_params msm_clock_freq_parameters_pll0_245[] = {
  319.  
  320.         MSM_CLOCK_REG(  144000,   3, 0x64, 0x32, 3, 3, 0, 1, 19200000), /* SD, 144kHz */
  321. #if 0 /* wince uses this clock setting for UART2DM */
  322.         MSM_CLOCK_REG( 1843200,     3, 0x64, 0x32, 3, 2, 4, 1, 245760000), /*  115200*16=1843200 */
  323. //      MSM_CLOCK_REG(            , 2, 0xc8, 0x64, 3, 2, 1, 1, 768888888), /* 1.92MHz for 120000 bps */
  324. #else
  325.         MSM_CLOCK_REG( 7372800,   3, 0x64, 0x32, 0, 2, 4, 1, 245760000), /*  460800*16, will be divided by 4 for 115200 */
  326. #endif
  327.         MSM_CLOCK_REG(12000000,   1, 0x20, 0x10, 1, 3, 1, 1, 768000000), /* SD, 12MHz */
  328.         MSM_CLOCK_REG(14745600,   3, 0x32, 0x19, 0, 2, 4, 1, 245760000), /* BT, 921600 (*16)*/
  329.         MSM_CLOCK_REG(19200000,   1, 0x0a, 0x05, 3, 3, 1, 1, 768000000), /* SD, 19.2MHz */
  330.         MSM_CLOCK_REG(24000000,   1, 0x10, 0x08, 1, 3, 1, 1, 768000000), /* SD, 24MHz */
  331.         MSM_CLOCK_REG(32000000,   1, 0x0c, 0x06, 1, 3, 1, 1, 768000000), /* SD, 32MHz */
  332.         MSM_CLOCK_REG(58982400,   6, 0x19, 0x0c, 0, 2, 4, 1, 245760000), /* BT, 3686400 (*16) */
  333.         MSM_CLOCK_REG(64000000,0x19, 0x60, 0x30, 0, 2, 4, 1, 245760000), /* BT, 4000000 (*16) */
  334.         {0, 0, 0, 0, 0, 0},
  335. };
  336.  
  337. // CDMA phones typically use a 196 MHz PLL0
  338. struct mdns_clock_params msm_clock_freq_parameters_pll0_196[] = {
  339.  
  340.         MSM_CLOCK_REG(  144000,   3, 0x64, 0x32, 3, 3, 0, 1, 19200000), /* SD, 144kHz */
  341.         MSM_CLOCK_REG( 7372800,   3, 0x50, 0x28, 0, 2, 4, 1, 196608000), /*  460800*16, will be divided by 4 for 115200 */
  342.         MSM_CLOCK_REG(12000000,   1, 0x20, 0x10, 1, 3, 1, 1, 768000000), /* SD, 12MHz */
  343.         MSM_CLOCK_REG(14745600,   3, 0x28, 0x14, 0, 2, 4, 1, 196608000), /* BT, 921600 (*16)*/
  344.         MSM_CLOCK_REG(19200000,   1, 0x0a, 0x05, 3, 3, 1, 1, 768000000), /* SD, 19.2MHz */
  345.         MSM_CLOCK_REG(24000000,   1, 0x10, 0x08, 1, 3, 1, 1, 768000000), /* SD, 24MHz */
  346.         MSM_CLOCK_REG(32000000,   1, 0x0c, 0x06, 1, 3, 1, 1, 768000000), /* SD, 32MHz */
  347.         MSM_CLOCK_REG(58982400,   3, 0x0a, 0x05, 0, 2, 4, 1, 196608000), /* BT, 3686400 (*16) */
  348.         MSM_CLOCK_REG(64000000,0x7d, 0x180, 0xC0, 0, 2, 4, 1, 196608000), /* BT, 4000000 (*16) */
  349.         {0, 0, 0, 0, 0, 0},
  350. };
  351.  
  352. // defines from MSM7500_Core.h
  353.  
  354. // often used defines
  355. #define MSM_PRPH_WEB_NS_REG     ( MSM_CLK_CTL_BASE+0x80 )
  356. #define MSM_GRP_NS_REG                          ( MSM_CLK_CTL_BASE+0x84 )
  357. #define MSM_AXI_RESET                                   ( MSM_CLK_CTL_BASE+0x208 )
  358. #define MSM_ROW_RESET                           ( MSM_CLK_CTL_BASE+0x214 )
  359. #define MSM_VDD_GRP_GFS_CTL     ( MSM_CLK_CTL_BASE+0x284 )
  360. #define MSM_VDD_VDC_GFS_CTL     ( MSM_CLK_CTL_BASE+0x288 )
  361. #define MSM_RAIL_CLAMP_IO                       ( MSM_CLK_CTL_BASE+0x290 )
  362.  
  363. #define REG_OR( reg, value ) do { u32 i = readl( (reg) ); writel( i | (value), (reg) ); } while(0)
  364. #define REG_AND( reg, value ) do {      u32 i = readl( reg ); writel( i & ~value, reg); } while(0)
  365. #define REG_SET( reg, value ) do { writel( value, reg ); } while(0)
  366.  
  367. static void set_grp_clk( int on ) {
  368.         if ( on != 0 ) {
  369.                 REG_OR( MSM_AXI_RESET, 0x20 );
  370.                 REG_OR( MSM_ROW_RESET, 0x20000 );
  371.                 REG_SET( MSM_VDD_GRP_GFS_CTL, 0x11f );
  372.                 mdelay( 20 );                                           // very rough delay
  373.  
  374.                 REG_OR( MSM_GRP_NS_REG, 0x800 );
  375.                 REG_OR( MSM_GRP_NS_REG, 0x80 );
  376.                 REG_OR( MSM_GRP_NS_REG, 0x200 );
  377.  
  378.                 REG_OR( MSM_CLK_CTL_BASE, 0x8 );                                        // grp idx
  379.  
  380.                 REG_AND( MSM_RAIL_CLAMP_IO, 0x4 );
  381.                 REG_AND( MSM_PRPH_WEB_NS_REG, 0x1 );                    // Suppress bit 0 of grp MD
  382.                 REG_AND( MSM_AXI_RESET, 0x20 );
  383.                 REG_AND( MSM_ROW_RESET, 0x20000 );
  384.         } else {
  385.                 REG_OR( MSM_GRP_NS_REG, 0x800 );
  386.                 REG_OR( MSM_GRP_NS_REG, 0x80 );
  387.                 REG_OR( MSM_GRP_NS_REG, 0x200 );
  388.  
  389.                 REG_OR(  MSM_CLK_CTL_BASE, 0x8 );                                       // grp idx
  390.  
  391.                 REG_OR( MSM_PRPH_WEB_NS_REG, 0x1 );                     // grp MD
  392.  
  393.                 int i = 0;
  394.                 int status = 0;
  395.                 while ( status == 0 && i < 100) {
  396.                         i++;
  397.                         status = readl( MSM_GRP_NS_REG ) & 0x1;
  398.                 }
  399.  
  400.                 REG_OR( MSM_AXI_RESET, 0x20 );
  401.                 REG_OR( MSM_ROW_RESET, 0x20000 );
  402.  
  403.                 REG_AND( MSM_GRP_NS_REG, 0x800 );
  404.                 REG_AND( MSM_GRP_NS_REG, 0x80 );
  405.                 REG_AND( MSM_GRP_NS_REG, 0x200 );
  406.  
  407.                 REG_OR( MSM_RAIL_CLAMP_IO, 0x4 );                                       // grp clk ramp
  408.  
  409.                 REG_SET( MSM_VDD_GRP_GFS_CTL, 0x11f );
  410.  
  411.                 int control = readl( MSM_VDD_VDC_GFS_CTL );
  412.  
  413.                 if ( control & 0x100 ) {
  414.                         REG_AND( MSM_CLK_CTL_BASE, 0x8 );                               // grp idx
  415.                 }
  416.         }
  417. }
  418.  
  419. static inline struct msm_clock_params msm_clk_get_params(uint32_t id)
  420. {
  421.         int i;
  422.         struct msm_clock_params empty = { };
  423.         for (i = 0; i < ARRAY_SIZE(msm_clock_parameters_def); i++) {
  424.                 if (id == msm_clock_parameters[i].clk_id) {
  425.                         return msm_clock_parameters[i];
  426.                 }
  427.         }
  428.         return empty;
  429. }
  430.  
  431. static inline uint32_t msm_clk_enable_bit(uint32_t id)
  432. {
  433.         struct msm_clock_params params;
  434.         params = msm_clk_get_params(id);
  435.         if (!params.idx) return 0;
  436.         return 1U << params.idx;
  437. }
  438.  
  439. static inline unsigned msm_clk_reg_offset(uint32_t id)
  440. {
  441.         struct msm_clock_params params;
  442.         params = msm_clk_get_params(id);
  443.         return params.offset;
  444. }
  445.  
  446. static int set_mdns_host_clock(uint32_t id, unsigned long freq)
  447. {
  448.         int n;
  449.         unsigned offset;
  450.         int retval;
  451.         bool found;
  452.         struct msm_clock_params params;
  453.         uint32_t nsreg;
  454.         found = 0;
  455.         retval = -EINVAL;
  456.  
  457.         params = msm_clk_get_params(id);
  458.         offset = params.offset;
  459.  
  460.         if(debug_mask&DEBUG_MDNS)
  461.                 D("set mdns: %u, %lu; bitidx=%u, offset=%x, ns=%x\n", id, freq,
  462.           params.idx, params.offset, params.ns_only);
  463.  
  464.         if (!params.offset)
  465.         {
  466.                 printk(KERN_WARNING "%s: FIXME! Don't know how to set clock %u - no known Md/Ns reg\n", __func__, id);
  467.                 return -ENOTSUPP;
  468.         }
  469.  
  470.         // Turn off clock-enable bit if supported
  471.         if (params.idx > 0)
  472.                 writel(readl(MSM_CLK_CTL_BASE) & ~(1U << params.idx), MSM_CLK_CTL_BASE);
  473.  
  474.         if (params.ns_only > 0)
  475.         {
  476.                 nsreg = readl(MSM_CLK_CTL_BASE + offset) & 0xfffff000;
  477.                 writel( nsreg | params.ns_only, MSM_CLK_CTL_BASE + offset);
  478.  
  479.                 found = 1;
  480.                 retval = 0;
  481.  
  482.         } else {
  483.                 n = 0;
  484.                 while (msm_clock_freq_parameters[n].freq) {
  485.                         n++;
  486.                 }
  487.  
  488.                 for (n--; n >= 0; n--) {
  489.                         if (freq >= msm_clock_freq_parameters[n].freq) {
  490.                                 // This clock requires MD and NS regs to set frequency:
  491.                                 writel(msm_clock_freq_parameters[n].md, MSM_CLK_CTL_BASE + offset - 4);
  492.                                 writel(msm_clock_freq_parameters[n].ns, MSM_CLK_CTL_BASE + offset);
  493. //                              msleep(5);
  494.                                 if(debug_mask&DEBUG_MDNS)
  495.                                         D("%s: %u, freq=%lu calc_freq=%u pll%d=%u expected pll =%u\n", __func__, id,
  496.                                   msm_clock_freq_parameters[n].freq,
  497.                                   msm_clock_freq_parameters[n].calc_freq,
  498.                                   msm_clock_freq_parameters[n].ns&7,
  499.                                   pll_get_rate(idx2pll(msm_clock_freq_parameters[n].ns&7)),
  500.                                   msm_clock_freq_parameters[n].pll_freq );
  501.                                 retval = 0;
  502.                                 found = 1;
  503.                                 break;
  504.                         }
  505.                 }
  506.         }
  507.  
  508.         // Turn clock-enable bit back on, if supported
  509.         if (params.idx > 0)
  510.                 writel(readl(MSM_CLK_CTL_BASE) | (1U << params.idx), MSM_CLK_CTL_BASE);
  511.  
  512.         if (!found && debug_mask&DEBUG_UNKNOWN_FREQ) {
  513.                 printk(KERN_WARNING "clock-wince: FIXME! set_sdcc_host_clock could not "
  514.                        "find suitable parameter for freq %lu\n", freq);
  515.         }
  516.  
  517. //     return retval;
  518.        return 0;
  519. }
  520.  
  521. static unsigned long get_mdns_host_clock(uint32_t id)
  522. {
  523.         int n;
  524.         unsigned offset;
  525.         uint32_t mdreg;
  526.         uint32_t nsreg;
  527.         unsigned long freq = 0;
  528.  
  529.         offset = msm_clk_reg_offset(id);
  530.         if (offset == 0)
  531.                 return -EINVAL;
  532.  
  533.         mdreg = readl(MSM_CLK_CTL_BASE + offset - 4);
  534.         nsreg = readl(MSM_CLK_CTL_BASE + offset);
  535.  
  536.         n = 0;
  537.         while (msm_clock_freq_parameters[n].freq) {
  538.                 if (msm_clock_freq_parameters[n].md == mdreg &&
  539.                         msm_clock_freq_parameters[n].ns == nsreg) {
  540.                         freq = msm_clock_freq_parameters[n].freq;
  541.                         break;
  542.                 }
  543.                 n++;
  544.         }
  545.  
  546.         return freq;
  547. }
  548.  
  549. #ifndef CONFIG_MSM_AMSS_VERSION_WINCE
  550. static inline int pc_clk_enable(unsigned id)
  551. {
  552.         return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
  553. }
  554.  
  555. static inline void pc_clk_disable(unsigned id)
  556. {
  557.         msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
  558. }
  559.  
  560. static inline int pc_clk_set_rate(unsigned id, unsigned rate)
  561. {
  562.         return msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
  563. }
  564.  
  565. static inline int pc_clk_set_min_rate(unsigned id, unsigned rate)
  566. {
  567.         return msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
  568. }
  569.  
  570. static inline int pc_clk_set_max_rate(unsigned id, unsigned rate)
  571. {
  572.         return msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
  573. }
  574.  
  575. static inline int pc_clk_set_flags(unsigned id, unsigned flags)
  576. {
  577.         return msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags);
  578. }
  579.  
  580. static inline unsigned pc_clk_get_rate(unsigned id)
  581. {
  582.         if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
  583.                 return 0;
  584.         else
  585.                 return id;
  586. }
  587.  
  588. static inline unsigned pc_clk_is_enabled(unsigned id)
  589. {
  590.         if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
  591.                 return 0;
  592.         else
  593.                 return id;
  594. }
  595.  
  596. static inline int pc_pll_request(unsigned id, unsigned on)
  597. {
  598.         on = !!on;
  599.         return msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on);
  600. }
  601. #else
  602.  
  603. static int pc_clk_enable(uint32_t id)
  604. {
  605.         struct msm_clock_params params;
  606.         int done=0;
  607.         params = msm_clk_get_params(id);
  608.  
  609.         //XXX: too spammy, extreme debugging only: D(KERN_DEBUG "%s: %d\n", __func__, id);
  610.  
  611.         if ( id == IMEM_CLK || id == GRP_CLK )
  612.         {
  613.                 //clock_poop( 0 );             
  614.                 set_grp_clk( 1 );
  615.                 //writel(readl(MSM_CLK_CTL_BASE) | (1U << params.idx), MSM_CLK_CTL_BASE);
  616.                 done=1;
  617.         }
  618.  
  619.         if (params.idx)
  620.         {
  621.                 writel(readl(MSM_CLK_CTL_BASE) | (1U << params.idx), MSM_CLK_CTL_BASE);
  622.                 done=1;
  623.         }
  624.         if (params.ns_only > 0 && params.offset)
  625.         {
  626.                 writel((readl(MSM_CLK_CTL_BASE + params.offset) &0xfffff000) | params.ns_only, MSM_CLK_CTL_BASE + params.offset);
  627.                 done=1;
  628.         }
  629.         if(!done && debug_mask&DEBUG_UNKNOWN_ID)
  630.                 printk(KERN_WARNING "%s: FIXME! enabling a clock that doesn't have an ena bit "
  631.                        "or ns-only offset: %u\n", __func__, id);
  632.  
  633.         return 0;
  634. }
  635.  
  636. static void pc_clk_disable(uint32_t id)
  637. {
  638.         struct msm_clock_params params;
  639.         params = msm_clk_get_params(id);
  640.  
  641.         //XXX: D(KERN_DEBUG "%s: %d\n", __func__, id);
  642.  
  643.         if ( id == IMEM_CLK || id == GRP_CLK )
  644.         {
  645.                 set_grp_clk( 0 );
  646.                 writel( readl( MSM_CLK_CTL_BASE ) & ~( 1U << params.idx ), MSM_CLK_CTL_BASE );
  647.                 return 0;
  648.         }
  649.  
  650.         if (params.idx)
  651.         {
  652.                 writel(readl(MSM_CLK_CTL_BASE) & ~(1U << params.idx), MSM_CLK_CTL_BASE);
  653.         } else if (params.ns_only > 0 && params.offset)
  654.         {
  655.                 writel(readl(MSM_CLK_CTL_BASE + params.offset) & 0xfffff000, MSM_CLK_CTL_BASE + params.offset);
  656.         } else {
  657.                 if(debug_mask&DEBUG_UNKNOWN_ID)
  658.                         printk(KERN_WARNING "%s: FIXME! disabling a clock that doesn't have an "
  659.                                "ena bit: %u\n", __func__, id);
  660.         }
  661. }
  662.  
  663. static int pc_clk_set_rate(uint32_t id, unsigned long rate)
  664. {
  665.         int retval;
  666.         retval = 0;
  667.  
  668.         if(DEBUG_MDNS)
  669.                 D("%s: id=%u rate=%lu\n", __func__, id, rate);
  670.  
  671.         retval = set_mdns_host_clock(id, rate);
  672.  
  673.         return retval;
  674. }
  675.  
  676. static int pc_clk_set_min_rate(uint32_t id, unsigned long rate)
  677. {
  678.         if (id < NR_CLKS)
  679.          min_clk_rate[id]=rate;
  680.         else if(debug_mask&DEBUG_UNKNOWN_ID)
  681.          printk(KERN_WARNING " FIXME! clk_set_min_rate not implemented; %u:%lu NR_CLKS=%d\n", id, rate, NR_CLKS);
  682.  
  683.         return 0;
  684. }
  685.  
  686. static int pc_clk_set_max_rate(uint32_t id, unsigned long rate)
  687. {
  688.         if (id < NR_CLKS)
  689.          max_clk_rate[id]=rate;
  690.         else if(debug_mask&DEBUG_UNKNOWN_ID)
  691.          printk(KERN_WARNING " FIXME! clk_set_min_rate not implemented; %u:%lu NR_CLKS=%d\n", id, rate, NR_CLKS);
  692.  
  693.         return 0;
  694. }
  695.  
  696. static unsigned long pc_clk_get_rate(uint32_t id)
  697. {
  698.         unsigned long rate = 0;
  699.  
  700.         switch (id) {
  701.                 /* known MD/NS clocks, MSM_CLK dump and arm/mach-msm/clock-7x30.c */
  702.                 case SDC1_CLK:
  703.                 case SDC2_CLK:
  704.                 case SDC3_CLK:
  705.                 case SDC4_CLK:
  706.                 case UART1DM_CLK:
  707.                 case UART2DM_CLK:
  708.                 case USB_HS_CLK:
  709.                 case SDAC_CLK:
  710.                 case TV_DAC_CLK:
  711.                 case TV_ENC_CLK:
  712.                 case USB_OTG_CLK:
  713.                         rate = get_mdns_host_clock(id);
  714.                         break;
  715.  
  716.                 case SDC1_PCLK:
  717.                 case SDC2_PCLK:
  718.                 case SDC3_PCLK:
  719.                 case SDC4_PCLK:
  720.                         rate = 64000000; /* g1 value */
  721.                         break;
  722.  
  723.                 default:
  724.                         //TODO: support all clocks
  725.                         if(debug_mask&DEBUG_UNKNOWN_ID)
  726.                                 printk("%s: unknown clock: id=%u\n", __func__, id);
  727.                         rate = 0;
  728.         }
  729.  
  730.         return rate;
  731. }
  732.  
  733. static int pc_clk_set_flags(uint32_t id, unsigned long flags)
  734. {
  735.         if(debug_mask&DEBUG_UNKNOWN_CMD)
  736.                 printk(KERN_WARNING "%s not implemented for clock: id=%u, flags=%lu\n", __func__, id, flags);
  737.         return 0;
  738. }
  739.  
  740. static int pc_clk_is_enabled(uint32_t id)
  741. {
  742.         int is_enabled = 0;
  743.         unsigned bit;
  744.         bit = msm_clk_enable_bit(id);
  745.         if (bit > 0)
  746.         {
  747.                 is_enabled = (readl(MSM_CLK_CTL_BASE) & bit) != 0;
  748.         }
  749.         //XXX: is this necessary?
  750.         if (id==SDC1_PCLK || id==SDC2_PCLK || id==SDC3_PCLK || id==SDC4_PCLK)
  751.                 is_enabled = 1;
  752.         return is_enabled;
  753. }
  754.  
  755. static int pc_pll_request(unsigned id, unsigned on)
  756. {
  757.         if(debug_mask&DEBUG_UNKNOWN_CMD)
  758.                 printk(KERN_WARNING "%s not implemented for PLL=%u\n", __func__, id);
  759.  
  760.         return 0;
  761. }
  762.  
  763. #endif
  764.  
  765. /*
  766.  * Standard clock functions defined in include/linux/clk.h
  767.  */
  768. struct clk *clk_get(struct device *dev, const char *id)
  769. {
  770.         struct clk *clk;
  771.  
  772.         mutex_lock(&clocks_mutex);
  773.  
  774.         list_for_each_entry(clk, &clocks, list)
  775.                 if (!strcmp(id, clk->name) && clk->dev == dev)
  776.                         goto found_it;
  777.  
  778.         list_for_each_entry(clk, &clocks, list)
  779.                 if (!strcmp(id, clk->name) && clk->dev == NULL)
  780.                         goto found_it;
  781.  
  782.         clk = ERR_PTR(-ENOENT);
  783. found_it:
  784.         mutex_unlock(&clocks_mutex);
  785.         return clk;
  786. }
  787. EXPORT_SYMBOL(clk_get);
  788.  
  789. void clk_put(struct clk *clk)
  790. {
  791. }
  792. EXPORT_SYMBOL(clk_put);
  793.  
  794. int clk_enable(struct clk *clk)
  795. {
  796.         unsigned long flags;
  797.         if (clk->id == ACPU_CLK)
  798.         {
  799.                 return -ENOTSUPP;
  800.         }
  801.         spin_lock_irqsave(&clocks_lock, flags);
  802.         clk->count++;
  803.         if (clk->count == 1)
  804.                 pc_clk_enable(clk->id);
  805.         spin_unlock_irqrestore(&clocks_lock, flags);
  806.         return 0;
  807. }
  808. EXPORT_SYMBOL(clk_enable);
  809.  
  810. void clk_disable(struct clk *clk)
  811. {
  812.         unsigned long flags;
  813.         spin_lock_irqsave(&clocks_lock, flags);
  814.         BUG_ON(clk->count == 0);
  815.         clk->count--;
  816.         if (clk->count == 0)
  817.                 pc_clk_disable(clk->id);
  818.         spin_unlock_irqrestore(&clocks_lock, flags);
  819. }
  820. EXPORT_SYMBOL(clk_disable);
  821.  
  822. unsigned long clk_get_rate(struct clk *clk)
  823. {
  824.         return pc_clk_get_rate(clk->id);
  825. }
  826. EXPORT_SYMBOL(clk_get_rate);
  827.  
  828. int clk_set_rate(struct clk *clk, unsigned long rate)
  829. {
  830.         int ret;
  831.         if (clk->flags & CLKFLAG_USE_MAX_TO_SET) {
  832.                 ret = pc_clk_set_max_rate(clk->id, rate);
  833.                 if (ret)
  834.                         return ret;
  835.         }
  836.         if (clk->flags & CLKFLAG_USE_MIN_TO_SET) {
  837.                 ret = pc_clk_set_min_rate(clk->id, rate);
  838.                 if (ret)
  839.                         return ret;
  840.         }
  841.  
  842.         if (clk->flags & CLKFLAG_USE_MAX_TO_SET ||
  843.                 clk->flags & CLKFLAG_USE_MIN_TO_SET)
  844.                 return ret;
  845.  
  846.         return pc_clk_set_rate(clk->id, rate);
  847. }
  848. EXPORT_SYMBOL(clk_set_rate);
  849.  
  850. int clk_set_parent(struct clk *clk, struct clk *parent)
  851. {
  852.         return -ENOSYS;
  853. }
  854. EXPORT_SYMBOL(clk_set_parent);
  855.  
  856. struct clk *clk_get_parent(struct clk *clk)
  857. {
  858.         return ERR_PTR(-ENOSYS);
  859. }
  860. EXPORT_SYMBOL(clk_get_parent);
  861.  
  862. int clk_set_flags(struct clk *clk, unsigned long flags)
  863. {
  864.         if (clk == NULL || IS_ERR(clk))
  865.                 return -EINVAL;
  866.         return pc_clk_set_flags(clk->id, flags);
  867. }
  868. EXPORT_SYMBOL(clk_set_flags);
  869.  
  870.  
  871. void __init msm_clock_init(void)
  872. {
  873.  
  874. int amss_s_version;
  875. //amss_s_version = get_amss_s_version();
  876.  
  877.         struct clk *clk;
  878. //      switch(amss_s_version) {
  879. //              case 6125:
  880.                         msm_clock_parameters = msm_clock_parameters_6125;
  881. //                      printk(KERN_ERR "amss: Using 6125 clocks\n");
  882. //              break;
  883. //              default:
  884. //                      msm_clock_parameters = msm_clock_parameters_def;
  885. //                      printk(KERN_ERR "amss: Using default clocks\n");
  886. //              break;
  887. //      }
  888.        
  889.         spin_lock_init(&clocks_lock);
  890.         mutex_lock(&clocks_mutex);
  891.         for (clk = msm_clocks; clk && clk->name; clk++) {
  892.                 list_add_tail(&clk->list, &clocks);
  893.         }
  894.  
  895. //      if (pll_get_rate(0) == 196608000) {
  896.                 // cdma pll0 = 196 MHz
  897. //              msm_clock_freq_parameters = msm_clock_freq_parameters_pll0_196;
  898. //      } else {
  899.                 // default gsm pll0 = 245 MHz
  900.                 msm_clock_freq_parameters = msm_clock_freq_parameters_pll0_245;
  901. //      }
  902.  
  903.         mutex_unlock(&clocks_mutex);
  904. }
  905.  
  906. /* The bootloader and/or AMSS may have left various clocks enabled.
  907.  * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
  908.  * not been explicitly enabled by a clk_enable() call.
  909.  */
  910.  
  911.  
  912.  
  913. #define PMIC_API_PROG           0x30000055
  914. #define PMIC_API_VERS           0x0
  915. #define PMIC_API_GET_KHZ_PROC   0x1
  916.  
  917. #define GRP_RAIL_ON 0x2C
  918. #define GRP_RAIL_OFF 0x2B
  919.  
  920. void clk_regime_sec(int i) {
  921.         struct msm_rpc_endpoint *ept=NULL;
  922.         struct {
  923.                 struct rpc_request_hdr hdr;
  924.                 uint32_t data[1];
  925.         } req;
  926.         BUG_ON(ept=msm_rpc_connect(0x3000000f, 0x1c5ace2a, 0x0));
  927.         if (IS_ERR(ept)) {
  928.                 printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
  929.                 __func__, PTR_ERR(ept));
  930.         }
  931.         else {
  932.                 req.data[0]=cpu_to_be32(0x1);
  933.                 msm_rpc_call(ept, i, &req, sizeof(req), 15*HZ);
  934.         }
  935. }
  936.  
  937. static void get_clk_khz(void)
  938. {
  939.         struct msm_rpc_endpoint *pmic_ep;
  940.         int rc;
  941.         struct {
  942.                 struct rpc_request_hdr hdr;
  943.                 uint32_t data[1];
  944.         } req;
  945.        
  946.         pmic_ep = msm_rpc_connect(PMIC_API_PROG, PMIC_API_VERS, 0);
  947.         if (IS_ERR(pmic_ep)) {
  948.                 printk(KERN_ERR "%s: init rpc failed! error: %ld\n",
  949.                                 __func__, PTR_ERR(pmic_ep));
  950.                 goto close;
  951.         }
  952.         unsigned i;
  953.         pr_info("IMEM OLD: VAL = %d\n", readl(MSM_IMEM_BASE ));
  954.         req.data[0] = cpu_to_be32(1);
  955.         rc = msm_rpc_call(pmic_ep, PMIC_API_GET_KHZ_PROC, &req, sizeof(req), 5 * HZ);
  956.         if (rc < 0)
  957.                 printk(KERN_ERR "%s: rpc call failed! (%d)\n", __func__, rc);
  958.        
  959.         msleep(100),
  960.         pr_info("IMEM NEW: VAL = %d\n", readl(MSM_IMEM_BASE ));
  961.  
  962. close:
  963.         msm_rpc_close(pmic_ep);
  964. }
  965.  
  966. static int __init clock_late_init(void)
  967. {
  968.         unsigned long flags;
  969.         struct clk *clk;
  970.         unsigned count = 0;
  971.  
  972.         //clock_poop(0);
  973.  
  974.         mutex_lock(&clocks_mutex);
  975.         list_for_each_entry(clk, &clocks, list) {
  976.                 if (clk->flags & CLKFLAG_AUTO_OFF) {
  977.                         spin_lock_irqsave(&clocks_lock, flags);
  978.                         if (!clk->count) {
  979.                                 count++;
  980.                                 // pr_info("disabling %d \n", clk->id);
  981.                                 pc_clk_disable(clk->id);
  982.                         }
  983.                         spin_unlock_irqrestore(&clocks_lock, flags);
  984.                 }
  985.         }
  986.         mutex_unlock(&clocks_mutex);
  987.         pr_info("clock_late_init() disabled %d unused clocks\n", count);
  988.  
  989.         return 0;
  990. }
  991.  
  992. late_initcall(clock_late_init);