aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/abx500-core.c
diff options
context:
space:
mode:
authorMattias Wallin <mattias.wallin@stericsson.com>2010-05-01 12:26:20 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2010-05-27 19:37:45 -0400
commitfa661258a27aa74aaf741882053d195291cefb75 (patch)
tree73b6e0c7156088f660de465555ee13226ac78242 /drivers/mfd/abx500-core.c
parent812f9e9d424dde9ccb35975c0281edb6f8543735 (diff)
mfd: AB3100 register access change to abx500 API
The interface for the AB3100 is changed to make way for the ABX500 family of chips: AB3550, AB5500 and future ST-Ericsson Analog Baseband chips. The register access functions are moved out to a separate struct abx500_ops. In this way the interface is moved from the implementation and the sub functionality drivers can keep their interface intact when chip infrastructure and communication mechanisms changes. We also define the AB3550 device IDs and the AB3550 platform data struct and convert the catenated 32bit event to an array of 3 x 8bits. Signed-off-by: Mattias Wallin <mattias.wallin@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/abx500-core.c')
-rw-r--r--drivers/mfd/abx500-core.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
new file mode 100644
index 000000000000..3b3b97ec32a7
--- /dev/null
+++ b/drivers/mfd/abx500-core.c
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2007-2010 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Register access functions for the ABX500 Mixed Signal IC family.
5 * Author: Mattias Wallin <mattias.wallin@stericsson.com>
6 */
7
8#include <linux/list.h>
9#include <linux/slab.h>
10#include <linux/err.h>
11#include <linux/mfd/abx500.h>
12
13static LIST_HEAD(abx500_list);
14
15struct abx500_device_entry {
16 struct list_head list;
17 struct abx500_ops ops;
18 struct device *dev;
19};
20
21static void lookup_ops(struct device *dev, struct abx500_ops **ops)
22{
23 struct abx500_device_entry *dev_entry;
24
25 *ops = NULL;
26 list_for_each_entry(dev_entry, &abx500_list, list) {
27 if (dev_entry->dev == dev) {
28 *ops = &dev_entry->ops;
29 return;
30 }
31 }
32}
33
34int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
35{
36 struct abx500_device_entry *dev_entry;
37
38 dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL);
39 if (IS_ERR(dev_entry)) {
40 dev_err(dev, "register_ops kzalloc failed");
41 return -ENOMEM;
42 }
43 dev_entry->dev = dev;
44 memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
45
46 list_add_tail(&dev_entry->list, &abx500_list);
47 return 0;
48}
49EXPORT_SYMBOL(abx500_register_ops);
50
51void abx500_remove_ops(struct device *dev)
52{
53 struct abx500_device_entry *dev_entry, *tmp;
54
55 list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list)
56 {
57 if (dev_entry->dev == dev) {
58 list_del(&dev_entry->list);
59 kfree(dev_entry);
60 }
61 }
62}
63EXPORT_SYMBOL(abx500_remove_ops);
64
65int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
66 u8 value)
67{
68 struct abx500_ops *ops;
69
70 lookup_ops(dev->parent, &ops);
71 if ((ops != NULL) && (ops->set_register != NULL))
72 return ops->set_register(dev, bank, reg, value);
73 else
74 return -ENOTSUPP;
75}
76EXPORT_SYMBOL(abx500_set_register_interruptible);
77
78int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
79 u8 *value)
80{
81 struct abx500_ops *ops;
82
83 lookup_ops(dev->parent, &ops);
84 if ((ops != NULL) && (ops->get_register != NULL))
85 return ops->get_register(dev, bank, reg, value);
86 else
87 return -ENOTSUPP;
88}
89EXPORT_SYMBOL(abx500_get_register_interruptible);
90
91int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
92 u8 first_reg, u8 *regvals, u8 numregs)
93{
94 struct abx500_ops *ops;
95
96 lookup_ops(dev->parent, &ops);
97 if ((ops != NULL) && (ops->get_register_page != NULL))
98 return ops->get_register_page(dev, bank,
99 first_reg, regvals, numregs);
100 else
101 return -ENOTSUPP;
102}
103EXPORT_SYMBOL(abx500_get_register_page_interruptible);
104
105int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
106 u8 reg, u8 bitmask, u8 bitvalues)
107{
108 struct abx500_ops *ops;
109
110 lookup_ops(dev->parent, &ops);
111 if ((ops != NULL) && (ops->mask_and_set_register != NULL))
112 return ops->mask_and_set_register(dev, bank,
113 reg, bitmask, bitvalues);
114 else
115 return -ENOTSUPP;
116}
117EXPORT_SYMBOL(abx500_mask_and_set_register_interruptible);
118
119int abx500_get_chip_id(struct device *dev)
120{
121 struct abx500_ops *ops;
122
123 lookup_ops(dev->parent, &ops);
124 if ((ops != NULL) && (ops->get_chip_id != NULL))
125 return ops->get_chip_id(dev);
126 else
127 return -ENOTSUPP;
128}
129EXPORT_SYMBOL(abx500_get_chip_id);
130
131int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
132{
133 struct abx500_ops *ops;
134
135 lookup_ops(dev->parent, &ops);
136 if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL))
137 return ops->event_registers_startup_state_get(dev, event);
138 else
139 return -ENOTSUPP;
140}
141EXPORT_SYMBOL(abx500_event_registers_startup_state_get);
142
143int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
144{
145 struct abx500_ops *ops;
146
147 lookup_ops(dev->parent, &ops);
148 if ((ops != NULL) && (ops->startup_irq_enabled != NULL))
149 return ops->startup_irq_enabled(dev, irq);
150 else
151 return -ENOTSUPP;
152}
153EXPORT_SYMBOL(abx500_startup_irq_enabled);
154
155MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
156MODULE_DESCRIPTION("ABX500 core driver");
157MODULE_LICENSE("GPL");