Commit 08cfadd9 authored by Andrey Porodko's avatar Andrey Porodko Committed by Jean-Paul Saman

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

parent ea075229
......@@ -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
......
/*
* 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.poro...@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");
/*
* neuros_osd2_msp.h - support MSP430 microcontroller on Neuros OSD2 board
* 2009 (c) Andrey A. Porodko <andrey.poro...@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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment