[PATCH 2/3] mfd: add U8500 STw4500 SPI device support

srinidhi kasagar srinidhi.kasagar at stericsson.com
Mon Sep 21 18:37:10 EDT 2009


From: srinidhi kasagar <srinidhi.kasagar at stericsson.com>

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 <srinidhi.kasagar at stericsson.com>
---
 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 <srinidhi.kasagar at stericsson.com>
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+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






More information about the linux-arm-kernel mailing list