Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 148963
b: refs/heads/master
c: 38f7b00
h: refs/heads/master
i:
  148961: 044edc0
  148959: 69e1120
v: v3
  • Loading branch information
Hartley Sweeten authored and Russell King committed Apr 26, 2009
1 parent 013b76a commit 1033422
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 924a158a12c7e732179dd85ddd20848039e7bd71
refs/heads/master: 38f7b009a6ae1708fcf0f208aba9a9a4364bcfcf
15 changes: 12 additions & 3 deletions trunk/arch/arm/mach-ep93xx/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,19 @@ static struct amba_device uart3_device = {
};


static struct resource ep93xx_rtc_resource[] = {
{
.start = EP93XX_RTC_PHYS_BASE,
.end = EP93XX_RTC_PHYS_BASE + 0x10c - 1,
.flags = IORESOURCE_MEM,
},
};

static struct platform_device ep93xx_rtc_device = {
.name = "ep93xx-rtc",
.id = -1,
.num_resources = 0,
.name = "ep93xx-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(ep93xx_rtc_resource),
.resource = ep93xx_rtc_resource,
};


Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
#define EP93XX_PWM_BASE (EP93XX_APB_VIRT_BASE + 0x00110000)

#define EP93XX_RTC_BASE (EP93XX_APB_VIRT_BASE + 0x00120000)
#define EP93XX_RTC_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00120000)

#define EP93XX_SYSCON_BASE (EP93XX_APB_VIRT_BASE + 0x00130000)
#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x))
Expand Down
149 changes: 112 additions & 37 deletions trunk/drivers/rtc/rtc-ep93xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,74 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <linux/io.h>

#define EP93XX_RTC_DATA 0x000
#define EP93XX_RTC_MATCH 0x004
#define EP93XX_RTC_STATUS 0x008
#define EP93XX_RTC_STATUS_INTR (1<<0)
#define EP93XX_RTC_LOAD 0x00C
#define EP93XX_RTC_CONTROL 0x010
#define EP93XX_RTC_CONTROL_MIE (1<<0)
#define EP93XX_RTC_SWCOMP 0x108
#define EP93XX_RTC_SWCOMP_DEL_MASK 0x001f0000
#define EP93XX_RTC_SWCOMP_DEL_SHIFT 16
#define EP93XX_RTC_SWCOMP_INT_MASK 0x0000ffff
#define EP93XX_RTC_SWCOMP_INT_SHIFT 0

#define DRV_VERSION "0.3"

#define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x))
#define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000)
#define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C)
#define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108)

#define DRV_VERSION "0.2"
/*
* struct device dev.platform_data is used to store our private data
* because struct rtc_device does not have a variable to hold it.
*/
struct ep93xx_rtc {
void __iomem *mmio_base;
};

static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload,
static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
unsigned short *delete)
{
unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP);
struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
unsigned long comp;

comp = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);

if (preload)
*preload = comp & 0xffff;
*preload = (comp & EP93XX_RTC_SWCOMP_INT_MASK)
>> EP93XX_RTC_SWCOMP_INT_SHIFT;

if (delete)
*delete = (comp >> 16) & 0x1f;
*delete = (comp & EP93XX_RTC_SWCOMP_DEL_MASK)
>> EP93XX_RTC_SWCOMP_DEL_SHIFT;

return 0;
}

static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
unsigned long time = __raw_readl(EP93XX_RTC_DATA);
struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;
unsigned long time;

time = __raw_readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);

rtc_time_to_tm(time, tm);
return 0;
}

static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
{
__raw_writel(secs + 1, EP93XX_RTC_LOAD);
struct ep93xx_rtc *ep93xx_rtc = dev->platform_data;

__raw_writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
return 0;
}

static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned short preload, delete;

ep93xx_get_swcomp(dev, &preload, &delete);
ep93xx_rtc_get_swcomp(dev, &preload, &delete);

seq_printf(seq, "preload\t\t: %d\n", preload);
seq_printf(seq, "delete\t\t: %d\n", delete);
Expand All @@ -67,78 +93,127 @@ static const struct rtc_class_ops ep93xx_rtc_ops = {
.proc = ep93xx_rtc_proc,
};

