~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/mfd/tps6105x.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Core driver for TPS61050/61052 boost converters, used for while LED
 
3
 * driving, audio power amplification, white LED flash, and generic
 
4
 * boost conversion. Additionally it provides a 1-bit GPIO pin (out or in)
 
5
 * and a flash synchronization pin to synchronize flash events when used as
 
6
 * flashgun.
 
7
 *
 
8
 * Copyright (C) 2011 ST-Ericsson SA
 
9
 * Written on behalf of Linaro for ST-Ericsson
 
10
 *
 
11
 * Author: Linus Walleij <linus.walleij@linaro.org>
 
12
 *
 
13
 * License terms: GNU General Public License (GPL) version 2
 
14
 */
 
15
 
 
16
#include <linux/module.h>
 
17
#include <linux/init.h>
 
18
#include <linux/i2c.h>
 
19
#include <linux/mutex.h>
 
20
#include <linux/gpio.h>
 
21
#include <linux/spinlock.h>
 
22
#include <linux/slab.h>
 
23
#include <linux/err.h>
 
24
#include <linux/regulator/driver.h>
 
25
#include <linux/mfd/core.h>
 
26
#include <linux/mfd/tps6105x.h>
 
27
 
 
28
int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value)
 
29
{
 
30
        int ret;
 
31
 
 
32
        ret = mutex_lock_interruptible(&tps6105x->lock);
 
33
        if (ret)
 
34
                return ret;
 
35
        ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value);
 
36
        mutex_unlock(&tps6105x->lock);
 
37
        if (ret < 0)
 
38
                return ret;
 
39
 
 
40
        return 0;
 
41
}
 
42
EXPORT_SYMBOL(tps6105x_set);
 
43
 
 
44
int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf)
 
45
{
 
46
        int ret;
 
47
 
 
48
        ret = mutex_lock_interruptible(&tps6105x->lock);
 
49
        if (ret)
 
50
                return ret;
 
51
        ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
 
52
        mutex_unlock(&tps6105x->lock);
 
53
        if (ret < 0)
 
54
                return ret;
 
55
 
 
56
        *buf = ret;
 
57
        return 0;
 
58
}
 
59
EXPORT_SYMBOL(tps6105x_get);
 
60
 
 
61
/*
 
62
 * Masks off the bits in the mask and sets the bits in the bitvalues
 
63
 * parameter in one atomic operation
 
64
 */
 
65
int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
 
66
                          u8 bitmask, u8 bitvalues)
 
67
{
 
68
        int ret;
 
69
        u8 regval;
 
70
 
 
71
        ret = mutex_lock_interruptible(&tps6105x->lock);
 
72
        if (ret)
 
73
                return ret;
 
74
        ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
 
75
        if (ret < 0)
 
76
                goto fail;
 
77
        regval = ret;
 
78
        regval = (~bitmask & regval) | (bitmask & bitvalues);
 
79
        ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval);
 
80
fail:
 
81
        mutex_unlock(&tps6105x->lock);
 
82
        if (ret < 0)
 
83
                return ret;
 
84
 
 
85
        return 0;
 
86
}
 
87
EXPORT_SYMBOL(tps6105x_mask_and_set);
 
88
 
 
89
static int __devinit tps6105x_startup(struct tps6105x *tps6105x)
 
90
{
 
91
        int ret;
 
92
        u8 regval;
 
93
 
 
94
        ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
 
95
        if (ret)
 
96
                return ret;
 
97
        switch (regval >> TPS6105X_REG0_MODE_SHIFT) {
 
98
        case TPS6105X_REG0_MODE_SHUTDOWN:
 
99
                dev_info(&tps6105x->client->dev,
 
100
                         "TPS6105x found in SHUTDOWN mode\n");
 
101
                break;
 
102
        case TPS6105X_REG0_MODE_TORCH:
 
103
                dev_info(&tps6105x->client->dev,
 
104
                         "TPS6105x found in TORCH mode\n");
 
105
                break;
 
106
        case TPS6105X_REG0_MODE_TORCH_FLASH:
 
107
                dev_info(&tps6105x->client->dev,
 
108
                         "TPS6105x found in FLASH mode\n");
 
109
                break;
 
110
        case TPS6105X_REG0_MODE_VOLTAGE:
 
111
                dev_info(&tps6105x->client->dev,
 
112
                         "TPS6105x found in VOLTAGE mode\n");
 
113
                break;
 
114
        default:
 
115
                break;
 
116
        }
 
117
 
 
118
        return ret;
 
119
}
 
120
 
 
121
/*
 
122
 * MFD cells - we have one cell which is selected operation
 
123
 * mode, and we always have a GPIO cell.
 
124
 */
 
