@@ -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)
@@ -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
@@ -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
new file mode 100644
@@ -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");
new file mode 100644
@@ -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 */