davinci: dm646x-evm: Add platform data for NAND
[linux-2.6-block.git] / arch / arm / mach-davinci / da850.c
index 192d719a47df556b663a12beaf9f02b4ec9e8682..bd79288e22acb055a0b2a6ce6c8df7772e4eb9de 100644 (file)
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/cpufreq.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach/map.h>
 
-#include <mach/clock.h>
 #include <mach/psc.h>
-#include <mach/mux.h>
 #include <mach/irqs.h>
 #include <mach/cputype.h>
 #include <mach/common.h>
 #include <mach/time.h>
 #include <mach/da8xx.h>
+#include <mach/cpufreq.h>
 
 #include "clock.h"
 #include "mux.h"
 
+/* SoC specific clock flags */
+#define DA850_CLK_ASYNC3       BIT(16)
+
 #define DA850_PLL1_BASE                0x01e1a000
 #define DA850_TIMER64P2_BASE   0x01f0c000
 #define DA850_TIMER64P3_BASE   0x01f0d000
 
 #define DA850_REF_FREQ         24000000
 
+#define CFGCHIP3_ASYNC3_CLKSRC BIT(4)
+#define CFGCHIP0_PLL_MASTER_LOCK       BIT(4)
+
+static int da850_set_armrate(struct clk *clk, unsigned long rate);
+static int da850_round_armrate(struct clk *clk, unsigned long rate);
+static int da850_set_pll0rate(struct clk *clk, unsigned long armrate);
+
 static struct pll_data pll0_data = {
        .num            = 1,
        .phys_base      = DA8XX_PLL0_BASE,
@@ -52,6 +62,7 @@ static struct clk pll0_clk = {
        .parent         = &ref_clk,
        .pll_data       = &pll0_data,
        .flags          = CLK_PLL,
+       .set_rate       = da850_set_pll0rate,
 };
 
 static struct clk pll0_aux_clk = {
@@ -210,16 +221,16 @@ static struct clk tpcc1_clk = {
        .name           = "tpcc1",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA850_LPSC1_TPCC1,
+       .gpsc           = 1,
        .flags          = CLK_PSC | ALWAYS_ENABLED,
-       .psc_ctlr       = 1,
 };
 
 static struct clk tptc2_clk = {
        .name           = "tptc2",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA850_LPSC1_TPTC2,
+       .gpsc           = 1,
        .flags          = ALWAYS_ENABLED,
-       .psc_ctlr       = 1,
 };
 
 static struct clk uart0_clk = {
@@ -232,14 +243,16 @@ static struct clk uart1_clk = {
        .name           = "uart1",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA8XX_LPSC1_UART1,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
+       .flags          = DA850_CLK_ASYNC3,
 };
 
 static struct clk uart2_clk = {
        .name           = "uart2",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA8XX_LPSC1_UART2,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
+       .flags          = DA850_CLK_ASYNC3,
 };
 
 static struct clk aintc_clk = {
@@ -253,22 +266,22 @@ static struct clk gpio_clk = {
        .name           = "gpio",
        .parent         = &pll0_sysclk4,
        .lpsc           = DA8XX_LPSC1_GPIO,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
 };
 
 static struct clk i2c1_clk = {
        .name           = "i2c1",
        .parent         = &pll0_sysclk4,
        .lpsc           = DA8XX_LPSC1_I2C,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
 };
 
 static struct clk emif3_clk = {
        .name           = "emif3",
        .parent         = &pll0_sysclk5,
        .lpsc           = DA8XX_LPSC1_EMIF3C,
+       .gpsc           = 1,
        .flags          = ALWAYS_ENABLED,
-       .psc_ctlr       = 1,
 };
 
 static struct clk arm_clk = {
@@ -276,6 +289,8 @@ static struct clk arm_clk = {
        .parent         = &pll0_sysclk6,
        .lpsc           = DA8XX_LPSC0_ARM,
        .flags          = ALWAYS_ENABLED,
+       .set_rate       = da850_set_armrate,
+       .round_rate     = da850_round_armrate,
 };
 
 static struct clk rmii_clk = {
@@ -287,21 +302,21 @@ static struct clk emac_clk = {
        .name           = "emac",
        .parent         = &pll0_sysclk4,
        .lpsc           = DA8XX_LPSC1_CPGMAC,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
 };
 
 static struct clk mcasp_clk = {
        .name           = "mcasp",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA8XX_LPSC1_McASP0,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
 };
 
 static struct clk lcdc_clk = {
        .name           = "lcdc",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA8XX_LPSC1_LCDC,
-       .psc_ctlr       = 1,
+       .gpsc           = 1,
 };
 
 static struct clk mmcsd_clk = {
@@ -404,6 +419,14 @@ static const struct mux_config da850_pins[] = {
        MUX_CFG(DA850, MII_RXD_0,       3,      28,     15,     8,      false)
        MUX_CFG(DA850, MDIO_CLK,        4,      0,      15,     8,      false)
        MUX_CFG(DA850, MDIO_D,          4,      4,      15,     8,      false)
+       MUX_CFG(DA850, RMII_TXD_0,      14,     12,     15,     8,      false)
+       MUX_CFG(DA850, RMII_TXD_1,      14,     8,      15,     8,      false)
+       MUX_CFG(DA850, RMII_TXEN,       14,     16,     15,     8,      false)
+       MUX_CFG(DA850, RMII_CRS_DV,     15,     4,      15,     8,      false)
+       MUX_CFG(DA850, RMII_RXD_0,      14,     24,     15,     8,      false)
+       MUX_CFG(DA850, RMII_RXD_1,      14,     20,     15,     8,      false)
+       MUX_CFG(DA850, RMII_RXER,       14,     28,     15,     8,      false)
+       MUX_CFG(DA850, RMII_MHZ_50_CLK, 15,     0,      15,     0,      false)
        /* McASP function */
        MUX_CFG(DA850,  ACLKR,          0,      0,      15,     1,      false)
        MUX_CFG(DA850,  ACLKX,          0,      4,      15,     1,      false)
@@ -506,8 +529,9 @@ static const struct mux_config da850_pins[] = {
        MUX_CFG(DA850, EMA_WAIT_1,      6,      24,     15,     1,      false)
        MUX_CFG(DA850, NEMA_CS_2,       7,      0,      15,     1,      false)
        /* GPIO function */
+       MUX_CFG(DA850, GPIO2_6,         6,      4,      15,     8,      false)
+       MUX_CFG(DA850, GPIO2_8,         5,      28,     15,     8,      false)
        MUX_CFG(DA850, GPIO2_15,        5,      0,      15,     8,      false)
-       MUX_CFG(DA850, GPIO8_10,        18,     28,     15,     8,      false)
        MUX_CFG(DA850, GPIO4_0,         10,     28,     15,     8,      false)
        MUX_CFG(DA850, GPIO4_1,         10,     24,     15,     8,      false)
 #endif
@@ -547,6 +571,14 @@ const short da850_cpgmac_pins[] __initdata = {
        -1
 };
 
+const short da850_rmii_pins[] __initdata = {
+       DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+       DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
+       DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
+       DA850_MDIO_D,
+       -1
+};
+
 const short da850_mcasp_pins[] __initdata = {
        DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
        DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE,
@@ -555,12 +587,11 @@ const short da850_mcasp_pins[] __initdata = {
 };
 
 const short da850_lcdcntl_pins[] __initdata = {
-       DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3, DA850_LCD_D_4,
-       DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7, DA850_LCD_D_8,
-       DA850_LCD_D_9, DA850_LCD_D_10, DA850_LCD_D_11, DA850_LCD_D_12,
-       DA850_LCD_D_13, DA850_LCD_D_14, DA850_LCD_D_15, DA850_LCD_PCLK,
-       DA850_LCD_HSYNC, DA850_LCD_VSYNC, DA850_NLCD_AC_ENB_CS, DA850_GPIO2_15,
-       DA850_GPIO8_10,
+       DA850_LCD_D_0, DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3,
+       DA850_LCD_D_4, DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7,
+       DA850_LCD_D_8, DA850_LCD_D_9, DA850_LCD_D_10, DA850_LCD_D_11,
+       DA850_LCD_D_12, DA850_LCD_D_13, DA850_LCD_D_14, DA850_LCD_D_15,
+       DA850_LCD_PCLK, DA850_LCD_HSYNC, DA850_LCD_VSYNC, DA850_NLCD_AC_ENB_CS,
        -1
 };
 
@@ -790,16 +821,223 @@ static struct davinci_timer_info da850_timer_info = {
        .clocksource_id = T0_TOP,
 };
 
+static void da850_set_async3_src(int pllnum)
+{
+       struct clk *clk, *newparent = pllnum ? &pll1_sysclk2 : &pll0_sysclk2;
+       struct davinci_clk *c;
+       unsigned int v;
+       int ret;
+
+       for (c = da850_clks; c->lk.clk; c++) {
+               clk = c->lk.clk;
+               if (clk->flags & DA850_CLK_ASYNC3) {
+                       ret = clk_set_parent(clk, newparent);
+                       WARN(ret, "DA850: unable to re-parent clock %s",
+                                                               clk->name);
+               }
+       }
+
+       v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG));
+       if (pllnum)
+               v |= CFGCHIP3_ASYNC3_CLKSRC;
+       else
+               v &= ~CFGCHIP3_ASYNC3_CLKSRC;
+       __raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG));
+}
+
+#ifdef CONFIG_CPU_FREQ
+/*
+ * Notes:
+ * According to the TRM, minimum PLLM results in maximum power savings.
+ * The OPP definitions below should keep the PLLM as low as possible.
+ *
+ * The output of the PLLM must be between 400 to 600 MHz.
+ * This rules out prediv of anything but divide-by-one for 24Mhz OSC input.
+ */
+struct da850_opp {
+       unsigned int    freq;   /* in KHz */
+       unsigned int    prediv;
+       unsigned int    mult;
+       unsigned int    postdiv;
+       unsigned int    cvdd_min; /* in uV */
+       unsigned int    cvdd_max; /* in uV */
+};
+
+static const struct da850_opp da850_opp_300 = {
+       .freq           = 300000,
+       .prediv         = 1,
+       .mult           = 25,
+       .postdiv        = 2,
+       .cvdd_min       = 1140000,
+       .cvdd_max       = 1320000,
+};
+
+static const struct da850_opp da850_opp_200 = {
+       .freq           = 200000,
+       .prediv         = 1,
+       .mult           = 25,
+       .postdiv        = 3,
+       .cvdd_min       = 1050000,
+       .cvdd_max       = 1160000,
+};
+
+static const struct da850_opp da850_opp_96 = {
+       .freq           = 96000,
+       .prediv         = 1,
+       .mult           = 20,
+       .postdiv        = 5,
+       .cvdd_min       = 950000,
+       .cvdd_max       = 1050000,
+};
+
+#define OPP(freq)              \
+       {                               \
+               .index = (unsigned int) &da850_opp_##freq,      \
+               .frequency = freq * 1000, \
+       }
+
+static struct cpufreq_frequency_table da850_freq_table[] = {
+       OPP(300),
+       OPP(200),
+       OPP(96),
+       {
+               .index          = 0,
+               .frequency      = CPUFREQ_TABLE_END,
+       },
+};
+
+static struct davinci_cpufreq_config cpufreq_info = {
+       .freq_table = &da850_freq_table[0],
+};
+
+static struct platform_device da850_cpufreq_device = {
+       .name                   = "cpufreq-davinci",
+       .dev = {
+               .platform_data  = &cpufreq_info,
+       },
+};
+
+int __init da850_register_cpufreq(void)
+{
+       return platform_device_register(&da850_cpufreq_device);
+}
+
+static int da850_round_armrate(struct clk *clk, unsigned long rate)
+{
+       int i, ret = 0, diff;
+       unsigned int best = (unsigned int) -1;
+
+       rate /= 1000; /* convert to kHz */
+
+       for (i = 0; da850_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+               diff = da850_freq_table[i].frequency - rate;
+               if (diff < 0)
+                       diff = -diff;
+
+               if (diff < best) {
+                       best = diff;
+                       ret = da850_freq_table[i].frequency;
+               }
+       }
+
+       return ret * 1000;
+}
+
+static int da850_set_armrate(struct clk *clk, unsigned long index)
+{
+       struct clk *pllclk = &pll0_clk;
+
+       return clk_set_rate(pllclk, index);
+}
+
+static int da850_set_pll0rate(struct clk *clk, unsigned long index)
+{
+       unsigned int prediv, mult, postdiv;
+       struct da850_opp *opp;
+       struct pll_data *pll = clk->pll_data;
+       unsigned int v;
+       int ret;
+
+       opp = (struct da850_opp *) da850_freq_table[index].index;
+       prediv = opp->prediv;
+       mult = opp->mult;
+       postdiv = opp->postdiv;
+
+       /* Unlock writing to PLL registers */
+       v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG));
+       v &= ~CFGCHIP0_PLL_MASTER_LOCK;
+       __raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG));
+
+       ret = davinci_set_pllrate(pll, prediv, mult, postdiv);
+       if (WARN_ON(ret))
+               return ret;
+
+       return 0;
+}
+#else
+int __init da850_register_cpufreq(void)
+{
+       return 0;
+}
+
+static int da850_set_armrate(struct clk *clk, unsigned long rate)
+{
+       return -EINVAL;
+}
+
+static int da850_set_pll0rate(struct clk *clk, unsigned long armrate)
+{
+       return -EINVAL;
+}
+
+static int da850_round_armrate(struct clk *clk, unsigned long rate)
+{
+       return clk->rate;
+}
+#endif
+
+#ifdef CONFIG_REGULATOR
+static struct regulator *cvdd;
+
+static int da850_set_voltage(unsigned int index)
+{
+       struct da850_opp *opp;
+
+       if (!cvdd)
+               return -ENODEV;
+
+       opp = (struct da850_opp *) da850_freq_table[index].index;
+
+       return regulator_set_voltage(cvdd, opp->cvdd_min, opp->cvdd_max);
+}
+
+static int __init da850_regulator_init(void)
+{
+       int ret = 0;
+
+       cvdd = regulator_get(NULL, "cvdd");
+       if (WARN(IS_ERR(cvdd), "Unable to obtain voltage regulator for CVDD;"
+                                       " voltage scaling unsupported\n")) {
+               ret = PTR_ERR(cvdd);
+               goto out;
+       }
+
+       cpufreq_info.set_voltage = da850_set_voltage;
+
+out:
+       return ret;
+}
+device_initcall(da850_regulator_init);
+#endif
+
 static struct davinci_soc_info davinci_soc_info_da850 = {
        .io_desc                = da850_io_desc,
        .io_desc_num            = ARRAY_SIZE(da850_io_desc),
-       .jtag_id_base           = IO_ADDRESS(DA8XX_JTAG_ID_REG),
        .ids                    = da850_ids,
        .ids_num                = ARRAY_SIZE(da850_ids),
        .cpu_clks               = da850_clks,
        .psc_bases              = da850_psc_bases,
        .psc_bases_num          = ARRAY_SIZE(da850_psc_bases),
-       .pinmux_base            = IO_ADDRESS(DA8XX_BOOT_CFG_BASE + 0x120),
        .pinmux_pins            = da850_pins,
        .pinmux_pins_num        = ARRAY_SIZE(da850_pins),
        .intc_base              = (void __iomem *)DA8XX_CP_INTC_VIRT,
@@ -816,5 +1054,22 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
 
 void __init da850_init(void)
 {
+       da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K);
+       if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module"))
+               return;
+
+       davinci_soc_info_da850.jtag_id_base =
+                                       DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG);
+       davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG_VIRT(0x120);
+
        davinci_common_init(&davinci_soc_info_da850);
+
+       /*
+        * Move the clock source of Async3 domain to PLL1 SYSCLK2.
+        * This helps keeping the peripherals on this domain insulated
+        * from CPU frequency changes caused by DVFS. The firmware sets
+        * both PLL0 and PLL1 to the same frequency so, there should not
+        * be any noticible change even in non-DVFS use cases.
+        */
+       da850_set_async3_src(1);
 }