Index: asic3_base.c =================================================================== RCS file: /cvs/linux/kernel26/drivers/soc/asic3_base.c,v retrieving revision 1.31 diff -u -r1.31 asic3_base.c --- asic3_base.c 22 Dec 2006 00:05:03 -0000 1.31 +++ asic3_base.c 22 Dec 2006 12:39:03 -0000 @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -253,6 +255,119 @@ } EXPORT_SYMBOL (asic3_set_clock_cdex); +static void +asic3_clock_cdex_enable (struct clk *clk) +{ + struct asic3_data *asic = clk->parent->priv; + unsigned long flags, val; + + local_irq_save (flags); + + val = __asic3_read_register (asic, _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX); + val |= clk->priv; + __asic3_write_register (asic, _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX, val); + + local_irq_restore (flags); +} + +static void +asic3_clock_cdex_disable (struct clk *clk) +{ + struct asic3_data *asic = clk->parent->priv; + unsigned long flags, val; + + local_irq_save (flags); + + val = __asic3_read_register (asic, _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX); + val &= ~clk->priv; + __asic3_write_register (asic, _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_CDEX, val); + + local_irq_restore (flags); +} + +/* base clocks */ + +static struct clk clk_g = { + .name = "gclk", + .rate = 0, + .parent = NULL, +}; + +/* clock definitions */ + +static struct clk asic3_clocks[] = { + { + .name = "spi" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_SPI, + }, + { + .name = "ds1wm" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_OWM, + }, + { + .name = "pwm0" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_pwm0, + }, + { + .name = "pwm1" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_PWM1, + }, + { + .name = "led0" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_LED0, + }, + { + .name = "led1" + .parent = &g_clk, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_LED1, + }, + { + .name = "led2" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_LED2, + }, + { + .name = "smbus" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_SMBUS, + }, + { + .name = "ex0" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_EX0, + }, + { + .name = "ex1" + .parent = &clk_g, + .enable = asic3_clock_cdex_enable, + .disable = asic3_clock_cdex_disable, + .priv = CLOCK_CDEX_EX1, + }, +}; + void asic3_set_extcf_select (struct device *dev, unsigned long bits, unsigned long val) { @@ -618,7 +733,7 @@ memset (sdev, 0, sizeof (*sdev)); if (asic3_pdata->tmio_mmc_hwconfig) { - memcpy(mmc_config, asic3_pdata->tmio_mmc_hwconfig, sizeof (*mmc_config)); + memcpy(mmc_config, asic3_pdata->tmio_mmc_hwconfig, sizeof (*mmc_config)); } else { memset(mmc_config, 0, sizeof (*mmc_config)); } @@ -678,6 +793,7 @@ struct asic3_data *asic; struct device *dev = &pdev->dev; unsigned long clksel; + int i, rc; asic = kmalloc (sizeof (struct asic3_data), GFP_KERNEL); if (!asic) @@ -704,6 +820,20 @@ clksel = 0; __asic3_write_register (asic, _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_SEL, clksel); + /* Register ASIC3's clocks. */ +// clk_g.rate = hamcop_gclk(hamcop); + clk_g.priv = asic; + + if (clk_register(&clk_g) < 0) + printk(KERN_ERR "failed to register ASIC3 gclk\n"); + + for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++) { + rc = clk_register(&asic3_clocks[i]); + if (rc < 0) + printk(KERN_ERR "Failed to register clock %s (%d)\n", + asic3_clocks[i].name, rc); + } + __asic3_write_register (asic, _IPAQ_ASIC3_GPIO_A_Base + _IPAQ_ASIC3_GPIO_Mask, 0xffff); __asic3_write_register (asic, _IPAQ_ASIC3_GPIO_B_Base + _IPAQ_ASIC3_GPIO_Mask, 0xffff); __asic3_write_register (asic, _IPAQ_ASIC3_GPIO_C_Base + _IPAQ_ASIC3_GPIO_Mask, 0xffff); @@ -818,9 +948,9 @@ { struct asic3_platform_data *pdata = pdev->dev.platform_data; struct asic3_data *asic = platform_get_drvdata(pdev); + int i; if (pdata && pdata->child_platform_devs && pdata->num_child_platform_devs != 0) { - int i; for (i = 0; i < pdata->num_child_platform_devs; i++) { platform_device_unregister (pdata->child_platform_devs[i]); } @@ -843,6 +973,10 @@ if (asic->mmc_dev) asic3_unregister_mmc(&pdev->dev); + + for (i = 0; i < ARRAY_SIZE(asic3_clocks); i++) + clk_unregister(&asic3_clocks[i]); + clk_unregister(&clk_g); __asic3_write_register (asic, _IPAQ_ASIC3_CLOCK_Base + _IPAQ_ASIC3_CLOCK_SEL, 0); __asic3_write_register (asic, _IPAQ_ASIC3_INTR_Base + _IPAQ_ASIC3_INTR_IntMask, 0);