aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig33
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/atmel_tclib.c161
-rw-r--r--drivers/misc/enclosure.c118
4 files changed, 259 insertions, 54 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 962817e49fb..bb94ce78a6d 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -22,6 +22,39 @@ config ATMEL_PWM
purposes including software controlled power-efficent backlights
on LCD displays, motor control, and waveform generation.
+config ATMEL_TCLIB
+ bool "Atmel AT32/AT91 Timer/Counter Library"
+ depends on (AVR32 || ARCH_AT91)
+ help
+ Select this if you want a library to allocate the Timer/Counter
+ blocks found on many Atmel processors. This facilitates using
+ these blocks by different drivers despite processor differences.
+
+config ATMEL_TCB_CLKSRC
+ bool "TC Block Clocksource"
+ depends on ATMEL_TCLIB && GENERIC_TIME
+ default y
+ help
+ Select this to get a high precision clocksource based on a
+ TC block with a 5+ MHz base clock rate. Two timer channels
+ are combined to make a single 32-bit timer.
+
+ When GENERIC_CLOCKEVENTS is defined, the third timer channel
+ may be used as a clock event device supporting oneshot mode
+ (delays of up to two seconds) based on the 32 KiHz clock.
+
+config ATMEL_TCB_CLKSRC_BLOCK
+ int
+ depends on ATMEL_TCB_CLKSRC
+ prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
+ default 0
+ range 0 1
+ help
+ Some chips provide more than one TC block, so you have the
+ choice of which one to use for the clock framework. The other
+ TC can be used for other purposes, such as PWM generation and
+ interval timing.
+
config IBM_ASM
tristate "Device driver for IBM RSA service processor"
depends on X86 && PCI && INPUT && EXPERIMENTAL
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index bbc69fdd1b9..4581b253311 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
+obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
new file mode 100644
index 00000000000..05dc8a31f28
--- /dev/null
+++ b/drivers/misc/atmel_tclib.c
@@ -0,0 +1,161 @@
+#include <linux/atmel_tc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+/* Number of bytes to reserve for the iomem resource */
+#define ATMEL_TC_IOMEM_SIZE 256
+
+
+/*
+ * This is a thin library to solve the problem of how to portably allocate
+ * one of the TC blocks. For simplicity, it doesn't currently expect to
+ * share individual timers between different drivers.
+ */
+
+#if defined(CONFIG_AVR32)
+/* AVR32 has these divide PBB */
+const u8 atmel_tc_divisors[5] = { 0, 4, 8, 16, 32, };
+EXPORT_SYMBOL(atmel_tc_divisors);
+
+#elif defined(CONFIG_ARCH_AT91)
+/* AT91 has these divide MCK */
+const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, };
+EXPORT_SYMBOL(atmel_tc_divisors);
+
+#endif
+
+static DEFINE_SPINLOCK(tc_list_lock);
+static LIST_HEAD(tc_list);
+
+/**
+ * atmel_tc_alloc - allocate a specified TC block
+ * @block: which block to allocate
+ * @name: name to be associated with the iomem resource
+ *
+ * Caller allocates a block. If it is available, a pointer to a
+ * pre-initialized struct atmel_tc is returned. The caller can access
+ * the registers directly through the "regs" field.
+ */
+struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
+{
+ struct atmel_tc *tc;
+ struct platform_device *pdev = NULL;
+ struct resource *r;
+
+ spin_lock(&tc_list_lock);
+ list_for_each_entry(tc, &tc_list, node) {
+ if (tc->pdev->id == block) {
+ pdev = tc->pdev;
+ break;
+ }
+ }
+
+ if (!pdev || tc->iomem)
+ goto fail;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ r = request_mem_region(r->start, ATMEL_TC_IOMEM_SIZE, name);
+ if (!r)
+ goto fail;
+
+ tc->regs = ioremap(r->start, ATMEL_TC_IOMEM_SIZE);
+ if (!tc->regs)
+ goto fail_ioremap;
+
+ tc->iomem = r;
+
+out:
+ spin_unlock(&tc_list_lock);
+ return tc;
+
+fail_ioremap:
+ release_resource(r);
+fail:
+ tc = NULL;
+ goto out;
+}
+EXPORT_SYMBOL_GPL(atmel_tc_alloc);
+
+/**
+ * atmel_tc_free - release a specified TC block
+ * @tc: Timer/counter block that was returned by atmel_tc_alloc()
+ *
+ * This reverses the effect of atmel_tc_alloc(), unmapping the I/O
+ * registers, invalidating the resource returned by that routine and
+ * making the TC available to other drivers.
+ */
+void atmel_tc_free(struct atmel_tc *tc)
+{
+ spin_lock(&tc_list_lock);
+ if (tc->regs) {
+ iounmap(tc->regs);
+ release_resource(tc->iomem);
+ tc->regs = NULL;
+ tc->iomem = NULL;
+ }
+ spin_unlock(&tc_list_lock);
+}
+EXPORT_SYMBOL_GPL(atmel_tc_free);
+
+static int __init tc_probe(struct platform_device *pdev)
+{
+ struct atmel_tc *tc;
+ struct clk *clk;
+ int irq;
+
+ if (!platform_get_resource(pdev, IORESOURCE_MEM, 0))
+ return -EINVAL;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -EINVAL;
+
+ tc = kzalloc(sizeof(struct atmel_tc), GFP_KERNEL);
+ if (!tc)
+ return -ENOMEM;
+
+ tc->pdev = pdev;
+
+ clk = clk_get(&pdev->dev, "t0_clk");
+ if (IS_ERR(clk)) {
+ kfree(tc);
+ return -EINVAL;
+ }
+
+ tc->clk[0] = clk;
+ tc->clk[1] = clk_get(&pdev->dev, "t1_clk");
+ if (IS_ERR(tc->clk[1]))
+ tc->clk[1] = clk;
+ tc->clk[2] = clk_get(&pdev->dev, "t2_clk");
+ if (IS_ERR(tc->clk[2]))
+ tc->clk[2] = clk;
+
+ tc->irq[0] = irq;
+ tc->irq[1] = platform_get_irq(pdev, 1);
+ if (tc->irq[1] < 0)
+ tc->irq[1] = irq;
+ tc->irq[2] = platform_get_irq(pdev, 2);
+ if (tc->irq[2] < 0)
+ tc->irq[2] = irq;
+
+ spin_lock(&tc_list_lock);
+ list_add_tail(&tc->node, &tc_list);
+ spin_unlock(&tc_list_lock);
+
+ return 0;
+}
+
+static struct platform_driver tc_driver = {
+ .driver.name = "atmel_tcb",
+};
+
+static int __init tc_init(void)
+{
+ return platform_driver_probe(&tc_driver, tc_probe);
+}
+arch_initcall(tc_init);
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 6fcb0e96adf..fafb57fed76 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -40,16 +40,16 @@ static struct class enclosure_component_class;
* Looks through the list of registered enclosures to see
* if it can find a match for a device. Returns NULL if no
* enclosure is found. Obtains a reference to the enclosure class
- * device which must be released with class_device_put().
+ * device which must be released with device_put().
*/
struct enclosure_device *enclosure_find(struct device *dev)
{
- struct enclosure_device *edev = NULL;
+ struct enclosure_device *edev;
mutex_lock(&container_list_lock);
list_for_each_entry(edev, &container_list, node) {
- if (edev->cdev.dev == dev) {
- class_device_get(&edev->cdev);
+ if (edev->edev.parent == dev) {
+ get_device(&edev->edev);
mutex_unlock(&container_list_lock);
return edev;
}
@@ -117,11 +117,11 @@ enclosure_register(struct device *dev, const char *name, int components,
edev->components = components;
- edev->cdev.class = &enclosure_class;
- edev->cdev.dev = get_device(dev);
+ edev->edev.class = &enclosure_class;
+ edev->edev.parent = get_device(dev);
edev->cb = cb;
- snprintf(edev->cdev.class_id, BUS_ID_SIZE, "%s", name);
- err = class_device_register(&edev->cdev);
+ snprintf(edev->edev.bus_id, BUS_ID_SIZE, "%s", name);
+ err = device_register(&edev->edev);
if (err)
goto err;
@@ -135,7 +135,7 @@ enclosure_register(struct device *dev, const char *name, int components,
return edev;
err:
- put_device(edev->cdev.dev);
+ put_device(edev->edev.parent);
kfree(edev);
return ERR_PTR(err);
}
@@ -158,27 +158,28 @@ void enclosure_unregister(struct enclosure_device *edev)
for (i = 0; i < edev->components; i++)
if (edev->component[i].number != -1)
- class_device_unregister(&edev->component[i].cdev);
+ device_unregister(&edev->component[i].cdev);
/* prevent any callbacks into service user */
edev->cb = &enclosure_null_callbacks;
- class_device_unregister(&edev->cdev);
+ device_unregister(&edev->edev);
}
EXPORT_SYMBOL_GPL(enclosure_unregister);
-static void enclosure_release(struct class_device *cdev)
+static void enclosure_release(struct device *cdev)
{
struct enclosure_device *edev = to_enclosure_device(cdev);
- put_device(cdev->dev);
+ put_device(cdev->parent);
kfree(edev);
}
-static void enclosure_component_release(struct class_device *cdev)
+static void enclosure_component_release(struct device *dev)
{
- if (cdev->dev)
- put_device(cdev->dev);
- class_device_put(cdev->parent);
+ struct enclosure_component *cdev = to_enclosure_component(dev);
+
+ put_device(cdev->dev);
+ put_device(dev->parent);
}
/**
@@ -201,7 +202,7 @@ enclosure_component_register(struct enclosure_device *edev,
const char *name)
{
struct enclosure_component *ecomp;
- struct class_device *cdev;
+ struct device *cdev;
int err;
if (number >= edev->components)
@@ -215,14 +216,14 @@ enclosure_component_register(struct enclosure_device *edev,
ecomp->type = type;
ecomp->number = number;
cdev = &ecomp->cdev;
- cdev->parent = class_device_get(&edev->cdev);
+ cdev->parent = get_device(&edev->edev);
cdev->class = &enclosure_component_class;
if (name)
- snprintf(cdev->class_id, BUS_ID_SIZE, "%s", name);
+ snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
else
- snprintf(cdev->class_id, BUS_ID_SIZE, "%u", number);
+ snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
- err = class_device_register(cdev);
+ err = device_register(cdev);
if (err)
ERR_PTR(err);
@@ -247,18 +248,17 @@ EXPORT_SYMBOL_GPL(enclosure_component_register);
int enclosure_add_device(struct enclosure_device *edev, int component,
struct device *dev)
{
- struct class_device *cdev;
+ struct enclosure_component *cdev;
if (!edev || component >= edev->components)
return -EINVAL;
- cdev = &edev->component[component].cdev;
+ cdev = &edev->component[component];
- class_device_del(cdev);
- if (cdev->dev)
- put_device(cdev->dev);
+ device_del(&cdev->cdev);
+ put_device(cdev->dev);
cdev->dev = get_device(dev);
- return class_device_add(cdev);
+ return device_add(&cdev->cdev);
}
EXPORT_SYMBOL_GPL(enclosure_add_device);
@@ -272,18 +272,17 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
*/
int enclosure_remove_device(struct enclosure_device *edev, int component)
{
- struct class_device *cdev;
+ struct enclosure_component *cdev;
if (!edev || component >= edev->components)
return -EINVAL;
- cdev = &edev->component[component].cdev;
+ cdev = &edev->component[component];
- class_device_del(cdev);
- if (cdev->dev)
- put_device(cdev->dev);
+ device_del(&cdev->cdev);
+ put_device(cdev->dev);
cdev->dev = NULL;
- return class_device_add(cdev);
+ return device_add(&cdev->cdev);
}
EXPORT_SYMBOL_GPL(enclosure_remove_device);
@@ -291,14 +290,16 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
* sysfs pieces below
*/
-static ssize_t enclosure_show_components(struct class_device *cdev, char *buf)
+static ssize_t enclosure_show_components(struct device *cdev,
+ struct device_attribute *attr,
+ char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev);
return snprintf(buf, 40, "%d\n", edev->components);
}
-static struct class_device_attribute enclosure_attrs[] = {
+static struct device_attribute enclosure_attrs[] = {
__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
__ATTR_NULL
};
@@ -306,8 +307,8 @@ static struct class_device_attribute enclosure_attrs[] = {
static struct class enclosure_class = {
.name = "enclosure",
.owner = THIS_MODULE,
- .release = enclosure_release,
- .class_dev_attrs = enclosure_attrs,
+ .dev_release = enclosure_release,
+ .dev_attrs = enclosure_attrs,
};
static const char *const enclosure_status [] = {
@@ -326,7 +327,8 @@ static const char *const enclosure_type [] = {
[ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
};
-static ssize_t get_component_fault(struct class_device *cdev, char *buf)
+static ssize_t get_component_fault(struct device *cdev,
+ struct device_attribute *attr, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -336,8 +338,9 @@ static ssize_t get_component_fault(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%d\n", ecomp->fault);
}
-static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
- size_t count)
+static ssize_t set_component_fault(struct device *cdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -348,7 +351,8 @@ static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
return count;
}
-static ssize_t get_component_status(struct class_device *cdev, char *buf)
+static ssize_t get_component_status(struct device *cdev,
+ struct device_attribute *attr,char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -358,8 +362,9 @@ static ssize_t get_component_status(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
}
-static ssize_t set_component_status(struct class_device *cdev, const char *buf,
- size_t count)
+static ssize_t set_component_status(struct device *cdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -380,7 +385,8 @@ static ssize_t set_component_status(struct class_device *cdev, const char *buf,
return -EINVAL;
}
-static ssize_t get_component_active(struct class_device *cdev, char *buf)
+static ssize_t get_component_active(struct device *cdev,
+ struct device_attribute *attr, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -390,8 +396,9 @@ static ssize_t get_component_active(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%d\n", ecomp->active);
}
-static ssize_t set_component_active(struct class_device *cdev, const char *buf,
- size_t count)
+static ssize_t set_component_active(struct device *cdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -402,7 +409,8 @@ static ssize_t set_component_active(struct class_device *cdev, const char *buf,
return count;
}
-static ssize_t get_component_locate(struct class_device *cdev, char *buf)
+static ssize_t get_component_locate(struct device *cdev,
+ struct device_attribute *attr, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -412,8 +420,9 @@ static ssize_t get_component_locate(struct class_device *cdev, char *buf)
return snprintf(buf, 40, "%d\n", ecomp->locate);
}
-static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
- size_t count)
+static ssize_t set_component_locate(struct device *cdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -424,7 +433,8 @@ static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
return count;
}
-static ssize_t get_component_type(struct class_device *cdev, char *buf)
+static ssize_t get_component_type(struct device *cdev,
+ struct device_attribute *attr, char *buf)
{
struct enclosure_component *ecomp = to_enclosure_component(cdev);
@@ -432,7 +442,7 @@ static ssize_t get_component_type(struct class_device *cdev, char *buf)
}
-static struct class_device_attribute enclosure_component_attrs[] = {
+static struct device_attribute enclosure_component_attrs[] = {
__ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
set_component_fault),
__ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
@@ -448,8 +458,8 @@ static struct class_device_attribute enclosure_component_attrs[] = {
static struct class enclosure_component_class = {
.name = "enclosure_component",
.owner = THIS_MODULE,
- .class_dev_attrs = enclosure_component_attrs,
- .release = enclosure_component_release,
+ .dev_attrs = enclosure_component_attrs,
+ .dev_release = enclosure_component_release,
};
static int __init enclosure_init(void)