125
static struct mfd_cell tps6105x_cells[] = {
 
126
        {
 
127
                /* name will be runtime assigned */
 
128
                .id = -1,
 
129
        },
 
130
        {
 
131
                .name = "tps6105x-gpio",
 
132
                .id = -1,
 
133
        },
 
134
};
 
135
 
 
136
static int __devinit tps6105x_probe(struct i2c_client *client,
 
137
                        const struct i2c_device_id *id)
 
138
{
 
139
        struct tps6105x                 *tps6105x;
 
140
        struct tps6105x_platform_data   *pdata;
 
141
        int ret;
 
142
        int i;
 
143
 
 
144
        tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL);
 
145
        if (!tps6105x)
 
146
                return -ENOMEM;
 
147
 
 
148
        i2c_set_clientdata(client, tps6105x);
 
149
        tps6105x->client = client;
 
150
        pdata = client->dev.platform_data;
 
151
        tps6105x->pdata = pdata;
 
152
        mutex_init(&tps6105x->lock);
 
153
 
 
154
        ret = tps6105x_startup(tps6105x);
 
155
        if (ret) {
 
156
                dev_err(&client->dev, "chip initialization failed\n");
 
157
                goto fail;
 
158
        }
 
159
 
 
160
        /* Remove warning texts when you implement new cell drivers */
 
161
        switch (pdata->mode) {
 
162
        case TPS6105X_MODE_SHUTDOWN:
 
163
                dev_info(&client->dev,
 
164
                         "present, not used for anything, only GPIO\n");
 
165
                break;
 
166
        case TPS6105X_MODE_TORCH:
 
167
                tps6105x_cells[0].name = "tps6105x-leds";
 
168
                dev_warn(&client->dev,
 
169
                         "torch mode is unsupported\n");
 
170
                break;
 
171
        case TPS6105X_MODE_TORCH_FLASH:
 
172
                tps6105x_cells[0].name = "tps6105x-flash";
 
173
                dev_warn(&client->dev,
 
174
                         "flash mode is unsupported\n");
 
175
                break;
 
176
        case TPS6105X_MODE_VOLTAGE:
 
177
                tps6105x_cells[0].name ="tps6105x-regulator";
 
178
                break;
 
179
        default:
 
180
                break;
 
181
        }
 
182
 
 
183
        /* Set up and register the platform devices. */
 
184
        for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) {
 
185
                /* One state holder for all drivers, this is simple */
 
186
                tps6105x_cells[i].platform_data = tps6105x;
 
187
                tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
 
188
        }
 
189
 
 
190
        ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
 
191
                ARRAY_SIZE(tps6105x_cells), NULL, 0);
 
192
        if (ret)
 
193
                goto fail;
 
194
 
 
195
        return 0;
 
196
 
 
197
fail:
 
198
        kfree(tps6105x);
 
199
        return ret;
 
200
}
 
201
 
 
202
static int __devexit tps6105x_remove(struct i2c_client *client)
 
203
{
 
204
        struct tps6105x *tps6105x = i2c_get_clientdata(client);
 
205
 
 
206
        mfd_remove_devices(&client->dev);
 
207
 
 
208
        /* Put chip in shutdown mode */
 
209
        tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
 
210
                TPS6105X_REG0_MODE_MASK,
 
211
                TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
 
212
 
 
213
        kfree(tps6105x);
 
214
        return 0;
 
215
}
 
216
 
 
217
static const struct i2c_device_id tps6105x_id[] = {
 
218
        { "tps61050", 0 },
 
219
        { "tps61052", 0 },
 
220
        { }
 
221
};
 
222
MODULE_DEVICE_TABLE(i2c, tps6105x_id);
 
223
 
 
224
static struct i2c_driver tps6105x_driver = {
 
225
        .driver = {
 
226
                .name   = "tps6105x",
 
227
        },
 
228
        .probe          = tps6105x_probe,
 
229
        .remove         = __devexit_p(tps6105x_remove),
 
230
        .id_table       = tps6105x_id,
 
231
};
 
232
 
 
233
static int __init tps6105x_init(void)
 
234
{
 
235
        return i2c_add_driver(&tps6105x_driver);
 
236
}
 
237
subsys_initcall(tps6105x_init);
 
238
 
 
239
static void __exit tps6105x_exit(void)
 
240
{
 
241
        i2c_del_driver(&tps6105x_driver);
 
242
}
 
243
module_exit(tps6105x_exit);
 
244
 
 
245
MODULE_AUTHOR("Linus Walleij");
 
246
MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver");
 
247
MODULE_LICENSE("GPL v2");