blob: 9e8786e7603dff2c29c8fc620fda2a8f7a864d21 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/interrupt.h>
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053014#include <linux/platform_device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/slab.h>
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053016#include <linux/delay.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070017#include <linux/mfd/core.h>
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053018#include <linux/msm_ssbi.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070019#include <linux/mfd/pmic8901.h>
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053020#include <linux/mfd/pm8xxx/core.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021
22/* PMIC8901 Revision */
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053023#define PM8901_REG_REV 0x002
24#define PM8901_VERSION_MASK 0xF0
25#define PM8901_REVISION_MASK 0x0F
26#define PM8901_VERSION_VALUE 0xF0
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053028#define REG_IRQ_BASE 0xD5
29#define REG_MPP_BASE 0x27
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053031#define REG_TEMP_ALRM_CTRL 0x23
32#define REG_TEMP_ALRM_PWM 0x24
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070033
34/* FTS regulator PMR registers */
35#define SSBI_REG_ADDR_S1_PMR (0xA7)
36#define SSBI_REG_ADDR_S2_PMR (0xA8)
37#define SSBI_REG_ADDR_S3_PMR (0xA9)
38#define SSBI_REG_ADDR_S4_PMR (0xAA)
39
40#define REGULATOR_PMR_STATE_MASK 0x60
41#define REGULATOR_PMR_STATE_OFF 0x20
42
David Collins88ebc9c2011-11-15 08:46:08 -080043/* Shutdown/restart delays to allow for LDO 7/dVdd regulator load settling. */
44#define DELAY_AFTER_REG_DISABLE_MS 4
45#define DELAY_BEFORE_SHUTDOWN_MS 8
46
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053047#define SINGLE_IRQ_RESOURCE(_name, _irq) \
48{ \
49 .name = _name, \
50 .start = _irq, \
51 .end = _irq, \
52 .flags = IORESOURCE_IRQ, \
53}
54
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055struct pm8901_chip {
56 struct pm8901_platform_data pdata;
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053057 struct device *dev;
Anirudh Ghayal9f77e962011-12-06 12:38:21 +053058 struct pm_irq_chip *irq_chip;
59 struct mfd_cell *mfd_regulators;
60 u8 revision;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070061};
62
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063static struct pm8901_chip *pmic_chip;
64
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065static inline int
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053066ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070067{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053068 return msm_ssbi_read(dev->parent, addr, buf, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070069}
70
71static inline int
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053072ssbi_write(struct device *dev, u16 addr, u8 *buf, size_t len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070073{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053074 return msm_ssbi_write(dev->parent, addr, buf, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075}
76
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070077int pm8901_reset_pwr_off(int reset)
78{
79 int rc = 0, i;
80 u8 pmr;
81 u8 pmr_addr[4] = {
82 SSBI_REG_ADDR_S2_PMR,
83 SSBI_REG_ADDR_S3_PMR,
84 SSBI_REG_ADDR_S4_PMR,
85 SSBI_REG_ADDR_S1_PMR,
86 };
87
88 if (pmic_chip == NULL)
89 return -ENODEV;
90
91 /* Turn off regulators S1, S2, S3, S4 when shutting down. */
92 if (!reset) {
93 for (i = 0; i < 4; i++) {
94 rc = ssbi_read(pmic_chip->dev, pmr_addr[i], &pmr, 1);
95 if (rc) {
96 pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
97 __func__, pmr_addr[i], rc);
98 goto get_out;
99 }
100
101 pmr &= ~REGULATOR_PMR_STATE_MASK;
102 pmr |= REGULATOR_PMR_STATE_OFF;
103
104 rc = ssbi_write(pmic_chip->dev, pmr_addr[i], &pmr, 1);
105 if (rc) {
106 pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d"
107 "\n", __func__, pmr_addr[i], pmr, rc);
108 goto get_out;
109 }
David Collins88ebc9c2011-11-15 08:46:08 -0800110 mdelay(DELAY_AFTER_REG_DISABLE_MS);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700111 }
112 }
113
114get_out:
David Collins88ebc9c2011-11-15 08:46:08 -0800115 mdelay(DELAY_BEFORE_SHUTDOWN_MS);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700116 return rc;
117}
118EXPORT_SYMBOL(pm8901_reset_pwr_off);
119
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530120static int pm8901_readb(const struct device *dev, u16 addr, u8 *val)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530122 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
123 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530125 return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126}
127
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530128static int pm8901_writeb(const struct device *dev, u16 addr, u8 val)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700129{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530130 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
131 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700132
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530133 return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134}
135
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530136static int pm8901_read_buf(const struct device *dev, u16 addr, u8 *buf,
137 int cnt)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530139 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
140 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530142 return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143}
144
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530145static int pm8901_write_buf(const struct device *dev, u16 addr, u8 *buf,
146 int cnt)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700147{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530148 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
149 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530151 return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152}
153
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530154static int pm8901_read_irq_stat(const struct device *dev, int irq)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530156 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
157 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530159 return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160
161 return 0;
162}
163
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530164static enum pm8xxx_version pm8901_get_version(const struct device *dev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530166 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
167 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
168 enum pm8xxx_version version = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530170 if ((pmic->revision & PM8901_VERSION_MASK) == PM8901_VERSION_VALUE)
171 version = PM8XXX_VERSION_8901;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700172
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530173 return version;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174}
175
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530176static int pm8901_get_revision(const struct device *dev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700177{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530178 const struct pm8xxx_drvdata *pm8901_drvdata = dev_get_drvdata(dev);
179 const struct pm8901_chip *pmic = pm8901_drvdata->pm_chip_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530181 return pmic->revision & PM8901_REVISION_MASK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182}
183
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530184static struct pm8xxx_drvdata pm8901_drvdata = {
185 .pmic_readb = pm8901_readb,
186 .pmic_writeb = pm8901_writeb,
187 .pmic_read_buf = pm8901_read_buf,
188 .pmic_write_buf = pm8901_write_buf,
189 .pmic_read_irq_stat = pm8901_read_irq_stat,
190 .pmic_get_version = pm8901_get_version,
191 .pmic_get_revision = pm8901_get_revision,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700192};
193
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530194static struct mfd_cell debugfs_cell = {
195 .name = "pm8xxx-debug",
196 .id = 1,
197 .platform_data = "pm8901-dbg",
198 .pdata_size = sizeof("pm8901-dbg"),
199};
200
201static const struct resource thermal_alarm_cell_resources[] = {
202 SINGLE_IRQ_RESOURCE("pm8901_tempstat_irq", PM8901_TEMPSTAT_IRQ),
203 SINGLE_IRQ_RESOURCE("pm8901_overtemp_irq", PM8901_OVERTEMP_IRQ),
204};
205
206static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
207 .adc_type = PM8XXX_TM_ADC_NONE,
208 .reg_addr_temp_alarm_ctrl = REG_TEMP_ALRM_CTRL,
209 .reg_addr_temp_alarm_pwm = REG_TEMP_ALRM_PWM,
210 .tm_name = "pm8901_tz",
211 .irq_name_temp_stat = "pm8901_tempstat_irq",
212 .irq_name_over_temp = "pm8901_overtemp_irq",
213};
214
215static struct mfd_cell thermal_alarm_cell = {
216 .name = PM8XXX_TM_DEV_NAME,
217 .id = 1,
218 .resources = thermal_alarm_cell_resources,
219 .num_resources = ARRAY_SIZE(thermal_alarm_cell_resources),
220 .platform_data = &thermal_alarm_cdata,
221 .pdata_size = sizeof(struct pm8xxx_tm_core_data),
222};
223
224static const struct resource mpp_cell_resources[] = {
225 {
226 .start = PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0),
227 .end = PM8901_IRQ_BLOCK_BIT(PM8901_MPP_BLOCK_START, 0)
228 + PM8901_MPPS - 1,
229 .flags = IORESOURCE_IRQ,
230 },
231};
232
233static struct mfd_cell mpp_cell = {
234 .name = PM8XXX_MPP_DEV_NAME,
235 .id = 1,
236 .resources = mpp_cell_resources,
237 .num_resources = ARRAY_SIZE(mpp_cell_resources),
238};
239
240static int __devinit
241pm8901_add_subdevices(const struct pm8901_platform_data *pdata,
242 struct pm8901_chip *pmic)
243{
244 int rc = 0, irq_base = 0, i;
245 struct pm_irq_chip *irq_chip;
246 static struct mfd_cell *mfd_regulators;
247
248 if (pdata->irq_pdata) {
249 pdata->irq_pdata->irq_cdata.nirqs = PM8901_NR_IRQS;
250 pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
251 irq_base = pdata->irq_pdata->irq_base;
252 irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
253
254 if (IS_ERR(irq_chip)) {
255 pr_err("Failed to init interrupts ret=%ld\n",
256 PTR_ERR(irq_chip));
257 return PTR_ERR(irq_chip);
258 }
259 pmic->irq_chip = irq_chip;
260 }
261
262 if (pdata->mpp_pdata) {
263 pdata->mpp_pdata->core_data.nmpps = PM8901_MPPS;
264 pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE;
265 mpp_cell.platform_data = pdata->mpp_pdata;
266 mpp_cell.pdata_size = sizeof(struct pm8xxx_mpp_platform_data);
267 rc = mfd_add_devices(pmic->dev, 0, &mpp_cell, 1, NULL,
268 irq_base);
269 if (rc) {
270 pr_err("Failed to add mpp subdevice ret=%d\n", rc);
271 goto bail;
272 }
273 }
274
275 if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
276 mfd_regulators = kzalloc(sizeof(struct mfd_cell)
277 * (pdata->num_regulators), GFP_KERNEL);
278 if (!mfd_regulators) {
279 pr_err("Cannot allocate %d bytes for pm8901 regulator "
280 "mfd cells\n", sizeof(struct mfd_cell)
281 * (pdata->num_regulators));
282 rc = -ENOMEM;
283 goto bail;
284 }
285 for (i = 0; i < pdata->num_regulators; i++) {
286 mfd_regulators[i].name = "pm8901-regulator";
287 mfd_regulators[i].id = pdata->regulator_pdatas[i].id;
288 mfd_regulators[i].platform_data =
289 &(pdata->regulator_pdatas[i]);
290 mfd_regulators[i].pdata_size =
291 sizeof(struct pm8901_vreg_pdata);
292 }
293 rc = mfd_add_devices(pmic->dev, 0, mfd_regulators,
294 pdata->num_regulators, NULL, irq_base);
295 if (rc) {
296 pr_err("Failed to add regulator subdevices ret=%d\n",
297 rc);
298 kfree(mfd_regulators);
299 goto bail;
300 }
301 pmic->mfd_regulators = mfd_regulators;
302 }
303
304 rc = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
305 irq_base);
306 if (rc) {
307 pr_err("Failed to add thermal alarm subdevice ret=%d\n",
308 rc);
309 goto bail;
310 }
311
312 rc = mfd_add_devices(pmic->dev, 0, &debugfs_cell, 1, NULL, irq_base);
313 if (rc) {
314 pr_err("Failed to add debugfs subdevice ret=%d\n", rc);
315 goto bail;
316 }
317
318 return rc;
319
320bail:
321 if (pmic->irq_chip) {
322 pm8xxx_irq_exit(pmic->irq_chip);
323 pmic->irq_chip = NULL;
324 }
325 return rc;
326}
327
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530328static int pm8901_probe(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700329{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530330 int rc;
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530331 struct pm8901_platform_data *pdata = pdev->dev.platform_data;
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530332 struct pm8901_chip *pmic;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700333
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530334 if (pdata == NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700335 pr_err("%s: No platform_data or IRQ.\n", __func__);
336 return -ENODEV;
337 }
338
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530339 pmic = kzalloc(sizeof *pmic, GFP_KERNEL);
340 if (pmic == NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341 pr_err("%s: kzalloc() failed.\n", __func__);
342 return -ENOMEM;
343 }
344
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530345 pmic->dev = &pdev->dev;
346
347 pm8901_drvdata.pm_chip_data = pmic;
348 platform_set_drvdata(pdev, &pm8901_drvdata);
349 pmic_chip = pmic;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700350
351 /* Read PMIC chip revision */
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530352 rc = pm8901_readb(pmic->dev, PM8901_REG_REV, &pmic->revision);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353 if (rc)
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530354 pr_err("%s: Failed reading version register rc=%d.\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355 __func__, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700356
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530357 pr_info("%s: PMIC REVISION = %X\n", __func__, pmic->revision);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700358
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530359 (void) memcpy((void *)&pmic->pdata, (const void *)pdata,
360 sizeof(pmic->pdata));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700361
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530362 rc = pm8901_add_subdevices(pdata, pmic);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700363 if (rc) {
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530364 pr_err("Cannot add subdevices rc=%d\n", rc);
365 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 }
367
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530368 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530370err:
371 platform_set_drvdata(pdev, NULL);
372 kfree(pmic);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700373 return rc;
374}
375
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530376static int __devexit pm8901_remove(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377{
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530378 struct pm8xxx_drvdata *drvdata;
379 struct pm8901_chip *pmic = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530381 drvdata = platform_get_drvdata(pdev);
382 if (drvdata)
383 pmic = drvdata->pm_chip_data;
384 if (pmic) {
385 if (pmic->dev)
386 mfd_remove_devices(pmic->dev);
387 if (pmic->irq_chip)
388 pm8xxx_irq_exit(pmic->irq_chip);
389 kfree(pmic->mfd_regulators);
390 kfree(pmic);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700391 }
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530392 platform_set_drvdata(pdev, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700393
394 return 0;
395}
396
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530397static struct platform_driver pm8901_driver = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 .probe = pm8901_probe,
399 .remove = __devexit_p(pm8901_remove),
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530400 .driver = {
401 .name = "pm8901-core",
402 .owner = THIS_MODULE,
403 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404};
405
406static int __init pm8901_init(void)
407{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530408 return platform_driver_register(&pm8901_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409}
Anirudh Ghayal9f77e962011-12-06 12:38:21 +0530410postcore_initcall(pm8901_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700411
412static void __exit pm8901_exit(void)
413{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530414 platform_driver_unregister(&pm8901_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416module_exit(pm8901_exit);
417
418MODULE_LICENSE("GPL v2");
419MODULE_DESCRIPTION("PMIC8901 core driver");
420MODULE_VERSION("1.0");
421MODULE_ALIAS("platform:pmic8901-core");