/* * Copyright (C) ST-Ericsson SA 2010 * * License Terms: GNU General Public License v2 * Author: Srinidhi Kasagar */ #include #include #include #include #include #include #include /* * This funtion writes to any AB8500 registers using * SPI protocol & before it writes it packs the data * in the below 24 bit frame format * * *|------------------------------------| * *| 23|22...18|17.......10|9|8|7......0| * *| r/w bank adr data | * * ------------------------------------ * * This function shouldn't be called from interrupt * context */ static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data) { struct spi_device *spi = container_of(ab8500->dev, struct spi_device, dev); unsigned long spi_data = addr << 10 | data; struct spi_transfer xfer; struct spi_message msg; ab8500->tx_buf[0] = spi_data; ab8500->rx_buf[0] = 0; xfer.tx_buf = ab8500->tx_buf; xfer.rx_buf = NULL; xfer.len = sizeof(unsigned long); spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); return spi_sync(spi, &msg); } static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr) { struct spi_device *spi = container_of(ab8500->dev, struct spi_device, dev); unsigned long spi_data = 1 << 23 | addr << 10; struct spi_transfer xfer; struct spi_message msg; int ret; ab8500->tx_buf[0] = spi_data; ab8500->rx_buf[0] = 0; xfer.tx_buf = ab8500->tx_buf; xfer.rx_buf = ab8500->rx_buf; xfer.len = sizeof(unsigned long); spi_message_init(&msg); spi_message_add_tail(&xfer, &msg); ret = spi_sync(spi, &msg); if (!ret) /* * Only the 8 lowermost bytes are * defined with value, the rest may * vary depending on chip/board noise. */ ret = ab8500->rx_buf[0] & 0xFFU; return ret; } static int __devinit ab8500_spi_probe(struct spi_device *spi) { struct ab8500 *ab8500; int ret; spi->bits_per_word = 24; ret = spi_setup(spi); if (ret < 0) return ret; ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL); if (!ab8500) return -ENOMEM; ab8500->dev = &spi->dev; ab8500->irq = spi->irq; ab8500->read = ab8500_spi_read; ab8500->write = ab8500_spi_write; spi_set_drvdata(spi, ab8500); ret = ab8500_init(ab8500); if (ret) kfree(ab8500); return ret; } static int __devexit ab8500_spi_remove(struct spi_device *spi) { struct ab8500 *ab8500 = spi_get_drvdata(spi); ab8500_exit(ab8500); kfree(ab8500); return 0; } static struct spi_driver ab8500_spi_driver = { .driver = { .name = "ab8500", .owner = THIS_MODULE, }, .probe = ab8500_spi_probe, .remove = __devexit_p(ab8500_spi_remove) }; static int __init ab8500_spi_init(void) { return spi_register_driver(&ab8500_spi_driver); } subsys_initcall(ab8500_spi_init); static void __exit ab8500_spi_exit(void) { spi_unregister_driver(&ab8500_spi_driver); } module_exit(ab8500_spi_exit); MODULE_AUTHOR("Srinidhi KASAGAR