2 * Copyright (C) 2007-2010 Motorola, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 #include <linux/miscdevice.h>
21 #include <linux/platform_device.h>
22 #include <linux/regulator/machine.h>
23 #include <linux/spi/spi.h>
24 #include <linux/spi/cpcap.h>
25 #include <linux/spi/cpcap-regbits.h>
26 #include <linux/uaccess.h>
27 #include <linux/reboot.h>
28 #include <linux/notifier.h>
29 #include <linux/delay.h>
32 struct cpcap_driver_info {
33 struct list_head list;
34 struct platform_device *pdev;
37 static long ioctl(struct file *file, unsigned int cmd, unsigned long arg);
38 static int __devinit cpcap_probe(struct spi_device *spi);
39 static int __devexit cpcap_remove(struct spi_device *spi);
42 static int cpcap_suspend(struct spi_device *spi, pm_message_t mesg);
43 static int cpcap_resume(struct spi_device *spi);
46 const static struct file_operations cpcap_fops = {
48 .unlocked_ioctl = ioctl,
51 static struct miscdevice cpcap_dev = {
52 .minor = MISC_DYNAMIC_MINOR,
53 .name = CPCAP_DEV_NAME,
57 static struct spi_driver cpcap_driver = {
64 .remove = __devexit_p(cpcap_remove),
66 .suspend = cpcap_suspend,
67 .resume = cpcap_resume,
71 static struct platform_device cpcap_adc_device = {
74 .dev.platform_data = NULL,
78 static struct platform_device cpcap_key_device = {
81 .dev.platform_data = NULL,
84 static struct platform_device cpcap_uc_device = {
87 .dev.platform_data = NULL,
90 static struct platform_device cpcap_rtc_device = {
93 .dev.platform_data = NULL,
96 /* List of required CPCAP devices that will ALWAYS be present.
98 * DO NOT ADD NEW DEVICES TO THIS LIST! You must use cpcap_driver_register()
99 * for any new drivers for non-core functionality of CPCAP.
101 static struct platform_device *cpcap_devices[] = {
108 static struct cpcap_device *misc_cpcap;
110 static LIST_HEAD(cpcap_device_list);
111 static DEFINE_MUTEX(cpcap_driver_lock);
113 static int cpcap_reboot(struct notifier_block *this, unsigned long code,
117 int result = NOTIFY_DONE;
119 /* Disable the USB transceiver */
120 ret = cpcap_regacc_write(misc_cpcap, CPCAP_REG_USBC2, 0,
121 CPCAP_BIT_USBXCVREN);
124 dev_err(&(misc_cpcap->spi->dev),
125 "Disable Transciever failure.\n");
129 if (code == SYS_RESTART)
130 cpcap_regacc_write(misc_cpcap, CPCAP_REG_MI2, 0, 0xFFFF);
132 /* Always clear the power cut bit on SW Shutdown*/
133 ret = cpcap_regacc_write(misc_cpcap, CPCAP_REG_PC1,
134 0, CPCAP_BIT_PC1_PCEN);
136 dev_err(&(misc_cpcap->spi->dev),
137 "Clear Power Cut bit failure.\n");
141 /* Clear the charger and charge path settings to avoid a false turn on
142 * event in caused by CPCAP. After clearing these settings, 100ms is
143 * needed to before SYSRSTRTB is pulled low to avoid the false turn on
146 cpcap_regacc_write(misc_cpcap, CPCAP_REG_CRM, 0, 0x3FFF);
151 static struct notifier_block cpcap_reboot_notifier = {
152 .notifier_call = cpcap_reboot,
155 static int __init cpcap_init(void)
157 return spi_register_driver(&cpcap_driver);
160 static void cpcap_vendor_read(struct cpcap_device *cpcap)
162 unsigned short value;
164 (void)cpcap_regacc_read(cpcap, CPCAP_REG_VERSC1, &value);
166 cpcap->vendor = (enum cpcap_vendor)((value >> 6) & 0x0007);
167 cpcap->revision = (enum cpcap_revision)(((value >> 3) & 0x0007) |
168 ((value << 3) & 0x0038));
172 int cpcap_device_unregister(struct platform_device *pdev)
174 struct cpcap_driver_info *info;
175 struct cpcap_driver_info *tmp;
180 mutex_lock(&cpcap_driver_lock);
182 list_for_each_entry_safe(info, tmp, &cpcap_device_list, list) {
183 if (info->pdev == pdev) {
184 list_del(&info->list);
187 * misc_cpcap != NULL suggests pdev
191 printk(KERN_INFO "CPCAP: unregister %s\n",
193 platform_device_unregister(pdev);
201 mutex_unlock(&cpcap_driver_lock);
207 int cpcap_device_register(struct platform_device *pdev)
210 struct cpcap_driver_info *info;
214 info = kzalloc(sizeof(*info), GFP_KERNEL);
216 printk(KERN_ERR "Cannot save device %s\n", pdev->name);
220 mutex_lock(&cpcap_driver_lock);
223 list_add_tail(&info->list, &cpcap_device_list);
225 /* If misc_cpcap is valid, the CPCAP driver has already been probed.
226 * Therefore, call platform_device_register() to probe the device.
229 dev_info(&(misc_cpcap->spi->dev),
230 "Probing CPCAP device %s\n", pdev->name);
233 * platform_data is non-empty indicates
234 * CPCAP client devices need to pass their own data
235 * In that case we put cpcap data in driver_data
237 if (pdev->dev.platform_data != NULL)
238 platform_set_drvdata(pdev, misc_cpcap);
240 pdev->dev.platform_data = misc_cpcap;
241 retval = platform_device_register(pdev);
243 printk(KERN_INFO "CPCAP: delaying %s probe\n",
245 mutex_unlock(&cpcap_driver_lock);
250 static int __devinit cpcap_probe(struct spi_device *spi)
252 int retval = -EINVAL;
253 struct cpcap_device *cpcap;
254 struct cpcap_platform_data *data;
256 struct cpcap_driver_info *info;
258 cpcap = kzalloc(sizeof(*cpcap), GFP_KERNEL);
263 data = spi->controller_data;
264 spi_set_drvdata(spi, cpcap);
266 retval = cpcap_regacc_init(cpcap);
269 retval = cpcap_irq_init(cpcap);
273 cpcap_vendor_read(cpcap);
275 for (i = 0; i < ARRAY_SIZE(cpcap_devices); i++)
276 cpcap_devices[i]->dev.platform_data = cpcap;
278 retval = misc_register(&cpcap_dev);
282 /* loop twice becuase cpcap_regulator_probe may refer to other devices
283 * in this list to handle dependencies between regulators. Create them
284 * all and then add them */
285 for (i = 0; i < CPCAP_NUM_REGULATORS; i++) {
286 struct platform_device *pdev;
288 pdev = platform_device_alloc("cpcap-regltr", i);
290 dev_err(&(spi->dev), "Cannot create regulator\n");
294 pdev->dev.parent = &(spi->dev);
295 pdev->dev.platform_data = &data->regulator_init[i];
296 platform_set_drvdata(pdev, cpcap);
297 cpcap->regulator_pdev[i] = pdev;
300 for (i = 0; i < CPCAP_NUM_REGULATORS; i++)
301 platform_device_add(cpcap->regulator_pdev[i]);
303 platform_add_devices(cpcap_devices, ARRAY_SIZE(cpcap_devices));
305 mutex_lock(&cpcap_driver_lock);
306 misc_cpcap = cpcap; /* kept for misc device */
308 list_for_each_entry(info, &cpcap_device_list, list) {
309 dev_info(&(spi->dev), "Probing CPCAP device %s\n",
311 if (info->pdev->dev.platform_data != NULL)
312 platform_set_drvdata(info->pdev, cpcap);
314 info->pdev->dev.platform_data = cpcap;
315 platform_device_register(info->pdev);
317 mutex_unlock(&cpcap_driver_lock);
319 register_reboot_notifier(&cpcap_reboot_notifier);
324 cpcap_irq_shutdown(cpcap);
330 static int __devexit cpcap_remove(struct spi_device *spi)
332 struct cpcap_device *cpcap = spi_get_drvdata(spi);
333 struct cpcap_driver_info *info;
336 unregister_reboot_notifier(&cpcap_reboot_notifier);
338 mutex_lock(&cpcap_driver_lock);
339 list_for_each_entry(info, &cpcap_device_list, list) {
340 dev_info(&(spi->dev), "Removing CPCAP device %s\n",
342 platform_device_unregister(info->pdev);
345 mutex_unlock(&cpcap_driver_lock);
347 for (i = ARRAY_SIZE(cpcap_devices); i > 0; i--)
348 platform_device_unregister(cpcap_devices[i-1]);
350 for (i = 0; i < CPCAP_NUM_REGULATORS; i++)
351 platform_device_unregister(cpcap->regulator_pdev[i]);
353 misc_deregister(&cpcap_dev);
354 cpcap_irq_shutdown(cpcap);
360 static long test_ioctl(unsigned int cmd, unsigned long arg)
362 int retval = -EINVAL;
363 struct cpcap_regacc read_data;
364 struct cpcap_regacc write_data;
367 case CPCAP_IOCTL_TEST_READ_REG:
368 if (copy_from_user((void *)&read_data, (void *)arg,
371 retval = cpcap_regacc_read(misc_cpcap, read_data.reg,
375 if (copy_to_user((void *)arg, (void *)&read_data,
381 case CPCAP_IOCTL_TEST_WRITE_REG:
382 if (copy_from_user((void *) &write_data,
386 retval = cpcap_regacc_write(misc_cpcap, write_data.reg,
387 write_data.value, write_data.mask);
398 static long adc_ioctl(unsigned int cmd, unsigned long arg)
400 int retval = -EINVAL;
401 struct cpcap_adc_phase phase;
404 case CPCAP_IOCTL_ADC_PHASE:
405 if (copy_from_user((void *) &phase, (void *) arg,
409 cpcap_adc_phase(misc_cpcap, &phase);
421 static long accy_ioctl(unsigned int cmd, unsigned long arg)
423 int retval = -EINVAL;
424 struct cpcap_whisper_request read_data;
427 case CPCAP_IOCTL_ACCY_WHISPER:
428 if (copy_from_user((void *) &read_data, (void *) arg,
431 read_data.dock_id[CPCAP_WHISPER_ID_SIZE - 1] = '\0';
432 read_data.dock_prop[CPCAP_WHISPER_PROP_SIZE - 1] = '\0';
433 retval = cpcap_accy_whisper(misc_cpcap, &read_data);
444 static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
446 int retval = -ENOTTY;
447 unsigned int cmd_num;
449 cmd_num = _IOC_NR(cmd);
451 if ((cmd_num > CPCAP_IOCTL_NUM_TEST__START) &&
452 (cmd_num < CPCAP_IOCTL_NUM_TEST__END)) {
453 retval = test_ioctl(cmd, arg);
455 if ((cmd_num > CPCAP_IOCTL_NUM_ADC__START) &&
456 (cmd_num < CPCAP_IOCTL_NUM_ADC__END)) {
457 retval = adc_ioctl(cmd, arg);
459 if ((cmd_num > CPCAP_IOCTL_NUM_ACCY__START) &&
460 (cmd_num < CPCAP_IOCTL_NUM_ACCY__END)) {
461 retval = accy_ioctl(cmd, arg);
467 static void cpcap_shutdown(void)
469 spi_unregister_driver(&cpcap_driver);
473 static int cpcap_suspend(struct spi_device *spi, pm_message_t mesg)
476 struct cpcap_device *cpcap = spi_get_drvdata(spi);
478 return cpcap_irq_suspend(cpcap);
481 static int cpcap_resume(struct spi_device *spi)
483 struct cpcap_device *cpcap = spi_get_drvdata(spi);
485 return cpcap_irq_resume(cpcap);
489 subsys_initcall(cpcap_init);
490 module_exit(cpcap_shutdown);
492 MODULE_ALIAS("platform:cpcap");
493 MODULE_DESCRIPTION("CPCAP driver");
494 MODULE_AUTHOR("Motorola");
495 MODULE_LICENSE("GPL");