gpio: sx150x: Add device tree support for sx150x gpio

Add device tree support for sx150x IO Expander devices.

Change-Id: I212957bc88278659c81e28e1003dbfc7509d9877
Signed-off-by: Bamidi RaviKiran <bamidir@codeaurora.org>
This commit is contained in:
Bamidi RaviKiran 2013-09-30 19:10:50 +05:30
parent e9fa666b62
commit 3aa5f509d8

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010, 2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -18,7 +18,10 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/of_gpio.h>
#include <linux/i2c/sx150x.h>
#include <linux/of.h>
#include <linux/delay.h>
#define NO_UPDATE_PENDING -1
@ -53,8 +56,11 @@ struct sx150x_chip {
struct mutex lock;
};
#define SX1508Q_ID 0
#define SX1509Q_ID 1
static const struct sx150x_device_data sx150x_devices[] = {
[0] = { /* sx1508q */
[SX1508Q_ID] = { /* sx1508q */
.reg_pullup = 0x03,
.reg_pulldn = 0x04,
.reg_drain = 0x05,
@ -69,7 +75,7 @@ static const struct sx150x_device_data sx150x_devices[] = {
.reg_reset = 0x7d,
.ngpios = 8
},
[1] = { /* sx1509q */
[SX1509Q_ID] = { /* sx1509q */
.reg_pullup = 0x07,
.reg_pulldn = 0x09,
.reg_drain = 0x0b,
@ -86,9 +92,24 @@ static const struct sx150x_device_data sx150x_devices[] = {
},
};
#ifdef CONFIG_OF
static struct of_device_id sx150x_match_table[] = {
{
.compatible = "sx1508q", .data = NULL,
},
{
.compatible = "sx1509q", .data = NULL,
},
{ },
};
MODULE_DEVICE_TABLE(of, sx150x_match_table);
#else
#define sx150x_match_table NULL
#endif
static const struct i2c_device_id sx150x_id[] = {
{"sx1508q", 0},
{"sx1509q", 1},
{"sx1508q", SX1508Q_ID},
{"sx1509q", SX1509Q_ID},
{}
};
MODULE_DEVICE_TABLE(i2c, sx150x_id);
@ -424,6 +445,13 @@ static void sx150x_init_chip(struct sx150x_chip *chip,
{
mutex_init(&chip->lock);
if (client->dev.of_node) {
if (of_device_is_compatible(client->dev.of_node, "sx1508q"))
driver_data = SX1508Q_ID;
else
driver_data = SX1509Q_ID;
}
chip->client = client;
chip->dev_cfg = &sx150x_devices[driver_data];
chip->gpio_chip.label = client->name;
@ -438,6 +466,10 @@ static void sx150x_init_chip(struct sx150x_chip *chip,
if (pdata->oscio_is_gpo)
++chip->gpio_chip.ngpio;
if (client && client->dev.of_node)
chip->gpio_chip.of_node =
of_node_get(client->dev.of_node);
chip->irq_chip.name = client->name;
chip->irq_chip.irq_mask = sx150x_irq_mask;
chip->irq_chip.irq_unmask = sx150x_irq_unmask;
@ -466,6 +498,29 @@ static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
static int sx150x_reset(struct sx150x_chip *chip)
{
int err;
struct device_node *np = chip->gpio_chip.of_node;
enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
int rst_gpio;
if (np) {
rst_gpio = of_get_named_gpio_flags(np, "sx150x,reset_gpio",
0, &flags);
if (rst_gpio < 0)
pr_debug("%s: No Reset GPIO found %d\n",
__func__, rst_gpio);
else {
err = gpio_request(rst_gpio, "sx150x_rst");
if (err) {
pr_err("Failed to get reset GPIO %d\n", err);
return err;
}
/* Max. time for NRESET low is 2.5ms */
gpio_direction_output(rst_gpio, 0x0);
usleep(2500);
gpio_direction_output(rst_gpio, 0x1);
}
}
err = i2c_smbus_write_byte_data(chip->client,
chip->dev_cfg->reg_reset,
@ -572,16 +627,85 @@ static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
}
}
#ifdef CONFIG_OF
static int sx150x_parse_dt(struct device *dev,
struct sx150x_platform_data *pdata)
{
int rc;
unsigned int temp;
struct device_node *np = dev->of_node;
if (!np)
return -ENODEV;
pdata->oscio_is_gpo = of_property_read_bool(np, "sx150x,oscio_is_gpo");
pdata->reset_during_probe =
of_property_read_bool(np, "sx150x,reset_onprobe");
rc = of_property_read_u32(np, "sx150x,pullup_ena", &temp);
if (rc) {
pr_err("%s: Failed to find pullup_ena %d\n", __func__, rc);
return rc;
}
pdata->io_pullup_ena = temp;
rc = of_property_read_u32(np, "sx150x,pulldn_ena", &temp);
if (rc) {
pr_err("%s: Failed to find pulldn_ena %d\n", __func__, rc);
return rc;
}
pdata->io_pulldn_ena = temp;
rc = of_property_read_u32(np, "sx150x,float_ena", &temp);
if (rc) {
pr_err("%s: Failed to find float_ena %d\n", __func__, rc);
return rc;
}
pdata->io_open_drain_ena = temp;
rc = of_property_read_u32(np, "sx150x,polarity", &temp);
if (rc) {
pr_err("%s: Failed to find polarity %d\n", __func__, rc);
return rc;
}
pdata->io_polarity = temp;
/* TODO: Add support for Interrupts */
pdata->irq_summary = -1;
pdata->gpio_base = -1;
return 0;
}
#else
static int sx150x_parse_dt(struct device *dev,
struct sx150x_platform_data *pdata)
{
return -ENODEV;
}
#endif
static int sx150x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WRITE_WORD_DATA;
I2C_FUNC_SMBUS_WRITE_WORD_DATA;
struct sx150x_platform_data *pdata;
struct sx150x_chip *chip;
int rc;
pdata = client->dev.platform_data;
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev,
sizeof(struct sx150x_platform_data), GFP_KERNEL);
if (!pdata) {
dev_err(&client->dev, "Failed to allocate memory\n");
return -ENOMEM;
}
rc = sx150x_parse_dt(&client->dev, pdata);
if (rc)
return rc;
} else
pdata = client->dev.platform_data;
if (!pdata)
return -EINVAL;
@ -640,7 +764,8 @@ static int sx150x_remove(struct i2c_client *client)
static struct i2c_driver sx150x_driver = {
.driver = {
.name = "sx150x",
.owner = THIS_MODULE
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(sx150x_match_table)
},
.probe = sx150x_probe,
.remove = sx150x_remove,