diff mbox

[fixed] MSP430 chip support for Neuros OSD2 board. MSP430 provides RTC, IR remote,

Message ID 1258452456-15077-1-git-send-email-panda@chelcom.ru (mailing list archive)
State Superseded
Headers show

Commit Message

A. Porodko Nov. 17, 2009, 10:07 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index bd9ca07..0949fa9 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -202,6 +202,9 @@  static struct davinci_i2c_platform_data ntosd2_i2c_pdata = {
 };
 
 static struct i2c_board_info __initdata ntosd2_i2c_info[] =  {
+	{					/* MSP430 interface	*/
+		I2C_BOARD_INFO("neuros_osd2_msp", NTOSD2_MSP430_I2C_ADDR),
+	},
 };
 
 static	int ntosd2_init_i2c(void)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 570be13..41ceebc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -43,6 +43,14 @@  config MFD_DM355EVM_MSP
 	  boards.  MSP430 firmware manages resets and power sequencing,
 	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
 
+config MFD_NEUROS_OSD2_MSP
+	bool "Neuros OSD2 open set top box microcontroller"
+	depends on I2C && MACH_NEUROS_OSD2
+	help
+	  This driver supports the MSP430 microcontroller used on these
+	  boards.  MSP430 firmware manages inputs/outputs from IR remote,
+	  an RTC and more.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f3b277b..32baa62 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -9,6 +9,7 @@  obj-$(CONFIG_HTC_EGPIO)		+= htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
 
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
+obj-$(CONFIG_MFD_NEUROS_OSD2_MSP) += neuros_osd2_msp.o
 
 obj-$(CONFIG_MFD_T7L66XB)	+= t7l66xb.o
 obj-$(CONFIG_MFD_TC6387XB)	+= tc6387xb.o
