diff options
Diffstat (limited to 'drivers/mfd/mc13xxx-core.c')
-rw-r--r-- | drivers/mfd/mc13xxx-core.c | 101 |
1 files changed, 96 insertions, 5 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) |