diff options
Diffstat (limited to 'drivers/mfd/da9052-core.c')
-rwxr-xr-x | drivers/mfd/da9052-core.c | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 8b4a658ceb50..928b1074748b 100755 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -2,6 +2,7 @@ * da9052-core.c -- Device access for Dialog DA9052 * * Copyright(c) 2009 Dialog Semiconductor Ltd. + * Copyright (C) 2012 Freescale Semiconductor, Inc. * * Author: Dialog Semiconductor Ltd <dchen@diasemi.com> * @@ -34,6 +35,7 @@ struct da9052_eh_nb eve_nb_array[EVE_CNT]; static struct da9052_ssc_ops ssc_ops; struct mutex manconv_lock; static struct semaphore eve_nb_array_lock; +static struct da9052 *da9052_data; void da9052_lock(struct da9052 *da9052) { @@ -248,17 +250,16 @@ static int process_events(struct da9052 *da9052, int events_sts) /* Check if interrupt is received for this event */ if (!((tmp_events_sts >> cnt) & 0x1)) /* Event bit is not set for this event */ - /* Move to next event */ + /* Move to next priority event */ continue; if (event == PEN_DOWN_EVE) { if (list_empty(&(eve_nb_array[event].nb_list))) continue; } - /* Event bit is set, execute all registered call backs */ if (down_interruptible(&eve_nb_array_lock)){ - printk(KERN_CRIT "Can't acquire eve_nb_array_lock \n"); + printk(KERN_CRIT "Can't acquire eve_nb_array_lock\n"); return -EIO; } @@ -281,14 +282,11 @@ void eh_workqueue_isr(struct work_struct *work) container_of(work, struct da9052, eh_isr_work); struct da9052_ssc_msg eve_data[4]; - struct da9052_ssc_msg eve_mask_data[4]; int events_sts, ret; - u32 mask; unsigned char cnt = 0; /* nIRQ is asserted, read event registeres to know what happened */ events_sts = 0; - mask = 0; /* Prepare ssc message to read all four event registers */ for (cnt = 0; cnt < DA9052_EVE_REGISTERS; cnt++) { @@ -296,13 +294,7 @@ void eh_workqueue_isr(struct work_struct *work) eve_data[cnt].data = 0; } - /* Prepare ssc message to read all four event registers */ - for (cnt = 0; cnt < DA9052_EVE_REGISTERS; cnt++) { - eve_mask_data[cnt].addr = (DA9052_IRQMASKA_REG + cnt); - eve_mask_data[cnt].data = 0; - } - - /* Now read all event and mask registers */ + /* Now read all event registers */ da9052_lock(da9052); ret = da9052_ssc_read_many(da9052,eve_data, DA9052_EVE_REGISTERS); @@ -312,22 +304,10 @@ void eh_workqueue_isr(struct work_struct *work) return; } - ret = da9052_ssc_read_many(da9052,eve_mask_data, DA9052_EVE_REGISTERS); - if (ret) { - enable_irq(da9052->irq); - da9052_unlock(da9052); - return; - } /* Collect all events */ for (cnt = 0; cnt < DA9052_EVE_REGISTERS; cnt++) - events_sts |= (eve_data[cnt].data << (DA9052_EVE_REGISTER_SIZE - * cnt)); - /* Collect all mask */ - for (cnt = 0; cnt < DA9052_EVE_REGISTERS; cnt++) - mask |= (eve_mask_data[cnt].data << (DA9052_EVE_REGISTER_SIZE - * cnt)); - events_sts &= ~mask; - da9052_unlock(da9052); + events_sts |= ((eve_data[cnt].data&0xff) << + (DA9052_EVE_REGISTER_SIZE * cnt)); /* Check if we really got any event */ if (events_sts == 0) { @@ -335,6 +315,7 @@ void eh_workqueue_isr(struct work_struct *work) da9052_unlock(da9052); return; } + da9052_unlock(da9052); /* Process all events occurred */ process_events(da9052, events_sts); @@ -376,7 +357,7 @@ static int da9052_add_subdevice_pdata(struct da9052 *da9052, struct mfd_cell cell = { .name = name, .platform_data = pdata, - .data_size = pdata_size, + .pdata_size = pdata_size, }; return mfd_add_devices(da9052->dev, -1, &cell, 1, NULL, 0); } @@ -399,6 +380,7 @@ static int add_da9052_devices(struct da9052 *da9052) }; struct da9052_tsi_platform_data tsi_data = *(pdata->tsi_data); + struct da9052_bat_platform_data bat_data = *(pdata->bat_data); if (pdata && pdata->init) { ret = pdata->init(da9052); @@ -406,7 +388,6 @@ static int add_da9052_devices(struct da9052 *da9052) return ret; } else pr_err("No platform initialisation supplied\n"); - ret = da9052_add_subdevice(da9052, "da9052-rtc"); if (ret) return ret; @@ -449,7 +430,8 @@ static int add_da9052_devices(struct da9052 *da9052) if (ret) return ret; - ret = da9052_add_subdevice(da9052, "da9052-bat"); + ret = da9052_add_subdevice_pdata(da9052, "da9052-bat", + &bat_data, sizeof(bat_data)); if (ret) return ret; @@ -493,6 +475,7 @@ int da9052_ssc_init(struct da9052 *da9052) ssc_ops.read_many = da9052_i2c_read_many; } else return -1; + /* Assign the EH notifier block register/de-register functions */ da9052->register_event_notifier = eh_register_nb; da9052->unregister_event_notifier = eh_unregister_nb; @@ -504,16 +487,34 @@ int da9052_ssc_init(struct da9052 *da9052) add_da9052_devices(da9052); INIT_WORK(&da9052->eh_isr_work, eh_workqueue_isr); + ssc_msg.addr = DA9052_IRQMASKA_REG; ssc_msg.data = 0xff; da9052->write(da9052, &ssc_msg); ssc_msg.addr = DA9052_IRQMASKC_REG; ssc_msg.data = 0xff; da9052->write(da9052, &ssc_msg); + + /* read chip version */ + ssc_msg.addr = DA9052_CHIPID_REG; + da9052->read(da9052, &ssc_msg); + pr_info("DA9053 chip ID reg read=0x%x ", ssc_msg.data); + if ((ssc_msg.data & DA9052_CHIPID_MRC) == 0x80) { + da9052->chip_version = DA9053_VERSION_AA; + pr_info("AA version probed\n"); + } else if ((ssc_msg.data & DA9052_CHIPID_MRC) == 0xa0) { + da9052->chip_version = DA9053_VERSION_BB; + pr_info("BB version probed\n"); + } else { + da9052->chip_version = 0; + pr_info("unknown chip version\n"); + } + if (request_irq(da9052->irq, da9052_eh_isr, IRQ_TYPE_LEVEL_LOW, DA9052_EH_DEVICE_NAME, da9052)) return -EIO; enable_irq_wake(da9052->irq); + da9052_data = da9052; return 0; } @@ -530,6 +531,27 @@ void da9052_ssc_exit(struct da9052 *da9052) return; } +void da9053_power_off(void) +{ + struct da9052_ssc_msg ssc_msg; + struct da9052_ssc_msg ssc_msg_dummy[2]; + if (!da9052_data) + return; + + ssc_msg.addr = DA9052_CONTROLB_REG; + da9052_data->read(da9052_data, &ssc_msg); + ssc_msg_dummy[0].addr = DA9052_CONTROLB_REG; + ssc_msg_dummy[0].data = ssc_msg.data | DA9052_CONTROLB_SHUTDOWN; + ssc_msg_dummy[1].addr = DA9052_GPID9_REG; + ssc_msg_dummy[1].data = 0; + da9052_data->write_many(da9052_data, &ssc_msg_dummy[0], 2); +} + +int da9053_get_chip_version(void) +{ + return da9052_data->chip_version; +} + MODULE_AUTHOR("Dialog Semiconductor Ltd <dchen@diasemi.com>"); MODULE_DESCRIPTION("DA9052 MFD Core"); MODULE_LICENSE("GPL v2"); |