summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Grzeschik <m.grzeschik@pengutronix.de>2013-08-14 06:07:51 +0200
committerMichael Grzeschik <m.grzeschik@pengutronix.de>2013-09-09 12:31:50 +0200
commitfe45b3b338c872e91691bf5ff3c0467329b08a66 (patch)
treeb3b7970324af3582bea2190da0fa5f4f9751bb32
parentd4b2b61a606cb83e3bc5229f9ffcb20fd5374d7b (diff)
downloadlinux-fe45b3b338c872e91691bf5ff3c0467329b08a66.tar.gz
mc13xxx wip
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
-rw-r--r--drivers/mfd/mc13xxx-core.c101
-rw-r--r--include/linux/mfd/mc13xxx.h2
2 files changed, 97 insertions, 6 deletions
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index e1b89e6..48e3f54 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -616,29 +616,120 @@ static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
}
#ifdef CONFIG_OF
-static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
+
+static struct mc13xxx_ts_platform_data* of_get_ts_pdata(struct mc13xxx *mc13xxx, struct device_node *np)
+{
+ struct mc13xxx_ts_platform_data *pdata;
+ struct device_node *parent;
+ int ret;
+
+ pdata = devm_kzalloc(mc13xxx->dev, sizeof(*pdata), GFP_KERNEL);
+
+ parent = of_find_node_by_name(np, "touch");
+
+ ret = of_property_read_u8(parent, "ato", &pdata->ato);
+
+ if (of_get_property(np, "delay-ato-for-each", NULL))
+ pdata->atox = true;
+
+ return pdata;
+}
+
+static struct mc13xxx_codec_platform_data* of_get_codec_pdata(struct mc13xxx *mc13xxx, struct device_node *np)
+{
+ struct mc13xxx_codec_platform_data *pdata;
+ struct device_node *parent;
+ int ret;
+
+ pdata = devm_kzalloc(mc13xxx->dev, sizeof(*pdata), GFP_KERNEL);
+
+ parent = of_find_node_by_name(np, "codec");
+ ret = of_property_read_u32(parent, "adc-ssi-port", &pdata->adc_ssi_port);
+ ret = of_property_read_u32(parent, "dac-ssi-port", &pdata->dac_ssi_port);
+
+ return pdata;
+}
+
+static struct mc13xxx_leds_platform_data* of_get_leds_pdata(struct mc13xxx *mc13xxx, struct device_node *np)
+{
+ struct mc13xxx_leds_platform_data *pdata;
+ unsigned int controls[MAX_LED_CONTROL_REGS];
+ struct device_node *parent;
+ const __be32 *list;
+ int size, ret, i;
+
+ pdata = devm_kzalloc(mc13xxx->dev, sizeof(*pdata), GFP_KERNEL);
+
+ parent = of_find_node_by_name(np, "leds");
+ if (!parent)
+ return NULL;
+
+ list = of_get_property(parent, "controls", &size);
+ if (!list) {
+ dev_err(mc13xxx->dev, "can not read the leds of %d\n", size);
+ return NULL;
+ }
+
+ size /= sizeof(*list);
+
+ ret = of_property_read_u32_array(parent, "controls", controls, size);
+ for (i = 0; i < size; i++)
+ pdata->led_control[i] = controls[i];
+
+ list = of_get_property(parent, "leds", &size);
+ if (!list) {
+ dev_err(mc13xxx->dev, "can not read the controls of %d\n", size);
+ return NULL;
+ }
+
+ size /= sizeof(*list);
+ pdata->num_leds = size;
+
+ pdata->led = devm_kzalloc(mc13xxx->dev, sizeof(*pdata->led) * pdata->num_leds, GFP_KERNEL);
+ for (i = 0; i < pdata->num_leds; i++) {
+ struct mc13xxx_led_platform_data *cur = &pdata->led[i];
+ of_property_read_u32_index(parent, "leds", i, &cur->id);;
+ of_property_read_string_index(parent, "led-names", i, &cur->name);
+ }
+
+ of_node_put(parent);
+
+ return pdata;
+}
+
+static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx, struct mc13xxx_platform_data *pdata)
{
struct device_node *np = mc13xxx->dev->of_node;
if (!np)
return -ENODEV;
+ if (!pdata)
+ pdata = devm_kzalloc(mc13xxx->dev, sizeof(*pdata), GFP_KERNEL);
+
if (of_get_property(np, "fsl,mc13xxx-uses-adc", NULL))
mc13xxx->flags |= MC13XXX_USE_ADC;
- if (of_get_property(np, "fsl,mc13xxx-uses-codec", NULL))
+ if (of_get_property(np, "fsl,mc13xxx-uses-codec", NULL)) {
mc13xxx->flags |= MC13XXX_USE_CODEC;
+ pdata->codec = of_get_codec_pdata(mc13xxx, np);
+ }
if (of_get_property(np, "fsl,mc13xxx-uses-rtc", NULL))
mc13xxx->flags |= MC13XXX_USE_RTC;
- if (of_get_property(np, "fsl,mc13xxx-uses-touch", NULL))
+ if (of_get_property(np, "fsl,mc13xxx-uses-touch", NULL)) {
mc13xxx->flags |= MC13XXX_USE_TOUCHSCREEN;
+ pdata->touch = of_get_ts_pdata(mc13xxx, np);
+ }
+
+ if (of_get_property(np, "fsl,mc13xxx-uses-leds", NULL))
+ pdata->leds = of_get_leds_pdata(mc13xxx, np);
return 0;
}
#else
-static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
+static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx, struct mc13xxx_platform_data *pdata)
{
return -ENODEV;
}
@@ -681,7 +772,7 @@ err_revision:
mc13xxx_unlock(mc13xxx);
- if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
+ if (mc13xxx_probe_flags_dt(mc13xxx, pdata) < 0 && pdata)
mc13xxx->flags = pdata->flags;
if (mc13xxx->flags & MC13XXX_USE_ADC)
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index 41ed592..8498f92 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -190,7 +190,7 @@ struct mc13xxx_platform_data {
struct mc13xxx_regulator_platform_data regulators;
struct mc13xxx_leds_platform_data *leds;
struct mc13xxx_buttons_platform_data *buttons;
- struct mc13xxx_ts_platform_data touch;
+ struct mc13xxx_ts_platform_data *touch;
struct mc13xxx_codec_platform_data *codec;
};