diff --git a/drivers/mfd/neuros_osd2_msp.c b/drivers/mfd/neuros_osd2_msp.c
new file mode 100644
index 0000000..489ab63
--- /dev/null
+++ b/drivers/mfd/neuros_osd2_msp.c
@@ -0,0 +1,204 @@ 
+/*
+ * neuros_osd2_msp.c - driver for MSP430 firmware on Neuros OSD2 board
+ *
+ * Based on code of dm355evm_msp.c by David Brownell
+ * 2009 (c) 2009 Andrey A. Porodko <Andrey.Porodko@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/i2c/neuros_osd2_msp.h>
+
+
+/*
+ * Neuros OSD2 has an MSP430 programmed with firmware for various board
+ * support functions.
+ */
+
+#if defined(CONFIG_INPUT_NEUROS_OSD2) || \
+				defined(CONFIG_INPUT_NEUROS_OSD2_MODULE)
+#define msp_has_keys()	true
+#else
+#define msp_has_keys()	false
+#endif
+
+#if defined(CONFIG_RTC_DRV_NEUROS_OSD2) || \
+				defined(CONFIG_RTC_DRV_NEUROS_OSD2_MODULE)
+#define msp_has_rtc()		true
+#else
+#define msp_has_rtc()		false
+#endif
+
+#if defined(CONFIG_NEUROS_OSD2_IRBLASTER) || \
+				defined(CONFIG_NEUROS_OSD2_IRBLASTER_MODULE)
+#define msp_has_irblaster()	true
+#else
+#define msp_has_irblaster()	false
+#endif
+
+static struct i2c_client *msp430;
+
+/**
+ * ntosd2_msp_write_byte - Writes command with parameter in neuros_osd2_msp
+ * @value: the value to be written
+ * @reg: the register in MSP430
+ *
+ * Returns result of operation - 0 is success, else negative errno
+ */
+int ntosd2_msp_write_byte(u8 reg, u8 value)
+{
+
+	return i2c_smbus_write_byte_data(msp430, reg, value);
+}
+EXPORT_SYMBOL(ntosd2_msp_write_byte);
+
+/**
+ * ntosd2_msp_read_byte - Reads a byte from neuros_osd2_msp
+ * @reg: the reg in msp430
+ *
+ * Returns result of operation - byte read, or negative errno
+ */
+int ntosd2_msp_read_byte(u8 reg)
+{
+
+	return i2c_smbus_read_byte_data(msp430, reg);
+}
+EXPORT_SYMBOL(ntosd2_msp_read_byte);
+
+
+/*----------------------------------------------------------------------*/
+
+static struct device *add_child(struct i2c_client *client, const char *name,
+				void *pdata, unsigned pdata_len,
+				bool can_wakeup, int irq)
+{
+	struct platform_device	*pdev;
+	int			status;
+
+	pdev = platform_device_alloc(name, -1);
+	if (!pdev) {
+		dev_dbg(&client->dev, "can't alloc dev\n");
+		status = -ENOMEM;
+		goto err;
+	}
+
+	device_init_wakeup(&pdev->dev, can_wakeup);
+	pdev->dev.parent = &client->dev;
+
+	if (pdata) {
+		status = platform_device_add_data(pdev, pdata, pdata_len);
+		if (status < 0) {
+			dev_dbg(&pdev->dev, "can't add platform_data\n");
+			goto err;
+		}
+	}
+
+	if (irq) {
+		struct resource r = {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+		};
+
+		status = platform_device_add_resources(pdev, &r, 1);
+		if (status < 0) {
+			dev_dbg(&pdev->dev, "can't add irq\n");
+			goto err;
+		}
+	}
+	status = platform_device_add(pdev);
+err:
+	if (status < 0) {
+		platform_device_put(pdev);
+		dev_err(&client->dev, "can't add %s dev\n", name);
+		return ERR_PTR(status);
+	}
+	return &pdev->dev;
+}
+
+static int add_children(struct i2c_client *client)
+{
+	struct device	*child;
+
+	/* RTC */
+	if (msp_has_rtc()) {
+		child = add_child(client, "rtc_neuros_osd2",
+				NULL, 0, false, 0);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+	}
+
+	/* input from IR remote (uses the IRQ) */
+	if (msp_has_keys()) {
+		child = add_child(client, "neuros_osd2_ir",
+				NULL, 0, true, client->irq);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+	}
+
+	/* output to IR blaster  */
+	if (msp_has_irblaster()) {
+		child = add_child(client, "neuros_osd2_irblaster",
+				NULL, 0, true, client->irq);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
+	}
+	return 0;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int ntosd2_msp_remove(struct i2c_client *client)
+{
+	msp430 = NULL;
+	return 0;
+}
+
+static int ntosd2_msp_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	int	status;
+
+	if (msp430) {
+		status = -EBUSY;
+	} else {
+		msp430 = client;
+	status = add_children(client);
+	if (status >= 0)
+		status = 0;
+	}
+	if (status < 0)				/* failed...		*/
+		ntosd2_msp_remove(client);
+	return status;
+}
+
+static const struct i2c_device_id ntosd2_msp_ids[] = {
+	{ "neuros_osd2_msp", 0 },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(i2c, ntosd2_msp_ids);
+
+static struct i2c_driver ntosd2_msp_driver = {
+	.driver.name	= "neuros_osd2_msp",
+	.id_table	= ntosd2_msp_ids,
+	.probe		= ntosd2_msp_probe,
+	.remove		= ntosd2_msp_remove,
+};
+
+static int __init ntosd2_msp_init(void)
+{
+	return i2c_add_driver(&ntosd2_msp_driver);
+}
+subsys_initcall(ntosd2_msp_init);
+
+static void __exit ntosd2_msp_exit(void)
+{
+	i2c_del_driver(&ntosd2_msp_driver);
+}
+module_exit(ntosd2_msp_exit);
+
+MODULE_DESCRIPTION("Interface to MSP430 firmware on Neuros OSD2");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/neuros_osd2_msp.h b/include/linux/i2c/neuros_osd2_msp.h
new file mode 100644
index 0000000..3b428d1
--- /dev/null
+++ b/include/linux/i2c/neuros_osd2_msp.h
@@ -0,0 +1,43 @@ 
+/*
+ * neuros_osd2_msp.h - support MSP430 microcontroller on Neuros OSD2 board
+ * 2009 (c) Andrey A. Porodko <Andrey.Porodko@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#ifndef __LINUX_I2C_NEUROS_OSD2_MSP
+#define __LINUX_I2C_NEUROS_OSD2_MSP
+
+/* utilities to access "registers" emulated by msp430 firmware */
+extern int ntosd2_msp_write_byte(u8 reg, u8 value);
+extern int ntosd2_msp_read_byte(u8 reg);
+
+/* MSP commands (registers) */
+#define	NTOSD2_MSP430_GETIRCODE	  0xB0
+#define	NTOSD2_MSP430_GETVER	  0x36
+#define NTOSD2_MSP430_RTC_MDAY	  0x19
+#define	NTOSD2_MSP430_RTC_MONTH	  0x1A
+#define	NTOSD2_MSP430_RTC_YEAR	  0x1B /* year since 2006, 0 = 2006	*/
+#define	NTOSD2_MSP430_RTC_HOURS	  0x18
+#define	NTOSD2_MSP430_RTC_MINUTES 0x17
+#define	NTOSD2_MSP430_RTC_SECONDS 0x16
+
+#define	NTOSD2_MSP430_READ_RETRIES 3
+
+#define	NTOSD2_MSP430_RESET	  6    /* reset to MSP430 high - active	*/
+#define	NTOSD2_MSP430_IRR_IRQ	  7    /* Raw data from IR sensor	*/
+#define	NTOSD2_MSP430_PWM0	  45   /* out, generates 38 kHz for IR Blaster*/
+#define	NTOSD2_MSP430_ARM_BLSTR	  47   /* Raw data to IR Blaster	*/
+
+#define	NTOSD2_MSP430_MAX_PULSES  128  /* max pulses in buffer		*/
+#define	NTOSD2_MSP430_IO_TIMEOUT  75   /* default I/O timeout in ms	*/
+#define	NTOSD2_MSP430_POOLING_TIMEOUT 10000/* default sensor polling in us */
+
+#define	NTOSD2_IR_BLASTER_IOC_MAGIC 'i'/* code for IR blaster ioctl	*/
+#define RRB_SET_IO_TIMEOUT 	  _IOW(NTOSD2_IR_BLASTER_IOC_MAGIC, \
+					1, unsigned long)
+#define RRB_SET_POOLING_TIMEOUT   _IOW(NTOSD2_IR_BLASTER_IOC_MAGIC, \
+					2, unsigned long)
+
+#endif /* __LINUX_I2C_NEUROS_OSD2_MSP */