diff options
author | Michael Grzeschik <m.grzeschik@pengutronix.de> | 2013-08-14 06:07:51 +0200 |
---|---|---|
committer | Michael Grzeschik <m.grzeschik@pengutronix.de> | 2013-09-09 12:31:50 +0200 |
commit | fe45b3b338c872e91691bf5ff3c0467329b08a66 (patch) | |
tree | b3b7970324af3582bea2190da0fa5f4f9751bb32 | |
parent | d4b2b61a606cb83e3bc5229f9ffcb20fd5374d7b (diff) | |
download | linux-fe45b3b338c872e91691bf5ff3c0467329b08a66.tar.gz linux-fe45b3b338c872e91691bf5ff3c0467329b08a66.tar.xz |
mc13xxx wip
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
-rw-r--r-- | drivers/mfd/mc13xxx-core.c | 101 | ||||
-rw-r--r-- | include/linux/mfd/mc13xxx.h | 2 |
2 files changed, 97 insertions, 6 deletions
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index e1b89e6bfa29..48e3f54f4634 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 41ed59276c00..8498f92079fb 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; }; |