[s3c24xx] glamo: Implement gpiolib for the glamo. Get rid of glamo-spi-gpio and
[openwrt/svn-archive/archive.git] / target / linux / s3c24xx / files-2.6.30 / drivers / mfd / glamo / glamo-core.c
index 1a6adcdeae62f901739d5010d1c2fb7d22f5af1b..077a7a839c196115358d772d1779f5b8a20b3c55 100644 (file)
@@ -43,9 +43,7 @@
 
 #include <asm/div64.h>
 
-#ifdef CONFIG_PM
 #include <linux/pm.h>
-#endif
 
 #include "glamo-regs.h"
 #include "glamo-core.h"
@@ -76,6 +74,7 @@ struct reg_range {
        char *name;
        char dump;
 };
+
 struct reg_range reg_range[] = {
        { 0x0000, 0x76,         "General",      1 },
        { 0x0200, 0x18,         "Host Bus",     1 },
@@ -86,13 +85,13 @@ struct reg_range reg_range[] = {
 /*             { 0x0c00, 0xcc,         "MPEG",         0 }, */
        { 0x1100, 0xb2,         "LCD 1",        1 },
        { 0x1200, 0x64,         "LCD 2",        1 },
-       { 0x1400, 0x40,         "MMC",          1 },
+       { 0x1400, 0x42,         "MMC",          1 },
 /*             { 0x1500, 0x080,        "MPU 0",        0 },
        { 0x1580, 0x080,        "MPU 1",        0 },
        { 0x1600, 0x080,        "Cmd Queue",    0 },
-       { 0x1680, 0x080,        "RISC CPU",     0 },
+       { 0x1680, 0x080,        "RISC CPU",     0 },*/
        { 0x1700, 0x400,        "2D Unit",      0 },
-       { 0x1b00, 0x900,        "3D Unit",      0 }, */
+/*     { 0x1b00, 0x900,        "3D Unit",      0 }, */
 };
 
 static inline void __reg_write(struct glamo_core *glamo,
@@ -180,7 +179,7 @@ static struct resource glamo_mmc_resources[] = {
 enum glamo_cells {
        GLAMO_CELL_FB,
        GLAMO_CELL_MMC,
-       GLAMO_CELL_SPI_GPIO
+       GLAMO_CELL_GPIO,
 };
 
 static struct mfd_cell glamo_cells[] = {
@@ -194,8 +193,8 @@ static struct mfd_cell glamo_cells[] = {
                .num_resources = ARRAY_SIZE(glamo_mmc_resources),
                .resources = glamo_mmc_resources,
        },
-       [GLAMO_CELL_SPI_GPIO] = {
-               .name = "glamo-spi-gpio",
+       [GLAMO_CELL_GPIO] = {
+               .name = "glamo-gpio",
        },
 };
 
@@ -382,7 +381,8 @@ int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
                                   GLAMO_CLOCK_MMC_EN_M9CLK |
                                   GLAMO_CLOCK_MMC_EN_TCLK |
                                   GLAMO_CLOCK_MMC_DG_M9CLK |
-                                  GLAMO_CLOCK_MMC_DG_TCLK, 0xffff);
+                                  GLAMO_CLOCK_MMC_DG_TCLK,
+                                  0xffff);
                /* enable the TCLK divider clk input */
                __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
                                                 GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
@@ -478,7 +478,7 @@ int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
                break;
        case GLAMO_ENGINE_2D:
                        __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
-                                          GLAMO_CLOCK_2D_EN_M7CLK |
+                                                          GLAMO_CLOCK_2D_EN_M7CLK |
                                                           GLAMO_CLOCK_2D_EN_GCLK |
                                                           GLAMO_CLOCK_2D_DG_M7CLK |
                                                           GLAMO_CLOCK_2D_DG_GCLK,
@@ -544,7 +544,40 @@ u_int16_t glamo_engine_clkreg_get(struct glamo_core *glamo,
 }
 EXPORT_SYMBOL_GPL(glamo_engine_clkreg_get);
 
-struct glamo_script reset_regs[] = {
+static const struct glamo_script engine_div_regs[__NUM_GLAMO_ENGINES] = {
+       [GLAMO_ENGINE_LCD] = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_DCLK},
+       [GLAMO_ENGINE_MMC] = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_TCLK},
+       [GLAMO_ENGINE_2D]  = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_GCLK},
+};
+
+void glamo_engine_div_enable(struct glamo_core *glamo, enum glamo_engine engine)
+{
+       uint16_t reg = engine_div_regs[engine].reg;
+       uint16_t bit = engine_div_regs[engine].val;
+       uint16_t val;
+
+       spin_lock(&glamo->lock);
+       val = __reg_read(glamo, reg);
+       __reg_write(glamo, reg, val | bit);
+       spin_unlock(&glamo->lock);
+       mdelay(5);
+}
+EXPORT_SYMBOL_GPL(glamo_engine_div_enable);
+
+void glamo_engine_div_disable(struct glamo_core *glamo, enum glamo_engine engine)
+{
+       uint16_t reg = engine_div_regs[engine].reg;
+       uint16_t bit = engine_div_regs[engine].val;
+       uint16_t val;
+
+       spin_lock(&glamo->lock);
+       val = __reg_read(glamo, reg);
+       __reg_write(glamo, reg, val & ~bit);
+       spin_unlock(&glamo->lock);
+}
+EXPORT_SYMBOL_GPL(glamo_engine_div_disable);
+
+static const struct glamo_script reset_regs[] = {
        [GLAMO_ENGINE_LCD] = {
                GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET
        },
@@ -572,48 +605,28 @@ struct glamo_script reset_regs[] = {
 
 void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
 {
-       struct glamo_script *rst;
+       uint16_t reg = reset_regs[engine].reg;
+       uint16_t val = reset_regs[engine].val;
 
        if (engine >= ARRAY_SIZE(reset_regs)) {
                dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine);
                return;
        }
 
-       rst = &reset_regs[engine];
 
        spin_lock(&glamo->lock);
-       __reg_set_bit(glamo, rst->reg, rst->val);
-       __reg_clear_bit(glamo, rst->reg, rst->val);
+       __reg_set_bit(glamo, reg, val);
+       __reg_clear_bit(glamo, reg, val);
        spin_unlock(&glamo->lock);
 }
 EXPORT_SYMBOL_GPL(glamo_engine_reset);
 
-void glamo_lcm_reset(struct platform_device *pdev, int level)
-{
-       struct glamo_core *glamo = dev_get_drvdata(&pdev->dev);
-       if (!glamo)
-               return;
-
-       glamo_gpio_setpin(glamo, GLAMO_GPIO4, level);
-       glamo_gpio_cfgpin(glamo, GLAMO_GPIO4_OUTPUT);
-}
-EXPORT_SYMBOL_GPL(glamo_lcm_reset);
-
-enum glamo_pll {
-       GLAMO_PLL1,
-       GLAMO_PLL2,
-};
-
-static int glamo_pll_rate(struct glamo_core *glamo,
+int glamo_pll_rate(struct glamo_core *glamo,
                          enum glamo_pll pll)
 {
        u_int16_t reg;
-       unsigned int div = 512;
        unsigned int osci = glamo->pdata->osci_clock_rate;
 
-       if (osci == 32768)
-               div = 1;
-
        switch (pll) {
        case GLAMO_PLL1:
                reg = __reg_read(glamo, GLAMO_REG_PLL_GEN1);
@@ -624,18 +637,19 @@ static int glamo_pll_rate(struct glamo_core *glamo,
        default:
                return -EINVAL;
        }
-       return (osci/div)*reg;
+       return osci*reg;
 }
+EXPORT_SYMBOL_GPL(glamo_pll_rate);
 
 int glamo_engine_reclock(struct glamo_core *glamo,
                         enum glamo_engine engine,
-                        int ps)
+                        int hz)
 {
-       int pll, khz;
-       u_int16_t reg, mask, val = 0;
+       int pll;
+       u_int16_t reg, mask, div;
 
-       if (!ps)
-               return 0;
+       if (!hz)
+               return -EINVAL;
 
        switch (engine) {
        case GLAMO_ENGINE_LCD:
@@ -643,6 +657,11 @@ int glamo_engine_reclock(struct glamo_core *glamo,
                reg = GLAMO_REG_CLOCK_GEN7;
                mask = 0xff;
                break;
+       case GLAMO_ENGINE_MMC:
+               pll = GLAMO_PLL1;
+               reg = GLAMO_REG_CLOCK_GEN8;
+               mask = 0xff;
+               break;
        default:
                dev_warn(&glamo->pdev->dev,
                         "reclock of engine 0x%x not supported\n", engine);
@@ -651,23 +670,22 @@ int glamo_engine_reclock(struct glamo_core *glamo,
        }
 
        pll = glamo_pll_rate(glamo, pll);
-       khz = 1000000000UL / ps;
 
-       if (khz)
-               val = (pll / khz) / 1000;
+       div = pll / hz;
+
+       if (div != 0 && pll / div <= hz)
+               --div;
+
+       if (div > mask)
+               div = mask;
 
        dev_dbg(&glamo->pdev->dev,
-                       "PLL %d, kHZ %d, div %d\n", pll, khz, val);
+                       "PLL %d, kHZ %d, div %d\n", pll, hz / 1000, div);
 
-       if (val) {
-               val--;
-               reg_set_bit_mask(glamo, reg, mask, val);
-               mdelay(5); /* wait some time to stabilize */
+       reg_set_bit_mask(glamo, reg, mask, div);
+       mdelay(5); /* wait some time to stabilize */
 
-               return 0;
-       } else {
-               return -EINVAL;
-       }
+       return pll / (div + 1);
 }
 EXPORT_SYMBOL_GPL(glamo_engine_reclock);
 
@@ -675,14 +693,13 @@ EXPORT_SYMBOL_GPL(glamo_engine_reclock);
  * script support
  ***********************************************************************/
 
-int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
+int glamo_run_script(struct glamo_core *glamo, const struct glamo_script *script,
                     int len, int may_sleep)
 {
        int i;
+    const struct glamo_script *line = script;
 
-       for (i = 0; i < len; i++) {
-               struct glamo_script *line = &script[i];
-
+       for (i = 0; i < len; ++i, ++line) {
                switch (line->reg) {
                case 0xffff:
                        return 0;
@@ -746,7 +763,7 @@ int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
 }
 EXPORT_SYMBOL(glamo_run_script);
 
-static struct glamo_script glamo_init_script[] = {
+static const struct glamo_script glamo_init_script[] = {
        { GLAMO_REG_CLOCK_HOST,         0x1000 },
                { 0xfffe, 2 },
        { GLAMO_REG_CLOCK_MEMORY,       0x1000 },
@@ -831,11 +848,6 @@ static struct glamo_script glamo_init_script[] = {
        { GLAMO_REG_MEM_DRAM1,          0xe100 },
        { GLAMO_REG_MEM_DRAM2,          0x01d6 },
        { GLAMO_REG_CLOCK_MEMORY,       0x000b },
-       { GLAMO_REG_GPIO_GEN1,          0x000f },
-       { GLAMO_REG_GPIO_GEN2,          0x111e },
-       { GLAMO_REG_GPIO_GEN3,          0xccc3 },
-       { GLAMO_REG_GPIO_GEN4,          0x111e },
-       { GLAMO_REG_GPIO_GEN5,          0x000f },
 };
 #if 0
 static struct glamo_script glamo_resume_script[] = {
@@ -1186,12 +1198,6 @@ static int __init glamo_probe(struct platform_device *pdev)
        glamo_cells[GLAMO_CELL_FB].platform_data = glamo->pdata->fb_data;
        glamo_cells[GLAMO_CELL_FB].data_size = sizeof(struct glamo_fb_platform_data);
 
-       glamo->pdata->spigpio_data->core = glamo;
-       glamo_cells[GLAMO_CELL_SPI_GPIO].platform_data =
-               glamo->pdata->spigpio_data;
-       glamo_cells[GLAMO_CELL_SPI_GPIO].data_size =
-               sizeof(struct glamo_spigpio_platform_data);
-
        mfd_add_devices(&pdev->dev, pdev->id, glamo_cells,
                              ARRAY_SIZE(glamo_cells),
                                                  glamo->mem, 0);
@@ -1251,37 +1257,41 @@ static int glamo_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
-static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
+static int glamo_suspend(struct device *dev)
 {
-       struct glamo_core *glamo = dev_get_drvdata(&pdev->dev);
+       struct glamo_core *glamo = dev_get_drvdata(dev);
        glamo->suspending = 1;
        glamo_power(glamo, GLAMO_POWER_SUSPEND);
 
        return 0;
 }
 
-static int glamo_resume(struct platform_device *pdev)
+static int glamo_resume(struct device *dev)
 {
-       struct glamo_core *glamo = dev_get_drvdata(&pdev->dev);
+       struct glamo_core *glamo = dev_get_drvdata(dev);
        glamo_power(glamo, GLAMO_POWER_ON);
        glamo->suspending = 0;
-
        return 0;
 }
 
+static struct dev_pm_ops glamo_pm_ops = {
+       .suspend = glamo_suspend,
+       .resume  = glamo_resume,
+};
+
+#define GLAMO_PM_OPS (&glamo_pm_ops)
+
 #else
-#define glamo_suspend NULL
-#define glamo_resume  NULL
+#define GLAMO_PM_OPS NULL
 #endif
 
 static struct platform_driver glamo_driver = {
        .probe          = glamo_probe,
        .remove         = glamo_remove,
-       .suspend        = glamo_suspend,
-       .resume = glamo_resume,
        .driver         = {
                .name   = "glamo3362",
                .owner  = THIS_MODULE,
+               .pm     = GLAMO_PM_OPS,
        },
 };