From mboxrd@z Thu Jan 1 00:00:00 1970 From: srinidhi.kasagar@stericsson.com (srinidhi kasagar) Date: Tue, 22 Sep 2009 04:07:10 +0530 Subject: [PATCH 2/3] mfd: add U8500 STw4500 SPI device support Message-ID: <1253572630.21542.46.camel@vinay-desktop> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org From: srinidhi kasagar This adds core driver support for STw4500 mixed signal multimedia & power management chip. This connects to U8500 on the SSP (pl022) bus operating in SPI protocol and exports read/write functions for the device to get access to this chip. Signed-off-by: srinidhi kasagar --- drivers/mfd/Kconfig | 10 ++++ drivers/mfd/Makefile | 1 + drivers/mfd/stw4500.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 0 deletions(-) create mode 100755 drivers/mfd/stw4500.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 491ac0f..e3aec52 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -256,6 +256,16 @@ config AB3100_CORE LEDs, vibrator, system power and temperature, power management and ALSA sound. +config U8500_STW4500 + tristate "ST-Ericsson U8500 Mixed Signal Power management chip" + depends on SPI + default y if ARCH_U8500 + help + Select this option to enable access to STw4500 power management + chip. This connects to U8500 on the SSP/SPI bus and exports + read/write functions for the devices to get access to this chip. + This chip embeds various other multimedia funtionalities as well. + config EZX_PCAP bool "PCAP Support" depends on GENERIC_HARDIRQS && SPI_MASTER diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 6f8a9a1..9b15e52 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o obj-$(CONFIG_AB3100_CORE) += ab3100-core.o +obj-$(CONFIG_U8500_STW4500) += stw4500.o diff --git a/drivers/mfd/stw4500.c b/drivers/mfd/stw4500.c new file mode 100755 index 0000000..a8c1d39 --- /dev/null +++ b/drivers/mfd/stw4500.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009 ST-Ericsson + * + * Author: Srinidhi KASAGAR + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * STw4500 is a companion power management chip used with U8500. On this + * platform, this is interfaced with SSP0 controller which is a ARM + * primecell pl022. + * + * At the moment the module just exports read/write features. + * Interrupt management to be added. + */ +#include +#include +#include +#include +#include + +static struct spi_driver stw4500_driver; + +struct stw4500_chip { + struct spi_device *spi; + unsigned long tx_buf[4]; + unsigned long rx_buf[4]; +}; + +struct stw4500_chip *the_stw4500; + +/* + * This funtion writes to any STw4500 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 + */ +int stw4500_write(unsigned char block, unsigned long addr, + unsigned char data) +{ + struct spi_transfer xfer; + struct spi_message msg; + unsigned long spi_data = + block << 18 | addr << 10 | data; + + the_stw4500->tx_buf[0] = spi_data; + the_stw4500->rx_buf[0] = 0; + + xfer.tx_buf = the_stw4500->tx_buf; + xfer.rx_buf = NULL; + xfer.len = sizeof(unsigned long); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + return spi_sync(the_stw4500->spi, &msg); +} +EXPORT_SYMBOL(stw4500_write); + +int stw4500_read(unsigned char block, unsigned long addr) +{ + struct spi_transfer xfer; + struct spi_message msg; + unsigned long spi_data = + 1 << 23 | block << 18 | addr << 10; + + the_stw4500->tx_buf[0] = spi_data; + the_stw4500->rx_buf[0] = 0; + + xfer.tx_buf = the_stw4500->tx_buf; + xfer.rx_buf = the_stw4500->rx_buf; + xfer.len = sizeof(unsigned long); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + spi_sync(the_stw4500->spi, &msg); + + return the_stw4500->rx_buf[0]; +} +EXPORT_SYMBOL(stw4500_read); + +static int __init stw4500_probe(struct spi_device *spi) +{ + struct stw4500_chip *chip; + unsigned char revision; + + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->spi = spi; + spi_set_drvdata(spi, chip); + the_stw4500 = chip; + + /* read the revision register */ + revision = stw4500_read(0x10, 0x1080); + printk(KERN_INFO "STw4500 PMU Initialized, revision = %x\n", revision); + + return 0; +} + +static int __devexit stw4500_remove(struct spi_device *spi) +{ + struct stw4500_chip *chip = + spi_get_drvdata(spi); + kfree(chip); + + return 0; +} + +static struct spi_driver stw4500_driver = { + .driver = { + .name = "stw4500", + .owner = THIS_MODULE, + }, + .probe = stw4500_probe, + .remove = __devexit_p(stw4500_remove) +}; + +static int __devinit stw4500_init(void) +{ + return spi_register_driver(&stw4500_driver); +} + +static void __exit stw4500_exit(void) +{ + spi_unregister_driver(&stw4500_driver); +} + +subsys_initcall_sync(stw4500_init); -- 1.6.3.GIT