diff options
author | Frank Li <Frank.Li@freescale.com> | 2010-04-13 14:11:52 +0800 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-25 11:20:24 +0200 |
commit | 81d98ca18cbc3d66200b5d28859b28869df7ad7e (patch) | |
tree | 0664d3819937d5e7919c55daad984775bd890294 | |
parent | 1959540617e21d8e16db725d2fd0042eced9393e (diff) |
ENGR00122477-2 iMX23 Enable persistent bit support
enable persistent bit support
Signed-off-by: Frank Li <Frank.Li@freescale.com>
Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
-rw-r--r-- | arch/arm/mach-mx23/device.c | 115 | ||||
-rw-r--r-- | arch/arm/plat-mxs/device.c | 19 | ||||
-rw-r--r-- | arch/arm/plat-mxs/include/mach/device.h | 12 | ||||
-rw-r--r-- | drivers/misc/Kconfig | 5 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/mxs-persistent.c | 117 |
6 files changed, 211 insertions, 58 deletions
diff --git a/arch/arm/mach-mx23/device.c b/arch/arm/mach-mx23/device.c index 33c4d7d5c845..38ad3f77181f 100644 --- a/arch/arm/mach-mx23/device.c +++ b/arch/arm/mach-mx23/device.c @@ -705,12 +705,13 @@ static void mx23_init_battery(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-battery", 0); - if (pdev) { - pdev->resource = battery_resource, - pdev->num_resources = ARRAY_SIZE(battery_resource), - pdev->dev.platform_data = &battery_data; - mxs_add_device(pdev, 3); - } + if (pdev == NULL || IS_ERR(pdev)) + return; + pdev->resource = battery_resource, + pdev->num_resources = ARRAY_SIZE(battery_resource), + pdev->dev.platform_data = &battery_data; + mxs_add_device(pdev, 3); + } #else static void mx23_init_battery(void) @@ -733,6 +734,107 @@ static inline mx23_init_spdif(void) } #endif +#if defined(CONFIG_MXS_PERSISTENT) +static const struct mxs_persistent_bit_config +mx23_persistent_bit_config[] = { + { .reg = 0, .start = 0, .width = 1, + .name = "CLOCKSOURCE" }, + { .reg = 0, .start = 1, .width = 1, + .name = "ALARM_WAKE_EN" }, + { .reg = 0, .start = 2, .width = 1, + .name = "ALARM_EN" }, + { .reg = 0, .start = 3, .width = 1, + .name = "CLK_SECS" }, + { .reg = 0, .start = 4, .width = 1, + .name = "XTAL24MHZ_PWRUP" }, + { .reg = 0, .start = 5, .width = 1, + .name = "XTAL32MHZ_PWRUP" }, + { .reg = 0, .start = 6, .width = 1, + .name = "XTAL32_FREQ" }, + { .reg = 0, .start = 7, .width = 1, + .name = "ALARM_WAKE" }, + { .reg = 0, .start = 8, .width = 5, + .name = "MSEC_RES" }, + { .reg = 0, .start = 13, .width = 1, + .name = "DISABLE_XTALOK" }, + { .reg = 0, .start = 14, .width = 2, + .name = "LOWERBIAS" }, + { .reg = 0, .start = 16, .width = 1, + .name = "DISABLE_PSWITCH" }, + { .reg = 0, .start = 17, .width = 1, + .name = "AUTO_RESTART" }, + { .reg = 0, .start = 18, .width = 14, + .name = "SPARE_ANALOG" }, + + { .reg = 1, .start = 0, .width = 1, + .name = "FORCE_RECOVERY" }, + { .reg = 1, .start = 1, .width = 1, + .name = "NAND_SECONDARY_BOOT" }, + { .reg = 1, .start = 2, .width = 1, + .name = "NAND_SDK_BLOCK_REWRITE" }, + { .reg = 1, .start = 3, .width = 1, + .name = "SD_SPEED_ENABLE" }, + { .reg = 1, .start = 4, .width = 1, + .name = "SD_INIT_SEQ_1_DISABLE" }, + { .reg = 1, .start = 5, .width = 1, + .name = "SD_CMD0_DISABLE" }, + { .reg = 1, .start = 6, .width = 1, + .name = "SD_INIT_SEQ_2_ENABLE" }, + { .reg = 1, .start = 7, .width = 1, + .name = "OTG_ATL_ROLE_BIT" }, + { .reg = 1, .start = 8, .width = 1, + .name = "OTG_HNP_BIT" }, + { .reg = 1, .start = 9, .width = 1, + .name = "USB_LOW_POWER_MODE" }, + { .reg = 1, .start = 10, .width = 1, + .name = "SKIP_CHECKDISK" }, + { .reg = 1, .start = 11, .width = 1, + .name = "USB_BOOT_PLAYER_MODE" }, + { .reg = 1, .start = 12, .width = 1, + .name = "ENUMERATE_500MA_TWICE" }, + { .reg = 1, .start = 13, .width = 19, + .name = "SPARE_GENERAL" }, + + { .reg = 2, .start = 0, .width = 32, + .name = "SPARE_2" }, + { .reg = 3, .start = 0, .width = 32, + .name = "SPARE_3" }, + { .reg = 4, .start = 0, .width = 32, + .name = "SPARE_4" }, + { .reg = 5, .start = 0, .width = 32, + .name = "SPARE_5" }, +}; + +static struct mxs_platform_persistent_data mx23_persistent_data = { + .bit_config_tab = mx23_persistent_bit_config, + .bit_config_cnt = ARRAY_SIZE(mx23_persistent_bit_config), +}; + +static struct resource mx23_persistent_res[] = { + { + .flags = IORESOURCE_MEM, + .start = RTC_PHYS_ADDR, + .end = RTC_PHYS_ADDR + 0x2000 - 1, + }, +}; + +static void mx23_init_persistent(void) +{ + struct platform_device *pdev; + pdev = mxs_get_device("mxs-persistent", 0); + if (pdev == NULL || IS_ERR(pdev)) + return; + pdev->dev.platform_data = &mx23_persistent_data; + pdev->resource = mx23_persistent_res, + pdev->num_resources = ARRAY_SIZE(mx23_persistent_res), + mxs_add_device(pdev, 3); +} +#else +static void mx23_init_persistent() +{ +} +#endif + int __init mx23_device_init(void) { mx23_init_dma(); @@ -751,6 +853,7 @@ int __init mx23_device_init(void) mx23_init_lcdif(); mx23_init_pxp(); mx23_init_battery(); + mx23_init_persistent(); return 0; } diff --git a/arch/arm/plat-mxs/device.c b/arch/arm/plat-mxs/device.c index 684ffd8e2afa..00180846885b 100644 --- a/arch/arm/plat-mxs/device.c +++ b/arch/arm/plat-mxs/device.c @@ -441,6 +441,16 @@ static struct platform_device busfreq_device = { }, }; +#ifdef CONFIG_MXS_PERSISTENT +static struct platform_device mxs_persistent = { + .name = "mxs-persistent", + .id = 0, + .dev = { + .release = mxs_nop_release, + }, +}; +#endif + static inline void mxs_init_busfreq(void) { (void)platform_device_register(&busfreq_device); @@ -505,6 +515,15 @@ static struct mxs_dev_lookup dev_lookup[] = { .pdev = &mxs_rtc, }, #endif + +#if defined(CONFIG_MXS_PERSISTENT) + { + .name = "mxs-persistent", + .size = 1, + .pdev = &mxs_persistent, + }, +#endif + #if defined(CONFIG_FB_MXS) || defined(CONFIG_FB_MXS_MODULE) { .name = "mxs-fb", diff --git a/arch/arm/plat-mxs/include/mach/device.h b/arch/arm/plat-mxs/include/mach/device.h index 3f9280ffd7f6..7a99647ed0ff 100644 --- a/arch/arm/plat-mxs/include/mach/device.h +++ b/arch/arm/plat-mxs/include/mach/device.h @@ -220,6 +220,18 @@ struct gpmi_platform_data { }; +struct mxs_persistent_bit_config { + int reg; + int start; + int width; + const char *name; +}; + +struct mxs_platform_persistent_data { + const struct mxs_persistent_bit_config *bit_config_tab; + int bit_config_cnt; +}; + extern void mxs_timer_init(struct mxs_sys_timer *timer); extern void mxs_nomatch_timer_init(struct mxs_sys_timer *timer); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 68ab39d7cb35..281b61b3b5f3 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -233,6 +233,11 @@ config ISL29003 This driver can also be built as a module. If so, the module will be called isl29003. +config MXS_PERSISTENT + tristate "MX23/MX28 persistent bit" + depends on ARCH_MXS + default y + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 36f733cd60e6..03dd5ee05ce2 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -20,5 +20,6 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_HP_ILO) += hpilo.o obj-$(CONFIG_ISL29003) += isl29003.o obj-$(CONFIG_C2PORT) += c2port/ +obj-$(CONFIG_MXS_PERSISTENT) += mxs-persistent.o obj-y += eeprom/ obj-y += cb710/ diff --git a/drivers/misc/mxs-persistent.c b/drivers/misc/mxs-persistent.c index 95826328a618..415010c6b810 100644 --- a/drivers/misc/mxs-persistent.c +++ b/drivers/misc/mxs-persistent.c @@ -24,16 +24,16 @@ #include <linux/sysfs.h> #include <mach/hardware.h> #include <asm/irq.h> -#include <mach/stmp3xxx.h> -#include <mach/platform.h> +#include <mach/device.h> #include <mach/regs-rtc.h> -struct stmp3xxx_persistent_data { +struct mxs_persistent_data { struct device *dev; - struct stmp3xxx_platform_persistent_data *pdata; + struct mxs_platform_persistent_data *pdata; int count; struct attribute_group attr_group; + unsigned int base; /* attribute ** follow */ /* device_attribute follow */ }; @@ -43,59 +43,65 @@ struct stmp3xxx_persistent_data { #define pd_device_attribute_ptr(x) \ ((struct device_attribute *)(pd_attribute_ptr(x) + (x)->count + 1)) -static inline u32 persistent_reg_read(int reg) +static inline u32 persistent_reg_read(struct mxs_persistent_data *pdata, + int reg) { u32 msk; /* wait for stable value */ - msk = BF(0x01 << reg, RTC_STAT_STALE_REGS); - while (__raw_readl(REGS_RTC_BASE + HW_RTC_STAT) & msk) + msk = BF_RTC_STAT_STALE_REGS((0x1 << reg)); + while (__raw_readl(pdata->base + HW_RTC_STAT) & msk) cpu_relax(); - return __raw_readl(REGS_RTC_BASE + 0x60 + (reg * 0x10)); + return __raw_readl(pdata->base + 0x60 + (reg * 0x10)); } -static inline void persistent_reg_wait_settle(int reg) +static inline void persistent_reg_wait_settle(struct mxs_persistent_data *pdata + , int reg) { u32 msk; /* wait until the change is propagated */ - msk = BF(0x01 << reg, RTC_STAT_NEW_REGS); - while (__raw_readl(REGS_RTC_BASE + HW_RTC_STAT) & msk) + msk = BF_RTC_STAT_NEW_REGS((0x1 << reg)); + while (__raw_readl(pdata->base + HW_RTC_STAT) & msk) cpu_relax(); } -static inline void persistent_reg_write(u32 val, int reg) +static inline void persistent_reg_write(struct mxs_persistent_data *pdata, + u32 val, int reg) { - __raw_writel(val, REGS_RTC_BASE + 0x60 + (reg * 0x10)); - persistent_reg_wait_settle(reg); + __raw_writel(val, pdata->base + 0x60 + (reg * 0x10)); + persistent_reg_wait_settle(pdata, reg); } -static inline void persistent_reg_set(u32 val, int reg) +static inline void persistent_reg_set(struct mxs_persistent_data *pdata, + u32 val, int reg) { - __raw_writel(val, REGS_RTC_BASE + 0x60 + (reg * 0x10) + 0x4); - persistent_reg_wait_settle(reg); + __raw_writel(val, pdata->base + 0x60 + (reg * 0x10) + 0x4); + persistent_reg_wait_settle(pdata, reg); } -static inline void persistent_reg_clr(u32 val, int reg) +static inline void persistent_reg_clr(struct mxs_persistent_data *pdata, + u32 val, int reg) { - __raw_writel(val, REGS_RTC_BASE + 0x60 + (reg * 0x10) + 0x8); - persistent_reg_wait_settle(reg); + __raw_writel(val, pdata->base + 0x60 + (reg * 0x10) + 0x8); + persistent_reg_wait_settle(pdata, reg); } -static inline void persistent_reg_tog(u32 val, int reg) +static inline void persistent_reg_tog(struct mxs_persistent_data *pdata, + u32 val, int reg) { - __raw_writel(val, REGS_RTC_BASE + 0x60 + (reg * 0x10) + 0xc); - persistent_reg_wait_settle(reg); + __raw_writel(val, pdata->base + 0x60 + (reg * 0x10) + 0xc); + persistent_reg_wait_settle(pdata, reg); } static ssize_t persistent_show(struct device *dev, struct device_attribute *attr, char *buf) { struct platform_device *pdev = to_platform_device(dev); - struct stmp3xxx_persistent_data *pd = platform_get_drvdata(pdev); + struct mxs_persistent_data *pd = platform_get_drvdata(pdev); struct device_attribute *devattr = pd_device_attribute_ptr(pd); - const struct stmp3xxx_persistent_bit_config *pb; + const struct mxs_persistent_bit_config *pb; int idx; u32 val; @@ -106,7 +112,7 @@ persistent_show(struct device *dev, struct device_attribute *attr, char *buf) pb = &pd->pdata->bit_config_tab[idx]; /* read value and shift */ - val = persistent_reg_read(pb->reg); + val = persistent_reg_read(pd, pb->reg); val >>= pb->start; val &= (1 << pb->width) - 1; @@ -118,9 +124,9 @@ persistent_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); - struct stmp3xxx_persistent_data *pd = platform_get_drvdata(pdev); + struct mxs_persistent_data *pd = platform_get_drvdata(pdev); struct device_attribute *devattr = pd_device_attribute_ptr(pd); - const struct stmp3xxx_persistent_bit_config *pb; + const struct mxs_persistent_bit_config *pb; int idx, r; unsigned long val, msk; @@ -141,21 +147,22 @@ persistent_store(struct device *dev, struct device_attribute *attr, /* lockless update, first clear the area */ msk = ((1 << pb->width) - 1) << pb->start; - persistent_reg_clr(msk, pb->reg); + persistent_reg_clr(pd, msk, pb->reg); /* shift into position */ val <<= pb->start; - persistent_reg_set(val, pb->reg); + persistent_reg_set(pd, val, pb->reg); return count; } -static int __devinit stmp3xxx_persistent_probe(struct platform_device *pdev) +static int __devinit mxs_persistent_probe(struct platform_device *pdev) { - struct stmp3xxx_persistent_data *pd; - struct stmp3xxx_platform_persistent_data *pdata; - const struct stmp3xxx_persistent_bit_config *pb; + struct mxs_persistent_data *pd; + struct mxs_platform_persistent_data *pdata; + struct resource *res; + const struct mxs_persistent_bit_config *pb; struct attribute **attr; struct device_attribute *devattr; int i, cnt, size; @@ -165,6 +172,10 @@ static int __devinit stmp3xxx_persistent_probe(struct platform_device *pdev) if (pdata == NULL) return -ENODEV; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) + return -ENODEV; + cnt = pdata->bit_config_cnt; size = sizeof(*pd) + (cnt + 1) * sizeof(struct atrribute *) + @@ -174,6 +185,8 @@ static int __devinit stmp3xxx_persistent_probe(struct platform_device *pdev) return -ENOMEM; pd->dev = &pdev->dev; pd->pdata = pdata; + pd->base = (unsigned int)IO_ADDRESS(res->start); + platform_set_drvdata(pdev, pd); pd->count = cnt; attr = pd_attribute_ptr(pd); @@ -200,9 +213,9 @@ static int __devinit stmp3xxx_persistent_probe(struct platform_device *pdev) return 0; } -static int stmp3xxx_persistent_remove(struct platform_device *pdev) +static int __devexit mxs_persistent_remove(struct platform_device *pdev) { - struct stmp3xxx_persistent_data *pd; + struct mxs_persistent_data *pd; pd = platform_get_drvdata(pdev); sysfs_remove_group(&pdev->dev.kobj, &pd->attr_group); @@ -214,44 +227,44 @@ static int stmp3xxx_persistent_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int -stmp3xxx_persistent_suspend(struct platform_device *pdev, pm_message_t state) +mxs_persistent_suspend(struct platform_device *pdev, pm_message_t state) { return 0; } -static int stmp3xxx_persistent_resume(struct platform_device *pdev) +static int mxs_persistent_resume(struct platform_device *pdev) { return 0; } #else -#define stmp3xxx_persistent_suspend NULL -#define stmp3xxx_persistent_resume NULL +#define mxs_persistent_suspend NULL +#define mxs_persistent_resume NULL #endif -static struct platform_driver stmp3xxx_persistent_driver = { - .probe = stmp3xxx_persistent_probe, - .remove = stmp3xxx_persistent_remove, - .suspend = stmp3xxx_persistent_suspend, - .resume = stmp3xxx_persistent_resume, +static struct platform_driver mxs_persistent_driver = { + .probe = mxs_persistent_probe, + .remove = __exit_p(mxs_persistent_remove), + .suspend = mxs_persistent_suspend, + .resume = mxs_persistent_resume, .driver = { - .name = "stmp3xxx-persistent", + .name = "mxs-persistent", .owner = THIS_MODULE, }, }; -static int __init stmp3xxx_persistent_init(void) +static int __init mxs_persistent_init(void) { - return platform_driver_register(&stmp3xxx_persistent_driver); + return platform_driver_register(&mxs_persistent_driver); } -static void __exit stmp3xxx_persistent_exit(void) +static void __exit mxs_persistent_exit(void) { - platform_driver_unregister(&stmp3xxx_persistent_driver); + platform_driver_unregister(&mxs_persistent_driver); } MODULE_AUTHOR("Pantelis Antoniou <pantelis@embeddedalley.com>"); MODULE_DESCRIPTION("Persistent bits user-access driver"); MODULE_LICENSE("GPL"); -module_init(stmp3xxx_persistent_init); -module_exit(stmp3xxx_persistent_exit); +module_init(mxs_persistent_init); +module_exit(mxs_persistent_exit); |