I must apologize, I missed some obvious style mistakes and again forgot to run checkpatch. Corrected.
Signed-off-by: Andrey Porodko <[email protected]> --- arch/arm/mach-davinci/board-neuros-osd2.c | 3 + drivers/mfd/Kconfig | 8 + drivers/mfd/Makefile | 1 + drivers/mfd/neuros_osd2_msp.c | 204 +++++++++++++++++++++++++++++ include/linux/i2c/neuros_osd2_msp.h | 43 ++++++ 5 files changed, 259 insertions(+), 0 deletions(-) create mode 100644 drivers/mfd/neuros_osd2_msp.c create mode 100644 include/linux/i2c/neuros_osd2_msp.h 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 <[email protected]> + * + * 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 <[email protected]> + * + * 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 */ -- 1.5.6.5 _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
