1 /* 2 * Copyright 2009-2010 Pengutronix 3 * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> 4 * 5 * loosely based on an earlier driver that has 6 * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> 7 * 8 * This program is free software; you can redistribute it and/or modify it under 9 * the terms of the GNU General Public License version 2 as published by the 10 * Free Software Foundation. 11 */ 12 13 #include <linux/slab.h> 14 #include <linux/module.h> 15 #include <linux/platform_device.h> 16 #include <linux/mutex.h> 17 #include <linux/interrupt.h> 18 #include <linux/mfd/core.h> 19 #include <linux/mfd/mc13xxx.h> 20 #include <linux/of.h> 21 #include <linux/of_device.h> 22 #include <linux/of_gpio.h> 23 #include <linux/err.h> 24 #include <linux/spi/spi.h> 25 26 #include "mc13xxx.h" 27 28 static const struct spi_device_id mc13xxx_device_id[] = { 29 { 30 .name = "mc13783", 31 .driver_data = MC13XXX_ID_MC13783, 32 }, { 33 .name = "mc13892", 34 .driver_data = MC13XXX_ID_MC13892, 35 }, { 36 /* sentinel */ 37 } 38 }; 39 MODULE_DEVICE_TABLE(spi, mc13xxx_device_id); 40 41 static const struct of_device_id mc13xxx_dt_ids[] = { 42 { .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, }, 43 { .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, }, 44 { /* sentinel */ } 45 }; 46 MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids); 47 48 static struct regmap_config mc13xxx_regmap_spi_config = { 49 .reg_bits = 7, 50 .pad_bits = 1, 51 .val_bits = 24, 52 53 .max_register = MC13XXX_NUMREGS, 54 55 .cache_type = REGCACHE_NONE, 56 }; 57 58 static int mc13xxx_spi_probe(struct spi_device *spi) 59 { 60 const struct of_device_id *of_id; 61 struct spi_driver *sdrv = to_spi_driver(spi->dev.driver); 62 struct mc13xxx *mc13xxx; 63 struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev); 64 int ret; 65 66 of_id = of_match_device(mc13xxx_dt_ids, &spi->dev); 67 if (of_id) 68 sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data]; 69 70 mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); 71 if (!mc13xxx) 72 return -ENOMEM; 73 74 dev_set_drvdata(&spi->dev, mc13xxx); 75 spi->mode = SPI_MODE_0 | SPI_CS_HIGH; 76 spi->bits_per_word = 32; 77 78 mc13xxx->dev = &spi->dev; 79 mutex_init(&mc13xxx->lock); 80 81 mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config); 82 if (IS_ERR(mc13xxx->regmap)) { 83 ret = PTR_ERR(mc13xxx->regmap); 84 dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", 85 ret); 86 dev_set_drvdata(&spi->dev, NULL); 87 kfree(mc13xxx); 88 return ret; 89 } 90 91 ret = mc13xxx_common_init(mc13xxx, pdata, spi->irq); 92 93 if (ret) { 94 dev_set_drvdata(&spi->dev, NULL); 95 } else { 96 const struct spi_device_id *devid = 97 spi_get_device_id(spi); 98 if (!devid || devid->driver_data != mc13xxx->ictype) 99 dev_warn(mc13xxx->dev, 100 "device id doesn't match auto detection!\n"); 101 } 102 103 return ret; 104 } 105 106 static int __devexit mc13xxx_spi_remove(struct spi_device *spi) 107 { 108 struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev); 109 110 mc13xxx_common_cleanup(mc13xxx); 111 112 return 0; 113 } 114 115 static struct spi_driver mc13xxx_spi_driver = { 116 .id_table = mc13xxx_device_id, 117 .driver = { 118 .name = "mc13xxx", 119 .owner = THIS_MODULE, 120 .of_match_table = mc13xxx_dt_ids, 121 }, 122 .probe = mc13xxx_spi_probe, 123 .remove = __devexit_p(mc13xxx_spi_remove), 124 }; 125 126 static int __init mc13xxx_init(void) 127 { 128 return spi_register_driver(&mc13xxx_spi_driver); 129 } 130 subsys_initcall(mc13xxx_init); 131 132 static void __exit mc13xxx_exit(void) 133 { 134 spi_unregister_driver(&mc13xxx_spi_driver); 135 } 136 module_exit(mc13xxx_exit); 137 138 MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC"); 139 MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); 140 MODULE_LICENSE("GPL v2"); 141