static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev,
static ssize_t ep93xx_rtc_show_comp_preload(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned short preload;

ep93xx_get_swcomp(dev, &preload, NULL);
ep93xx_rtc_get_swcomp(dev, &preload, NULL);

return sprintf(buf, "%d\n", preload);
}
static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL);
static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_rtc_show_comp_preload, NULL);

static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev,
static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned short delete;

ep93xx_get_swcomp(dev, NULL, &delete);
ep93xx_rtc_get_swcomp(dev, NULL, &delete);

return sprintf(buf, "%d\n", delete);
}
static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL);
static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL);


static int __devinit ep93xx_rtc_probe(struct platform_device *dev)
static int __init ep93xx_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc = rtc_device_register("ep93xx",
&dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
struct ep93xx_rtc *ep93xx_rtc;
struct resource *res;
struct rtc_device *rtc;
int err;

ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL);
if (ep93xx_rtc == NULL)
return -ENOMEM;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL)
return -ENXIO;

res = request_mem_region(res->start, resource_size(res), pdev->name);
if (res == NULL)
return -EBUSY;

ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res));
if (ep93xx_rtc->mmio_base == NULL) {
err = -ENXIO;
goto fail;
}

pdev->dev.platform_data = ep93xx_rtc;

rtc = rtc_device_register(pdev->name,
&pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
return PTR_ERR(rtc);
err = PTR_ERR(rtc);
goto fail;
}

platform_set_drvdata(dev, rtc);
platform_set_drvdata(pdev, rtc);

device_create_file(&dev->dev, &dev_attr_comp_preload);
device_create_file(&dev->dev, &dev_attr_comp_delete);
err = device_create_file(&pdev->dev, &dev_attr_comp_preload);
if (err)
goto fail;
err = device_create_file(&pdev->dev, &dev_attr_comp_delete);
if (err) {
device_remove_file(&pdev->dev, &dev_attr_comp_preload);
goto fail;
}

return 0;

fail:
if (ep93xx_rtc->mmio_base) {
iounmap(ep93xx_rtc->mmio_base);
pdev->dev.platform_data = NULL;
}
release_mem_region(res->start, resource_size(res));
return err;
}

static int __devexit ep93xx_rtc_remove(struct platform_device *dev)
static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
{
struct rtc_device *rtc = platform_get_drvdata(dev);
struct rtc_device *rtc = platform_get_drvdata(pdev);
struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data;
struct resource *res;

/* cleanup sysfs */
device_remove_file(&pdev->dev, &dev_attr_comp_delete);
device_remove_file(&pdev->dev, &dev_attr_comp_preload);

rtc_device_unregister(rtc);

iounmap(ep93xx_rtc->mmio_base);
pdev->dev.platform_data = NULL;

if (rtc)
rtc_device_unregister(rtc);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));

platform_set_drvdata(dev, NULL);
platform_set_drvdata(pdev, NULL);

return 0;
}

/* work with hotplug and coldplug */
MODULE_ALIAS("platform:ep93xx-rtc");

static struct platform_driver ep93xx_rtc_platform_driver = {
static struct platform_driver ep93xx_rtc_driver = {
.driver = {
.name = "ep93xx-rtc",
.owner = THIS_MODULE,
},
.probe = ep93xx_rtc_probe,
.remove = __devexit_p(ep93xx_rtc_remove),
.remove = __exit_p(ep93xx_rtc_remove),
};

static int __init ep93xx_rtc_init(void)
{
return platform_driver_register(&ep93xx_rtc_platform_driver);
return platform_driver_probe(&ep93xx_rtc_driver, ep93xx_rtc_probe);
}

static void __exit ep93xx_rtc_exit(void)
{
platform_driver_unregister(&ep93xx_rtc_platform_driver);
platform_driver_unregister(&ep93xx_rtc_driver);
}

MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
Expand Down

0 comments on commit 1033422

Please sign in to comment.