mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-02-04 08:04:49 +00:00
ENGR00122477-2 iMX23 Enable persistent bit support
enable persistent bit support Signed-off-by: Frank Li <Frank.Li@freescale.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user