diff options
Diffstat (limited to 'arch/arm/mach-s3c2440')
-rw-r--r-- | arch/arm/mach-s3c2440/Kconfig | 13 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/irq.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-anubis.c | 29 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-at2440evb.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-mini2440.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-osiris-dvs.c | 194 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-osiris.c | 47 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-rx3715.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-smdk2440.c | 2 |
10 files changed, 286 insertions, 29 deletions
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index ce7bfe4dde22..80879358eb2f 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -51,6 +51,19 @@ config MACH_OSIRIS Say Y here if you are using the Simtec IM2440D20 module, also known as the Osiris. +config MACH_OSIRIS_DVS + tristate "Simtec IM2440D20 (OSIRIS) Dynamic Voltage Scaling driver" + depends on MACH_OSIRIS + select TPS65010 + help + Say Y/M here if you want to have dynamic voltage scaling support + on the Simtec IM2440D20 (OSIRIS) module via the TPS65011. + + The DVS driver alters the voltage supplied to the ARM core + depending on the frequency it is running at. The driver itself + does not do any of the frequency alteration, which is left up + to the cpufreq driver. + config MACH_RX3715 bool "HP iPAQ rx3715" select CPU_S3C2440 diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile index bfadcf684a2a..5f3224531885 100644 --- a/arch/arm/mach-s3c2440/Makefile +++ b/arch/arm/mach-s3c2440/Makefile @@ -23,3 +23,7 @@ obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o + +# extra machine support + +obj-$(CONFIG_MACH_OSIRIS_DVS) += mach-osiris-dvs.o diff --git a/arch/arm/mach-s3c2440/irq.c b/arch/arm/mach-s3c2440/irq.c index 63c5ab65727f..0c049b95c378 100644 --- a/arch/arm/mach-s3c2440/irq.c +++ b/arch/arm/mach-s3c2440/irq.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2440/irq.c * - * Copyright (c) 2003,2004 Simtec Electronics + * Copyright (c) 2003-2004 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * * This program is free software; you can redistribute it and/or modify diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index 68f3870991bf..62a4c3eba97f 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2440/mach-anubis.c * - * Copyright (c) 2003-2005,2008 Simtec Electronics + * Copyright 2003-2009 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks <ben@simtec.co.uk> * @@ -53,8 +53,9 @@ #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <plat/audio-simtec.h> -#define COPYRIGHT ", (c) 2005 Simtec Electronics" +#define COPYRIGHT ", Copyright 2005-2009 Simtec Electronics" static struct map_desc anubis_iodesc[] __initdata = { /* ISA IO areas */ @@ -138,7 +139,7 @@ static int external_map[] = { 2 }; static int chip0_map[] = { 0 }; static int chip1_map[] = { 1 }; -static struct mtd_partition anubis_default_nand_part[] = { +static struct mtd_partition __initdata anubis_default_nand_part[] = { [0] = { .name = "Boot Agent", .size = SZ_16K, @@ -161,7 +162,7 @@ static struct mtd_partition anubis_default_nand_part[] = { } }; -static struct mtd_partition anubis_default_nand_part_large[] = { +static struct mtd_partition __initdata anubis_default_nand_part_large[] = { [0] = { .name = "Boot Agent", .size = SZ_128K, @@ -191,7 +192,7 @@ static struct mtd_partition anubis_default_nand_part_large[] = { * socket. */ -static struct s3c2410_nand_set anubis_nand_sets[] = { +static struct s3c2410_nand_set __initdata anubis_nand_sets[] = { [1] = { .name = "External", .nr_chips = 1, @@ -233,7 +234,7 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot) __raw_writeb(tmp, ANUBIS_VA_CTRL1); } -static struct s3c2410_platform_nand anubis_nand_info = { +static struct s3c2410_platform_nand __initdata anubis_nand_info = { .tacls = 25, .twrph0 = 55, .twrph1 = 40, @@ -437,6 +438,17 @@ static struct i2c_board_info anubis_i2c_devs[] __initdata = { } }; +/* Audio setup */ +static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { + .have_mic = 1, + .have_lout = 1, + .output_cdclk = 1, + .use_mpllin = 1, + .amp_gpio = S3C2410_GPB(2), + .amp_gain[0] = S3C2410_GPD(10), + .amp_gain[1] = S3C2410_GPD(11), +}; + static void __init anubis_map_io(void) { /* initialise the clocks */ @@ -454,8 +466,6 @@ static void __init anubis_map_io(void) s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks)); - s3c_device_nand.dev.platform_data = &anubis_nand_info; - s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); s3c24xx_init_clocks(0); s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); @@ -476,6 +486,9 @@ static void __init anubis_map_io(void) static void __init anubis_init(void) { s3c_i2c0_set_platdata(NULL); + s3c_nand_set_platdata(&anubis_nand_info); + simtec_audio_add(NULL, false, &anubis_audio); + platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices)); i2c_register_board_info(0, anubis_i2c_devs, diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c index dfc7010935da..aa69290e04c6 100644 --- a/arch/arm/mach-s3c2440/mach-at2440evb.c +++ b/arch/arm/mach-s3c2440/mach-at2440evb.c @@ -96,7 +96,7 @@ static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = { /* NAND Flash on AT2440EVB board */ -static struct mtd_partition at2440evb_default_nand_part[] = { +static struct mtd_partition __initdata at2440evb_default_nand_part[] = { [0] = { .name = "Boot Agent", .size = SZ_256K, @@ -114,7 +114,7 @@ static struct mtd_partition at2440evb_default_nand_part[] = { }, }; -static struct s3c2410_nand_set at2440evb_nand_sets[] = { +static struct s3c2410_nand_set __initdata at2440evb_nand_sets[] = { [0] = { .name = "nand", .nr_chips = 1, @@ -123,7 +123,7 @@ static struct s3c2410_nand_set at2440evb_nand_sets[] = { }, }; -static struct s3c2410_platform_nand at2440evb_nand_info = { +static struct s3c2410_platform_nand __initdata at2440evb_nand_info = { .tacls = 25, .twrph0 = 55, .twrph1 = 40, @@ -216,8 +216,6 @@ static struct platform_device *at2440evb_devices[] __initdata = { static void __init at2440evb_map_io(void) { - s3c_device_nand.dev.platform_data = &at2440evb_nand_info; - s3c_device_sdi.name = "s3c2440-sdi"; s3c_device_sdi.dev.platform_data = &at2440evb_mci_pdata; s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc)); @@ -228,6 +226,7 @@ static void __init at2440evb_map_io(void) static void __init at2440evb_init(void) { s3c24xx_fb_set_platdata(&at2440evb_fb_info); + s3c_nand_set_platdata(&at2440evb_nand_info); s3c_i2c0_set_platdata(NULL); platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices)); diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index 1c3382fefdd2..547d4fc99131 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -532,7 +532,6 @@ static void __init mini2440_map_io(void) s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs)); - s3c_device_nand.dev.platform_data = &mini2440_nand_info; s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg; } @@ -677,8 +676,11 @@ static void __init mini2440_init(void) printk("\n"); s3c24xx_fb_set_platdata(&mini2440_fb_info); } + s3c24xx_udc_set_platdata(&mini2440_udc_cfg); + s3c_nand_set_platdata(&mini2440_nand_info); s3c_i2c0_set_platdata(NULL); + i2c_register_board_info(0, mini2440_i2c_devs, ARRAY_SIZE(mini2440_i2c_devs)); diff --git a/arch/arm/mach-s3c2440/mach-osiris-dvs.c b/arch/arm/mach-s3c2440/mach-osiris-dvs.c new file mode 100644 index 000000000000..ad2792dfbee1 --- /dev/null +++ b/arch/arm/mach-s3c2440/mach-osiris-dvs.c @@ -0,0 +1,194 @@ +/* linux/arch/arm/mach-s3c2440/mach-osiris-dvs.c + * + * Copyright (c) 2009 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * Simtec Osiris Dynamic Voltage Scaling support. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/cpufreq.h> +#include <linux/gpio.h> + +#include <linux/i2c/tps65010.h> + +#include <plat/cpu-freq.h> + +#define OSIRIS_GPIO_DVS S3C2410_GPB(5) + +static bool dvs_en; + +static void osiris_dvs_tps_setdvs(bool on) +{ + unsigned vregs1 = 0, vdcdc2 = 0; + + if (!on) { + vdcdc2 = TPS_VCORE_DISCH | TPS_LP_COREOFF; + vregs1 = TPS_LDO1_OFF; /* turn off in low-power mode */ + } + + dvs_en = on; + vdcdc2 |= TPS_VCORE_1_3V | TPS_VCORE_LP_1_0V; + vregs1 |= TPS_LDO2_ENABLE | TPS_LDO1_ENABLE; + + tps65010_config_vregs1(vregs1); + tps65010_config_vdcdc2(vdcdc2); +} + +static bool is_dvs(struct s3c_freq *f) +{ + /* at the moment, we assume ARMCLK = HCLK => DVS */ + return f->armclk == f->hclk; +} + +/* keep track of current state */ +static bool cur_dvs = false; + +static int osiris_dvs_notify(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *cf = data; + struct s3c_cpufreq_freqs *freqs = to_s3c_cpufreq(cf); + bool old_dvs = is_dvs(&freqs->old); + bool new_dvs = is_dvs(&freqs->new); + int ret = 0; + + if (!dvs_en) + return 0; + + printk(KERN_DEBUG "%s: old %ld,%ld new %ld,%ld\n", __func__, + freqs->old.armclk, freqs->old.hclk, + freqs->new.armclk, freqs->new.hclk); + + switch (val) { + case CPUFREQ_PRECHANGE: + if (old_dvs & !new_dvs || + cur_dvs & !new_dvs) { + pr_debug("%s: exiting dvs\n", __func__); + cur_dvs = false; + gpio_set_value(OSIRIS_GPIO_DVS, 1); + } + break; + case CPUFREQ_POSTCHANGE: + if (!old_dvs & new_dvs || + !cur_dvs & new_dvs) { + pr_debug("entering dvs\n"); + cur_dvs = true; + gpio_set_value(OSIRIS_GPIO_DVS, 0); + } + break; + } + + return ret; +} + +static struct notifier_block osiris_dvs_nb = { + .notifier_call = osiris_dvs_notify, +}; + +static int __devinit osiris_dvs_probe(struct platform_device *pdev) +{ + int ret; + + dev_info(&pdev->dev, "initialising\n"); + + ret = gpio_request(OSIRIS_GPIO_DVS, "osiris-dvs"); + if (ret) { + dev_err(&pdev->dev, "cannot claim gpio\n"); + goto err_nogpio; + } + + /* start with dvs disabled */ + gpio_direction_output(OSIRIS_GPIO_DVS, 1); + + ret = cpufreq_register_notifier(&osiris_dvs_nb, + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { + dev_err(&pdev->dev, "failed to register with cpufreq\n"); + goto err_nofreq; + } + + osiris_dvs_tps_setdvs(true); + + return 0; + +err_nofreq: + gpio_free(OSIRIS_GPIO_DVS); + +err_nogpio: + return ret; +} + +static int __devexit osiris_dvs_remove(struct platform_device *pdev) +{ + dev_info(&pdev->dev, "exiting\n"); + + /* disable any current dvs */ + gpio_set_value(OSIRIS_GPIO_DVS, 1); + osiris_dvs_tps_setdvs(false); + + cpufreq_unregister_notifier(&osiris_dvs_nb, + CPUFREQ_TRANSITION_NOTIFIER); + + gpio_free(OSIRIS_GPIO_DVS); + + return 0; +} + +/* the CONFIG_PM block is so small, it isn't worth actaully compiling it + * out if the configuration isn't set. */ + +static int osiris_dvs_suspend(struct device *dev) +{ + gpio_set_value(OSIRIS_GPIO_DVS, 1); + osiris_dvs_tps_setdvs(false); + cur_dvs = false; + + return 0; +} + +static int osiris_dvs_resume(struct device *dev) +{ + osiris_dvs_tps_setdvs(true); + return 0; +} + +static const struct dev_pm_ops osiris_dvs_pm = { + .suspend = osiris_dvs_suspend, + .resume = osiris_dvs_resume, +}; + +static struct platform_driver osiris_dvs_driver = { + .probe = osiris_dvs_probe, + .remove = __devexit_p(osiris_dvs_remove), + .driver = { + .name = "osiris-dvs", + .owner = THIS_MODULE, + .pm = &osiris_dvs_pm, + }, +}; + +static int __init osiris_dvs_init(void) +{ + return platform_driver_register(&osiris_dvs_driver); +} + +static void __exit osiris_dvs_exit(void) +{ + platform_driver_unregister(&osiris_dvs_driver); +} + +module_init(osiris_dvs_init); +module_exit(osiris_dvs_exit); + +MODULE_DESCRIPTION("Simtec OSIRIS DVS support"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:osiris-dvs"); diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 2105a41281a4..015dfb2a80da 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2440/mach-osiris.c * - * Copyright (c) 2005,2008 Simtec Electronics + * Copyright (c) 2005-2008 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks <ben@simtec.co.uk> * @@ -23,6 +23,8 @@ #include <linux/i2c.h> #include <linux/io.h> +#include <linux/i2c/tps65010.h> + #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -148,7 +150,7 @@ static int external_map[] = { 2 }; static int chip0_map[] = { 0 }; static int chip1_map[] = { 1 }; -static struct mtd_partition osiris_default_nand_part[] = { +static struct mtd_partition __initdata osiris_default_nand_part[] = { [0] = { .name = "Boot Agent", .size = SZ_16K, @@ -171,7 +173,7 @@ static struct mtd_partition osiris_default_nand_part[] = { } }; -static struct mtd_partition osiris_default_nand_part_large[] = { +static struct mtd_partition __initdata osiris_default_nand_part_large[] = { [0] = { .name = "Boot Agent", .size = SZ_128K, @@ -201,7 +203,7 @@ static struct mtd_partition osiris_default_nand_part_large[] = { * socket. */ -static struct s3c2410_nand_set osiris_nand_sets[] = { +static struct s3c2410_nand_set __initdata osiris_nand_sets[] = { [1] = { .name = "External", .nr_chips = 1, @@ -243,7 +245,7 @@ static void osiris_nand_select(struct s3c2410_nand_set *set, int slot) __raw_writeb(tmp, OSIRIS_VA_CTRL0); } -static struct s3c2410_platform_nand osiris_nand_info = { +static struct s3c2410_platform_nand __initdata osiris_nand_info = { .tacls = 25, .twrph0 = 60, .twrph1 = 60, @@ -326,12 +328,44 @@ static struct sys_device osiris_pm_sysdev = { .cls = &osiris_pm_sysclass, }; +/* Link for DVS driver to TPS65011 */ + +static void osiris_tps_release(struct device *dev) +{ + /* static device, do not need to release anything */ +} + +static struct platform_device osiris_tps_device = { + .name = "osiris-dvs", + .id = -1, + .dev.release = osiris_tps_release, +}; + +static int osiris_tps_setup(struct i2c_client *client, void *context) +{ + osiris_tps_device.dev.parent = &client->dev; + return platform_device_register(&osiris_tps_device); +} + +static int osiris_tps_remove(struct i2c_client *client, void *context) +{ + platform_device_unregister(&osiris_tps_device); + return 0; +} + +static struct tps65010_board osiris_tps_board = { + .base = -1, /* GPIO can go anywhere at the moment */ + .setup = osiris_tps_setup, + .teardown = osiris_tps_remove, +}; + /* I2C devices fitted. */ static struct i2c_board_info osiris_i2c_devs[] __initdata = { { I2C_BOARD_INFO("tps65011", 0x48), .irq = IRQ_EINT20, + .platform_data = &osiris_tps_board, }, }; @@ -377,8 +411,6 @@ static void __init osiris_map_io(void) s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks)); - s3c_device_nand.dev.platform_data = &osiris_nand_info; - s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); s3c24xx_init_clocks(0); s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); @@ -408,6 +440,7 @@ static void __init osiris_init(void) sysdev_register(&osiris_pm_sysdev); s3c_i2c0_set_platdata(NULL); + s3c_nand_set_platdata(&osiris_nand_info); s3c_cpufreq_setboard(&osiris_cpufreq); diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index bc8d8d1ebd1a..a952a13afb1f 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2440/mach-rx3715.c * - * Copyright (c) 2003,2004 Simtec Electronics + * Copyright (c) 2003-2004 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * * http://www.handhelds.org/projects/rx3715.html @@ -149,7 +149,7 @@ static struct s3c2410fb_mach_info rx3715_fb_info __initdata = { .gpdup_mask = 0xffffffff, }; -static struct mtd_partition rx3715_nand_part[] = { +static struct mtd_partition __initdata rx3715_nand_part[] = { [0] = { .name = "Whole Flash", .offset = 0, @@ -158,7 +158,7 @@ static struct mtd_partition rx3715_nand_part[] = { } }; -static struct s3c2410_nand_set rx3715_nand_sets[] = { +static struct s3c2410_nand_set __initdata rx3715_nand_sets[] = { [0] = { .name = "Internal", .nr_chips = 1, @@ -167,7 +167,7 @@ static struct s3c2410_nand_set rx3715_nand_sets[] = { }, }; -static struct s3c2410_platform_nand rx3715_nand_info = { +static struct s3c2410_platform_nand __initdata rx3715_nand_info = { .tacls = 25, .twrph0 = 50, .twrph1 = 15, @@ -186,8 +186,6 @@ static struct platform_device *rx3715_devices[] __initdata = { static void __init rx3715_map_io(void) { - s3c_device_nand.dev.platform_data = &rx3715_nand_info; - s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); s3c24xx_init_clocks(16934000); s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs)); @@ -205,6 +203,7 @@ static void __init rx3715_init_machine(void) #endif s3c_pm_init(); + s3c_nand_set_platdata(&rx3715_nand_info); s3c24xx_fb_set_platdata(&rx3715_fb_info); platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices)); } diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c index db6eafbd4d90..ec13e748ccc5 100644 --- a/arch/arm/mach-s3c2440/mach-smdk2440.c +++ b/arch/arm/mach-s3c2440/mach-smdk2440.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2440/mach-smdk2440.c * - * Copyright (c) 2004,2005 Simtec Electronics + * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * * http://www.fluff.org/ben/smdk2440/ |