From 0a6aa88f77e744853cadbdba1b67fd35952b19c6 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:17 +0530 Subject: regulator: helper routine to extract regulator_init_data The helper routine is meant to be used by the regulator drivers to extract the regulator_init_data structure from the data that is passed from device tree. 'consumer_supplies' which is part of regulator_init_data is not extracted as the regulator consumer mappings are passed through DT differently, implemented in subsequent patches. Similarly the regulator<-->parent/supply mapping is handled in subsequent patches. Also add documentation for regulator bindings to be used to pass regulator_init_data struct information from device tree. Some of the regulator properties which are linux and board specific, are left out since its not clear if they can be in someway embedded into the kernel or passed in from DT. They will be revisited later. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/regulator.txt | 54 +++++++++++++++ drivers/regulator/Makefile | 1 + drivers/regulator/of_regulator.c | 81 ++++++++++++++++++++++ include/linux/regulator/of_regulator.h | 20 ++++++ 4 files changed, 156 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/regulator.txt create mode 100644 drivers/regulator/of_regulator.c create mode 100644 include/linux/regulator/of_regulator.h diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt new file mode 100644 index 00000000000..82bef20d4c4 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -0,0 +1,54 @@ +Voltage/Current Regulators + +Optional properties: +- regulator-name: A string used as a descriptive name for regulator outputs +- regulator-min-microvolt: smallest voltage consumers may set +- regulator-max-microvolt: largest voltage consumers may set +- regulator-microvolt-offset: Offset applied to voltages to compensate for voltage drops +- regulator-min-microamp: smallest current consumers may set +- regulator-max-microamp: largest current consumers may set +- regulator-always-on: boolean, regulator should never be disabled +- regulator-boot-on: bootloader/firmware enabled regulator +- -supply: phandle to the parent supply/regulator node + +Example: + + xyzreg: regulator@0 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + vin-supply = <&vin>; + }; + +Regulator Consumers: +Consumer nodes can reference one or more of its supplies/ +regulators using the below bindings. + +- -supply: phandle to the regulator node + +These are the same bindings that a regulator in the above +example used to reference its own supply, in which case +its just seen as a special case of a regulator being a +consumer itself. + +Example of a consumer device node (mmc) referencing two +regulators (twl-reg1 and twl-reg2), + + twl-reg1: regulator@0 { + ... + ... + ... + }; + + twl-reg2: regulator@1 { + ... + ... + ... + }; + + mmc: mmc@0x0 { + ... + ... + vmmc-supply = <&twl-reg1>; + vmmcaux-supply = <&twl-reg2>; + }; diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 55d1b5dc3ae..4043b4d98f0 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_REGULATOR) += core.o dummy.o +obj-$(CONFIG_OF) += of_regulator.o obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c new file mode 100644 index 00000000000..76673c784ab --- /dev/null +++ b/drivers/regulator/of_regulator.c @@ -0,0 +1,81 @@ +/* + * OF helpers for regulator framework + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +static void of_get_regulation_constraints(struct device_node *np, + struct regulator_init_data **init_data) +{ + const __be32 *min_uV, *max_uV, *uV_offset; + const __be32 *min_uA, *max_uA; + struct regulation_constraints *constraints = &(*init_data)->constraints; + + constraints->name = of_get_property(np, "regulator-name", NULL); + + min_uV = of_get_property(np, "regulator-min-microvolt", NULL); + if (min_uV) + constraints->min_uV = be32_to_cpu(*min_uV); + max_uV = of_get_property(np, "regulator-max-microvolt", NULL); + if (max_uV) + constraints->max_uV = be32_to_cpu(*max_uV); + + /* Voltage change possible? */ + if (constraints->min_uV != constraints->max_uV) + constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + + uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); + if (uV_offset) + constraints->uV_offset = be32_to_cpu(*uV_offset); + min_uA = of_get_property(np, "regulator-min-microamp", NULL); + if (min_uA) + constraints->min_uA = be32_to_cpu(*min_uA); + max_uA = of_get_property(np, "regulator-max-microamp", NULL); + if (max_uA) + constraints->max_uA = be32_to_cpu(*max_uA); + + /* Current change possible? */ + if (constraints->min_uA != constraints->max_uA) + constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; + + if (of_find_property(np, "regulator-boot-on", NULL)) + constraints->boot_on = true; + + if (of_find_property(np, "regulator-always-on", NULL)) + constraints->always_on = true; + else /* status change should be possible if not always on. */ + constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; +} + +/** + * of_get_regulator_init_data - extract regulator_init_data structure info + * @dev: device requesting for regulator_init_data + * + * Populates regulator_init_data structure by extracting data from device + * tree node, returns a pointer to the populated struture or NULL if memory + * alloc fails. + */ +struct regulator_init_data *of_get_regulator_init_data(struct device *dev) +{ + struct regulator_init_data *init_data; + + if (!dev->of_node) + return NULL; + + init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return NULL; /* Out of memory? */ + + of_get_regulation_constraints(dev->of_node, &init_data); + return init_data; +} diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h new file mode 100644 index 00000000000..d83a98d3e3f --- /dev/null +++ b/include/linux/regulator/of_regulator.h @@ -0,0 +1,20 @@ +/* + * OpenFirmware regulator support routines + * + */ + +#ifndef __LINUX_OF_REG_H +#define __LINUX_OF_REG_H + +#if defined(CONFIG_OF) +extern struct regulator_init_data + *of_get_regulator_init_data(struct device *dev); +#else +static inline struct regulator_init_data + *of_get_regulator_init_data(struct device *dev) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +#endif /* __LINUX_OF_REG_H */ -- cgit v1.2.3 From ea05e7fcdb7189212863c418424107c2c1e9ab8e Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:18 +0530 Subject: regulator: adapt fixed regulator driver to dt The fixed regulator driver uses of_get_fixed_voltage_config() to extract fixed_voltage_config structure contents from device tree. Also add documenation for additional bindings for fixed regulators that can be passed through dt. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown --- .../bindings/regulator/fixed-regulator.txt | 29 ++++++++++ drivers/regulator/fixed.c | 65 ++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/fixed-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt new file mode 100644 index 00000000000..9cf57fd042d --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -0,0 +1,29 @@ +Fixed Voltage regulators + +Required properties: +- compatible: Must be "regulator-fixed"; + +Optional properties: +- gpio: gpio to use for enable control +- startup-delay-us: startup time in microseconds +- enable-active-high: Polarity of GPIO is Active high +If this property is missing, the default assumed is Active low. + +Any property defined as part of the core regulator +binding, defined in regulator.txt, can also be used. +However a fixed voltage regulator is expected to have the +regulator-min-microvolt and regulator-max-microvolt +to be the same. + +Example: + + abc: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-supply"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio1 16 0>; + startup-delay-us = <70000>; + enable-active-high; + regulator-boot-on + }; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 21ecf212a52..0650856b93c 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -27,6 +27,10 @@ #include #include #include +#include +#include +#include +#include struct fixed_voltage_data { struct regulator_desc desc; @@ -38,6 +42,53 @@ struct fixed_voltage_data { bool is_enabled; }; + +/** + * of_get_fixed_voltage_config - extract fixed_voltage_config structure info + * @dev: device requesting for fixed_voltage_config + * + * Populates fixed_voltage_config structure by extracting data from device + * tree node, returns a pointer to the populated structure of NULL if memory + * alloc fails. + */ +struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev) +{ + struct fixed_voltage_config *config; + struct device_node *np = dev->of_node; + const __be32 *delay; + struct regulator_init_data *init_data; + + config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), + GFP_KERNEL); + if (!config) + return NULL; + + config->init_data = of_get_regulator_init_data(dev); + init_data = config->init_data; + + config->supply_name = init_data->constraints.name; + if (init_data->constraints.min_uV == init_data->constraints.max_uV) { + config->microvolts = init_data->constraints.min_uV; + } else { + dev_err(dev, + "Fixed regulator specified with variable voltages\n"); + return NULL; + } + + if (init_data->constraints.boot_on) + config->enabled_at_boot = true; + + config->gpio = of_get_named_gpio(np, "gpio", 0); + delay = of_get_property(np, "startup-delay-us", NULL); + if (delay) + config->startup_delay = be32_to_cpu(*delay); + + if (of_find_property(np, "enable-active-high", NULL)) + config->enable_high = true; + + return config; +} + static int fixed_voltage_is_enabled(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); @@ -109,6 +160,9 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) struct fixed_voltage_data *drvdata; int ret; + if (pdev->dev.of_node) + config = of_get_fixed_voltage_config(&pdev->dev); + drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); if (drvdata == NULL) { dev_err(&pdev->dev, "Failed to allocate device data\n"); @@ -217,12 +271,23 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id fixed_of_match[] __devinitconst = { + { .compatible = "regulator-fixed", }, + {}, +}; +MODULE_DEVICE_TABLE(of, fixed_of_match); +#else +#define fixed_of_match NULL +#endif + static struct platform_driver regulator_fixed_voltage_driver = { .probe = reg_fixed_voltage_probe, .remove = __devexit_p(reg_fixed_voltage_remove), .driver = { .name = "reg-fixed-voltage", .owner = THIS_MODULE, + .of_match_table = fixed_of_match, }, }; -- cgit v1.2.3 From 3cb2bc07246faf01047c6d51308be591048a1e88 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:19 +0530 Subject: regulator: pass additional of_node to regulator_register() With device tree support for regulators, its needed that the regulator_dev->dev device has the right of_node attached. To be able to do this add an additional parameter to the regulator_register() api, wherein the dt-adapted driver can then pass this additional info onto the regulator core. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 2 +- drivers/regulator/aat2870-regulator.c | 2 +- drivers/regulator/ab3100.c | 2 +- drivers/regulator/ab8500.c | 2 +- drivers/regulator/ad5398.c | 2 +- drivers/regulator/bq24022.c | 2 +- drivers/regulator/core.c | 3 ++- drivers/regulator/da903x.c | 2 +- drivers/regulator/db8500-prcmu.c | 2 +- drivers/regulator/dummy.c | 2 +- drivers/regulator/fixed.c | 2 +- drivers/regulator/isl6271a-regulator.c | 2 +- drivers/regulator/lp3971.c | 2 +- drivers/regulator/lp3972.c | 2 +- drivers/regulator/max1586.c | 2 +- drivers/regulator/max8649.c | 2 +- drivers/regulator/max8660.c | 2 +- drivers/regulator/max8925-regulator.c | 2 +- drivers/regulator/max8952.c | 2 +- drivers/regulator/max8997.c | 2 +- drivers/regulator/max8998.c | 2 +- drivers/regulator/mc13783-regulator.c | 2 +- drivers/regulator/mc13892-regulator.c | 2 +- drivers/regulator/pcap-regulator.c | 2 +- drivers/regulator/pcf50633-regulator.c | 2 +- drivers/regulator/tps6105x-regulator.c | 3 ++- drivers/regulator/tps65023-regulator.c | 2 +- drivers/regulator/tps6507x-regulator.c | 2 +- drivers/regulator/tps6524x-regulator.c | 2 +- drivers/regulator/tps6586x-regulator.c | 2 +- drivers/regulator/tps65910-regulator.c | 2 +- drivers/regulator/tps65912-regulator.c | 2 +- drivers/regulator/twl-regulator.c | 2 +- drivers/regulator/wm831x-dcdc.c | 8 ++++---- drivers/regulator/wm831x-isink.c | 2 +- drivers/regulator/wm831x-ldo.c | 6 +++--- drivers/regulator/wm8350-regulator.c | 2 +- drivers/regulator/wm8400-regulator.c | 2 +- drivers/regulator/wm8994-regulator.c | 2 +- include/linux/regulator/driver.h | 2 +- sound/soc/codecs/sgtl5000.c | 2 +- 41 files changed, 48 insertions(+), 46 deletions(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index ca0d608f824..df33530cec4 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -427,7 +427,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) /* replace driver_data with info */ info->regulator = regulator_register(&info->desc, &pdev->dev, - pdata, info); + pdata, info, NULL); if (IS_ERR(info->regulator)) { dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 298c6c6a279..43b25cc9d84 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -188,7 +188,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev) ri->pdev = pdev; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 585e4946fe0..042271aace6 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -634,7 +634,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) rdev = regulator_register(&ab3100_regulator_desc[i], &pdev->dev, &plfdata->reg_constraints[i], - reg); + reg, NULL); if (IS_ERR(rdev)) { err = PTR_ERR(rdev); diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 6e1ae69646b..e91b8ddc279 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -822,7 +822,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) /* register regulator with framework */ info->regulator = regulator_register(&info->desc, &pdev->dev, - &pdata->regulator[i], info); + &pdata->regulator[i], info, NULL); if (IS_ERR(info->regulator)) { err = PTR_ERR(info->regulator); dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index a4be41614ee..483c8093085 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -233,7 +233,7 @@ static int __devinit ad5398_probe(struct i2c_client *client, chip->current_mask = (chip->current_level - 1) << chip->current_offset; chip->rdev = regulator_register(&ad5398_reg, &client->dev, - init_data, chip); + init_data, chip, NULL); if (IS_ERR(chip->rdev)) { ret = PTR_ERR(chip->rdev); dev_err(&client->dev, "failed to register %s %s\n", diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c index e24d1b7d97a..9fab6d1bbe8 100644 --- a/drivers/regulator/bq24022.c +++ b/drivers/regulator/bq24022.c @@ -107,7 +107,7 @@ static int __init bq24022_probe(struct platform_device *pdev) ret = gpio_direction_output(pdata->gpio_nce, 1); bq24022 = regulator_register(&bq24022_desc, &pdev->dev, - pdata->init_data, pdata); + pdata->init_data, pdata, NULL); if (IS_ERR(bq24022)) { dev_dbg(&pdev->dev, "couldn't register regulator\n"); ret = PTR_ERR(bq24022); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 938398f3e86..dd695b9aecf 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2637,7 +2637,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) */ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, - void *driver_data) + void *driver_data, struct device_node *of_node) { static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; @@ -2696,6 +2696,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, /* register with sysfs */ rdev->dev.class = ®ulator_class; + rdev->dev.of_node = of_node; rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index e23ddfa8b2c..8dbc54da7d7 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -537,7 +537,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) ri->desc.ops = &da9030_regulator_ldo1_15_ops; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 78329751af5..515443fcd26 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -486,7 +486,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) /* register with the regulator framework */ info->rdev = regulator_register(&info->desc, &pdev->dev, - init_data, info); + init_data, info, NULL); if (IS_ERR(info->rdev)) { err = PTR_ERR(info->rdev); dev_err(&pdev->dev, "failed to register %s: err %i\n", diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index b8f520513ce..0ee00de4be7 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -42,7 +42,7 @@ static int __devinit dummy_regulator_probe(struct platform_device *pdev) int ret; dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, - &dummy_initdata, NULL); + &dummy_initdata, NULL, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 0650856b93c..db90919f99c 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -234,7 +234,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata); + config->init_data, drvdata, NULL); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e4b3592e817..c1a456c4257 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -170,7 +170,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, for (i = 0; i < 3; i++) { pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, - init_data, pmic); + init_data, pmic, NULL); if (IS_ERR(pmic->rdev[i])) { dev_err(&i2c->dev, "failed to register %s\n", id->name); err = PTR_ERR(pmic->rdev[i]); diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 72b16b5f3db..0cfabd318a5 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -451,7 +451,7 @@ static int __devinit setup_regulators(struct lp3971 *lp3971, for (i = 0; i < pdata->num_regulators; i++) { struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; lp3971->rdev[i] = regulator_register(®ulators[reg->id], - lp3971->dev, reg->initdata, lp3971); + lp3971->dev, reg->initdata, lp3971, NULL); if (IS_ERR(lp3971->rdev[i])) { err = PTR_ERR(lp3971->rdev[i]); diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index fbc5e3741be..49a15eefe5f 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -555,7 +555,7 @@ static int __devinit setup_regulators(struct lp3972 *lp3972, for (i = 0; i < pdata->num_regulators; i++) { struct lp3972_regulator_subdev *reg = &pdata->regulators[i]; lp3972->rdev[i] = regulator_register(®ulators[reg->id], - lp3972->dev, reg->initdata, lp3972); + lp3972->dev, reg->initdata, lp3972, NULL); if (IS_ERR(lp3972->rdev[i])) { err = PTR_ERR(lp3972->rdev[i]); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 3f49512c513..40e7a4db285 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -214,7 +214,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, } rdev[i] = regulator_register(&max1586_reg[id], &client->dev, pdata->subdevs[i].platform_data, - max1586); + max1586, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 1062cf9f02d..524a5da23c7 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -347,7 +347,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, } info->regulator = regulator_register(&dcdc_desc, &client->dev, - pdata->regulator, info); + pdata->regulator, info, NULL); if (IS_ERR(info->regulator)) { dev_err(info->dev, "failed to register regulator %s\n", dcdc_desc.name); diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 33f5d9a492e..a838e664569 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -449,7 +449,7 @@ static int __devinit max8660_probe(struct i2c_client *client, rdev[i] = regulator_register(&max8660_reg[id], &client->dev, pdata->subdevs[i].platform_data, - max8660); + max8660, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index cc9ec0e0327..f976e5d0867 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -266,7 +266,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) ri->chip = chip; rdev = regulator_register(&ri->desc, &pdev->dev, - pdata->regulator[pdev->id], ri); + pdata->regulator[pdev->id], ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 3883d85c5b8..75d89400c12 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -208,7 +208,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, max8952->pdata = pdata; max8952->rdev = regulator_register(®ulator, max8952->dev, - &pdata->reg_data, max8952); + &pdata->reg_data, max8952, NULL); if (IS_ERR(max8952->rdev)) { ret = PTR_ERR(max8952->rdev); diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 6176129a27e..d26e8646277 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -1146,7 +1146,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) regulators[id].n_voltages = 16; rdev[i] = regulator_register(®ulators[id], max8997->dev, - pdata->regulators[i].initdata, max8997); + pdata->regulators[i].initdata, max8997, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8997->dev, "regulator init failed for %d\n", diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 41a1495eec2..2d38c2493a0 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -847,7 +847,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) regulators[index].n_voltages = count; } rdev[i] = regulator_register(®ulators[index], max8998->dev, - pdata->regulators[i].initdata, max8998); + pdata->regulators[i].initdata, max8998, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8998->dev, "regulator init failed\n"); diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 8479082e1ae..56d4a677c40 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -357,7 +357,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) init_data = &pdata->regulators[i]; priv->regulators[i] = regulator_register( &mc13783_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv); + &pdev->dev, init_data->init_data, priv, NULL); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 023d17d022c..2824804a289 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -573,7 +573,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) init_data = &pdata->regulators[i]; priv->regulators[i] = regulator_register( &mc13892_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv); + &pdev->dev, init_data->init_data, priv, NULL); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 31f6e11a7f1..a5aab1b08bc 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -277,7 +277,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev) void *pcap = dev_get_drvdata(pdev->dev.parent); rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcap); + pdev->dev.platform_data, pcap, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 69a11d9dd87..1d1c3105629 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -320,7 +320,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) pcf = dev_to_pcf50633(pdev->dev.parent); rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcf); + pdev->dev.platform_data, pcf, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 1011873896d..d9278da18a9 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -151,7 +151,8 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) /* Register regulator with framework */ tps6105x->regulator = regulator_register(&tps6105x_regulator_desc, &tps6105x->client->dev, - pdata->regulator_data, tps6105x); + pdata->regulator_data, tps6105x, + NULL); if (IS_ERR(tps6105x->regulator)) { ret = PTR_ERR(tps6105x->regulator); dev_err(&tps6105x->client->dev, diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 9fb4c7b8175..7fd3b9092d1 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -496,7 +496,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, /* Register the regulators */ rdev = regulator_register(&tps->desc[i], &client->dev, - init_data, tps); + init_data, tps, NULL); if (IS_ERR(rdev)) { dev_err(&client->dev, "failed to register %s\n", id->name); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index bdef70365f5..0b63ef71a5f 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -599,7 +599,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) tps->desc[i].owner = THIS_MODULE; rdev = regulator_register(&tps->desc[i], - tps6507x_dev->dev, init_data, tps); + tps6507x_dev->dev, init_data, tps, NULL); if (IS_ERR(rdev)) { dev_err(tps6507x_dev->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 9166aa0a9df..70b7b1f4f00 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -651,7 +651,7 @@ static int __devinit pmic_probe(struct spi_device *spi) hw->desc[i].n_voltages = 1; hw->rdev[i] = regulator_register(&hw->desc[i], dev, - init_data, hw); + init_data, hw, NULL); if (IS_ERR(hw->rdev[i])) { ret = PTR_ERR(hw->rdev[i]); hw->rdev[i] = NULL; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 14b9389dd52..c75fb20faa5 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -396,7 +396,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) return err; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index b552aae55b4..654bc5bab9a 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -965,7 +965,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].owner = THIS_MODULE; rdev = regulator_register(&pmic->desc[i], - tps65910->dev, reg_data, pmic); + tps65910->dev, reg_data, pmic, NULL); if (IS_ERR(rdev)) { dev_err(tps65910->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 39d4a1749e7..da00d88f94b 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -727,7 +727,7 @@ static __devinit int tps65912_probe(struct platform_device *pdev) pmic->desc[i].owner = THIS_MODULE; range = tps65912_get_range(pmic, i); rdev = regulator_register(&pmic->desc[i], - tps65912->dev, reg_data, pmic); + tps65912->dev, reg_data, pmic, NULL); if (IS_ERR(rdev)) { dev_err(tps65912->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 11cc308d66e..181a2cfe180 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1112,7 +1112,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) break; } - rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); + rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index bd3531d8b2a..7558a9666a5 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -553,7 +553,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -747,7 +747,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -874,7 +874,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -973,7 +973,7 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->epe[id], dcdc); + pdata->epe[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register EPE%d: %d\n", diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 01f27c7f423..d3ad3f5cff4 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -189,7 +189,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) isink->desc.owner = THIS_MODULE; isink->regulator = regulator_register(&isink->desc, &pdev->dev, - pdata->isink[id], isink); + pdata->isink[id], isink, NULL); if (IS_ERR(isink->regulator)) { ret = PTR_ERR(isink->regulator); dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n", diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 6709710a059..5e96a2386b1 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -351,7 +351,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -621,7 +621,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -818,7 +818,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 1bcb22c4409..6894009d815 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1428,7 +1428,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) /* register regulator */ rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev, pdev->dev.platform_data, - dev_get_drvdata(&pdev->dev)); + dev_get_drvdata(&pdev->dev), NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s\n", wm8350_reg[pdev->id].name); diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 71632ddc378..706f39563a7 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -326,7 +326,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, wm8400); + pdev->dev.platform_data, wm8400, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index b87bf5c841f..435e335d6e6 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -269,7 +269,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ldo->is_enabled = true; ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, - pdata->ldo[id].init_data, ldo); + pdata->ldo[id].init_data, ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm8994->dev, "Failed to register LDO%d: %d\n", diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 52c89ae32f6..8fbb6964bb7 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -212,7 +212,7 @@ struct regulator_dev { struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, - void *driver_data); + void *driver_data, struct device_node *of_node); void regulator_unregister(struct regulator_dev *rdev); int regulator_notifier_call_chain(struct regulator_dev *rdev, diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index cb9818c5830..690193d439b 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -841,7 +841,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, ldo->voltage = voltage; ldo->dev = regulator_register(&ldo->desc, codec->dev, - init_data, ldo); + init_data, ldo, NULL); if (IS_ERR(ldo->dev)) { int ret = PTR_ERR(ldo->dev); -- cgit v1.2.3 From 601b52e3659b066a531e71fd6c7463350504e803 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:20 +0530 Subject: regulator: map consumer regulator based on device tree Device nodes in DT can associate themselves with one or more regulators/supply by providing a list of phandles (to regulator nodes) and corresponding supply names. For Example: devicenode: node@0x0 { ... ... vmmc-supply = <®ulator1>; vpll-supply = <®ulator2>; }; The driver would then do a regulator_get(dev, "vmmc"); to get regulator1 and do a regulator_get(dev, "vpll"); to get regulator2. of_get_regulator() extracts the regulator node for a given device, based on the supply name. Use it to look up the regulator for a given consumer from device tree, during a regulator_get(). If not found fallback and lookup through the regulator_map_list instead. Also, since the regulator dt nodes can use the same binding to associate with a parent regulator/supply, allow the drivers to specify a supply_name, which can then be used to lookup dt to find the parent phandle. Signed-off-by: Rajendra Nayak Acked-by: Grant Likely Signed-off-by: Mark Brown --- drivers/regulator/core.c | 79 ++++++++++++++++++++++++++++++++++------ include/linux/regulator/driver.h | 2 + 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index dd695b9aecf..5baa1965aa1 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -132,6 +134,33 @@ static struct regulator *get_device_regulator(struct device *dev) return NULL; } +/** + * of_get_regulator - get a regulator device node based on supply name + * @dev: Device pointer for the consumer (of regulator) device + * @supply: regulator supply name + * + * Extract the regulator device node corresponding to the supply name. + * retruns the device node corresponding to the regulator if found, else + * returns NULL. + */ +static struct device_node *of_get_regulator(struct device *dev, const char *supply) +{ + struct device_node *regnode = NULL; + char prop_name[32]; /* 32 is max size of property name */ + + dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); + + snprintf(prop_name, 32, "%s-supply", supply); + regnode = of_parse_phandle(dev->of_node, prop_name, 0); + + if (!regnode) { + dev_warn(dev, "%s property in node %s references invalid phandle", + prop_name, dev->of_node->full_name); + return NULL; + } + return regnode; +} + /* Platform voltage constraint check */ static int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) @@ -1148,6 +1177,30 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) return rdev->desc->ops->enable_time(rdev); } +static struct regulator_dev *regulator_dev_lookup(struct device *dev, + const char *supply) +{ + struct regulator_dev *r; + struct device_node *node; + + /* first do a dt based lookup */ + if (dev && dev->of_node) { + node = of_get_regulator(dev, supply); + if (node) + list_for_each_entry(r, ®ulator_list, list) + if (r->dev.parent && + node == r->dev.of_node) + return r; + } + + /* if not found, try doing it non-dt way */ + list_for_each_entry(r, ®ulator_list, list) + if (strcmp(rdev_get_name(r), supply) == 0) + return r; + + return NULL; +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) @@ -1168,6 +1221,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, mutex_lock(®ulator_list_mutex); + rdev = regulator_dev_lookup(dev, id); + if (rdev) + goto found; + list_for_each_entry(map, ®ulator_map_list, list) { /* If the mapping has a device set up it must match */ if (map->dev_name && @@ -2642,6 +2699,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; int ret, i; + const char *supply = NULL; if (regulator_desc == NULL) return ERR_PTR(-EINVAL); @@ -2718,21 +2776,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (ret < 0) goto scrub; - if (init_data->supply_regulator) { + if (init_data->supply_regulator) + supply = init_data->supply_regulator; + else if (regulator_desc->supply_name) + supply = regulator_desc->supply_name; + + if (supply) { struct regulator_dev *r; - int found = 0; - list_for_each_entry(r, ®ulator_list, list) { - if (strcmp(rdev_get_name(r), - init_data->supply_regulator) == 0) { - found = 1; - break; - } - } + r = regulator_dev_lookup(dev, supply); - if (!found) { - dev_err(dev, "Failed to find supply %s\n", - init_data->supply_regulator); + if (!r) { + dev_err(dev, "Failed to find supply %s\n", supply); ret = -ENODEV; goto scrub; } diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 8fbb6964bb7..4214b9a9d1c 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -154,6 +154,7 @@ enum regulator_type { * this type. * * @name: Identifying name for the regulator. + * @supply_name: Identifying the regulator supply * @id: Numerical identifier for the regulator. * @n_voltages: Number of selectors available for ops.list_voltage(). * @ops: Regulator operations table. @@ -163,6 +164,7 @@ enum regulator_type { */ struct regulator_desc { const char *name; + const char *supply_name; int id; unsigned n_voltages; struct regulator_ops *ops; -- cgit v1.2.3 From 57a561597e2a5c7934482589a71c30d6030ceca8 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 24 Nov 2011 12:57:17 +0530 Subject: regulator: Fix compile break due to missing arguments to regulator_register The commit 2c043bcbf287 ("regulator: pass additional of_node to regulator_register()") caused a compile break because it missed updating the regulator_register() call in gpio-regulator.c with the additional parameter (NULL). The compile break as reported by Stephen Rothwell with the x86_64 allmodconfig looked like this drivers/regulator/gpio-regulator.c: In function 'gpio_regulator_probe': drivers/regulator/gpio-regulator.c:287:8: error: too few arguments to function 'regulator_register' include/linux/regulator/driver.h:215:23: note: declared here Reported-by: Stephen Rothwell Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index f0acf52498b..42e1cb1835e 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -284,7 +284,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) drvdata->state = state; drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata); + config->init_data, drvdata, NULL); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); -- cgit v1.2.3 From d5e10b0b8c4b2cf8dac4f3ee415e661675d1923c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Nov 2011 18:50:58 +0800 Subject: regulator: export of_get_regulator_init_data of_get_regulator_init_data is called in drivers/regulator/fixed.c which could be a module. Export of_get_regulator_init_data to fix below build error: ERROR: "of_get_regulator_init_data" [drivers/regulator/fixed.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 Reported-by: Randy Dunlap Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 76673c784ab..acd7045d160 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -10,6 +10,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -79,3 +80,4 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev) of_get_regulation_constraints(dev->of_node, &init_data); return init_data; } +EXPORT_SYMBOL_GPL(of_get_regulator_init_data); -- cgit v1.2.3 From 669647a0676ee078c5a5b47216c15e2cdcf79587 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Nov 2011 20:19:19 +0800 Subject: regulator: Checking return value of of_get_regulator_init_data of_get_regulator_init_data() may return NULL, thus check the return value to avoid NULL pointer dereference. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index db90919f99c..2997f11af90 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -64,6 +64,9 @@ struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev) return NULL; config->init_data = of_get_regulator_init_data(dev); + if (!config->init_data) + return NULL; + init_data = config->init_data; config->supply_name = init_data->constraints.name; -- cgit v1.2.3 From 729a958f44042ad9fbb2d271f502242a1bcce725 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 27 Nov 2011 10:35:08 +0800 Subject: regulator: Staticise of_get_fixed_voltage_config() It is not used outside this driver so no need to make the symbol global. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 2997f11af90..703c26b756d 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -51,7 +51,8 @@ struct fixed_voltage_data { * tree node, returns a pointer to the populated structure of NULL if memory * alloc fails. */ -struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev) +static struct fixed_voltage_config * +of_get_fixed_voltage_config(struct device *dev) { struct fixed_voltage_config *config; struct device_node *np = dev->of_node; -- cgit v1.2.3 From 1bda01ec3336d0884de08ae567ce6df9a5ee3f97 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 27 Nov 2011 20:07:57 +0800 Subject: regulator: Avoid potential NULL dereference in reg_fixed_voltage_probe() of_get_fixed_voltage_config() may return NULL, return -ENOMEM in this case so we don't dereference NULL pointer. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 703c26b756d..ebec5e06dfa 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -160,12 +160,17 @@ static struct regulator_ops fixed_voltage_ops = { static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) { - struct fixed_voltage_config *config = pdev->dev.platform_data; + struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; int ret; if (pdev->dev.of_node) config = of_get_fixed_voltage_config(&pdev->dev); + else + config = pdev->dev.platform_data; + + if (!config) + return -ENOMEM; drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); if (drvdata == NULL) { -- cgit v1.2.3 From dc304b6a1f61b51ae1aec26194c1e79e3e253083 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 28 Nov 2011 21:37:16 +0800 Subject: regulator: fix label names used in device tree bindings Device tree compiler does not recognize '-' in label name. Instead, '_' works fine. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/regulator.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 82bef20d4c4..5b7a408acda 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -32,15 +32,15 @@ its just seen as a special case of a regulator being a consumer itself. Example of a consumer device node (mmc) referencing two -regulators (twl-reg1 and twl-reg2), +regulators (twl_reg1 and twl_reg2), - twl-reg1: regulator@0 { + twl_reg1: regulator@0 { ... ... ... }; - twl-reg2: regulator@1 { + twl_reg2: regulator@1 { ... ... ... @@ -49,6 +49,6 @@ regulators (twl-reg1 and twl-reg2), mmc: mmc@0x0 { ... ... - vmmc-supply = <&twl-reg1>; - vmmcaux-supply = <&twl-reg2>; + vmmc-supply = <&twl_reg1>; + vmmcaux-supply = <&twl_reg2>; }; -- cgit v1.2.3 From 44f14da8b6dd06c84b7a050f1558d432695d5557 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 5 Dec 2011 12:47:42 +0530 Subject: regulator: Fix regulator_register() API signature in Documentation The commit 2c043bcbf287 ("regulator: pass additional of_node to regulator_register()") added an additional parameter to the regulator_register() API. Update the Documentation accordingly to reflect the change in the function signature. Reported-by: Thomas Abraham Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown --- Documentation/power/regulator/regulator.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/power/regulator/regulator.txt b/Documentation/power/regulator/regulator.txt index 3f8b528f237..e272d9909e3 100644 --- a/Documentation/power/regulator/regulator.txt +++ b/Documentation/power/regulator/regulator.txt @@ -12,7 +12,7 @@ Drivers can register a regulator by calling :- struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, struct regulator_init_data *init_data, - void *driver_data); + void *driver_data, struct device_node *of_node); This will register the regulators capabilities and operations to the regulator core. -- cgit v1.2.3 From 473462b438912b197acb959e1c54271cd8828459 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Dec 2011 10:58:41 +0000 Subject: regulator: If a single voltage is set with device tree then set apply_uV Otherwise there is no way in the bindings to configure a fixed voltage via software. It seems reasonable to assume that if the binding explicitly specifies a voltage we want to actually use that voltage. Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index acd7045d160..b7b3fc3b09e 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -34,6 +34,9 @@ static void of_get_regulation_constraints(struct device_node *np, /* Voltage change possible? */ if (constraints->min_uV != constraints->max_uV) constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + /* Only one voltage? Then make sure it's set. */ + if (constraints->min_uV == constraints->max_uV) + constraints->apply_uV = true; uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); if (uV_offset) -- cgit v1.2.3 From 3f7157fbb39fc8705ad20a3a0f64bd5b6ffb74c4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 1 Dec 2011 17:21:06 +0800 Subject: regulator: pass device_node to of_get_regulator_init_data() It's not always true that the device_node of regulator can be found at dev->of_node at the time when of_get_regulator_init_data() is being called, because in some cases the regulator nodes in device tree do not have 'struct device' behind them until regulator_dev gets created for it by core function regulator_register(). The patch adds device_node as a new parameter to of_get_regulator_init_data(), so that caller can pass in the node of regulator directly. Signed-off-by: Shawn Guo Acked-by: Thomas Abraham Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 2 +- drivers/regulator/of_regulator.c | 7 ++++--- include/linux/regulator/of_regulator.h | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index ebec5e06dfa..12d08c694ae 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -64,7 +64,7 @@ of_get_fixed_voltage_config(struct device *dev) if (!config) return NULL; - config->init_data = of_get_regulator_init_data(dev); + config->init_data = of_get_regulator_init_data(dev, dev->of_node); if (!config->init_data) return NULL; diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index b7b3fc3b09e..f1651eb6964 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -69,18 +69,19 @@ static void of_get_regulation_constraints(struct device_node *np, * tree node, returns a pointer to the populated struture or NULL if memory * alloc fails. */ -struct regulator_init_data *of_get_regulator_init_data(struct device *dev) +struct regulator_init_data *of_get_regulator_init_data(struct device *dev, + struct device_node *node) { struct regulator_init_data *init_data; - if (!dev->of_node) + if (!node) return NULL; init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); if (!init_data) return NULL; /* Out of memory? */ - of_get_regulation_constraints(dev->of_node, &init_data); + of_get_regulation_constraints(node, &init_data); return init_data; } EXPORT_SYMBOL_GPL(of_get_regulator_init_data); diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index d83a98d3e3f..769704f296e 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -8,10 +8,12 @@ #if defined(CONFIG_OF) extern struct regulator_init_data - *of_get_regulator_init_data(struct device *dev); + *of_get_regulator_init_data(struct device *dev, + struct device_node *node); #else static inline struct regulator_init_data - *of_get_regulator_init_data(struct device *dev) + *of_get_regulator_init_data(struct device *dev, + struct device_node *node) { return NULL; } -- cgit v1.2.3 From 6fa4001204169477483d239b50ddaf7b65142b26 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 11:04:26 +0800 Subject: dts/imx6q-sabrelite: add 2P5V and 3P3V regulators Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index fe2d320275a..3af9c6620ad 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -140,4 +140,24 @@ compatible = "fsl,vout_ipuv3"; }; }; + + regulators { + compatible = "simple-bus"; + + reg_2P5V: regulator-2P5V { + compatible = "regulator-fixed"; + regulator-name = "2P5V"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3P3V: regulator-3P3V { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; }; -- cgit v1.2.3 From 67b839c0f6247e02718a2b94668bc968d1e0cc48 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 13:43:59 +0800 Subject: regulator/fixed: set apply_uV 0 Signed-off-by: Richard Zhao --- drivers/regulator/fixed.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 12d08c694ae..5a214b4c7c3 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -69,6 +69,7 @@ of_get_fixed_voltage_config(struct device *dev) return NULL; init_data = config->init_data; + init_data->constraints.apply_uV = 0; config->supply_name = init_data->constraints.name; if (init_data->constraints.min_uV == init_data->constraints.max_uV) { -- cgit v1.2.3 From b4e82a9f90ab2ec5ed07fa55690a94f2aa57ed84 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 14:19:42 +0800 Subject: dts/imx6q-sabrelite: add sgtl5000 audio codec Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 3af9c6620ad..213de78e774 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -58,6 +58,18 @@ status = "okay"; }; + i2c@021a0000 { /* I2C1 */ + status = "okay"; + clock-frequency = <100000>; + + codec: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + VDDA-supply = <®_2P5V>; + VDDIO-supply = <®_3P3V>; + }; + }; + i2c@021a4000 { /* I2C2 */ status = "okay"; clock-frequency = <100000>; -- cgit v1.2.3 From 174523ce57ac8e495e04b2bc96613ec353300a1f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 14 Jul 2011 13:17:41 +0800 Subject: ASoC: imx-ssi: add device tree probe support It adds device tree probe support for imx-ssi driver. Signed-off-by: Shawn Guo Cc: Grant Likely Cc: Sascha Hauer Cc: Liam Girdwood Cc: Mark Brown --- sound/soc/imx/imx-ssi.c | 63 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 563d197e37d..2e8a0ee517b 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,11 @@ #define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) +static const struct of_device_id imx_ssi_dt_ids[] = { + { .compatible = "fsl,imx1-ssi", }, + { /* sentinel */ } +}; + /* * SSI Network Mode or TDM slots configuration. * Should only be called when port is inactive (i.e. SSIEN = 0). @@ -603,11 +609,45 @@ struct snd_ac97_bus_ops soc_ac97_ops = { }; EXPORT_SYMBOL_GPL(soc_ac97_ops); +#ifdef CONFIG_OF +static int imx_ssi_probe_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct imx_ssi *ssi = platform_get_drvdata(pdev); + + if (!np) + return -ENODEV; + + if (of_get_property(np, "fsl,ssi-uses-dma", NULL)) + ssi->flags |= IMX_SSI_DMA; + + if (of_get_property(np, "fsl,ssi-asynchronous-mode", NULL)) + ssi->flags |= IMX_SSI_SYN; + + if (of_get_property(np, "fsl,ssi-network-mode", NULL)) + ssi->flags |= IMX_SSI_NET; + + if (of_get_property(np, "fsl,ssi-as-ac97", NULL)) + ssi->flags |= IMX_SSI_USE_AC97; + + if (of_get_property(np, "fsl,ssi-as-i2s-slave", NULL)) + ssi->flags |= IMX_SSI_USE_I2S_SLAVE; + + return 0; +} +#else +static inline int imx_ssi_probe_dt(struct platform_device *pdev) +{ + return -ENODEV; +} +#endif + static int imx_ssi_probe(struct platform_device *pdev) { struct resource *res; struct imx_ssi *ssi; struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; + int dma_events[2]; int ret = 0; struct snd_soc_dai_driver *dai; @@ -616,7 +656,8 @@ static int imx_ssi_probe(struct platform_device *pdev) return -ENOMEM; dev_set_drvdata(&pdev->dev, ssi); - if (pdata) { + ret = imx_ssi_probe_dt(pdev); + if (ret < 0 && pdata) { ssi->ac97_reset = pdata->ac97_reset; ssi->ac97_warm_reset = pdata->ac97_warm_reset; ssi->flags = pdata->flags; @@ -673,13 +714,20 @@ static int imx_ssi_probe(struct platform_device *pdev) ssi->dma_params_tx.peripheral_type = IMX_DMATYPE_SSI_SP; ssi->dma_params_rx.peripheral_type = IMX_DMATYPE_SSI_SP; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); - if (res) - ssi->dma_params_tx.dma = res->start; + ret = of_property_read_u32_array(pdev->dev.of_node, "fsl,dma-events", + dma_events, ARRAY_SIZE(dma_events)); + if (ret < 0) { + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); + if (res) + ssi->dma_params_tx.dma = res->start; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); - if (res) - ssi->dma_params_rx.dma = res->start; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); + if (res) + ssi->dma_params_rx.dma = res->start; + } else { + ssi->dma_params_tx.dma = dma_events[0]; + ssi->dma_params_rx.dma = dma_events[1]; + } platform_set_drvdata(pdev, ssi); @@ -768,6 +816,7 @@ static struct platform_driver imx_ssi_driver = { .driver = { .name = "imx-ssi", .owner = THIS_MODULE, + .of_match_table = imx_ssi_dt_ids, }, }; -- cgit v1.2.3 From 93b2ca743a19e378400db60e15f0d29a85017929 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 16:02:26 +0800 Subject: alsa/imx-ssi: rename fsl,ssi-asynchronous-mode to fsl,ssi-synchronous-mode Signed-off-by: Richard Zhao --- sound/soc/imx/imx-ssi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 2e8a0ee517b..a58440a2345 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -621,7 +621,7 @@ static int imx_ssi_probe_dt(struct platform_device *pdev) if (of_get_property(np, "fsl,ssi-uses-dma", NULL)) ssi->flags |= IMX_SSI_DMA; - if (of_get_property(np, "fsl,ssi-asynchronous-mode", NULL)) + if (of_get_property(np, "fsl,ssi-synchronous-mode", NULL)) ssi->flags |= IMX_SSI_SYN; if (of_get_property(np, "fsl,ssi-network-mode", NULL)) -- cgit v1.2.3 From 49b803ee71edaceb76ab7a6acd9af6284842172a Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 16:06:46 +0800 Subject: dts/imx6q: add ssi Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts | 8 ++++++++ arch/arm/boot/dts/imx6q.dtsi | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 213de78e774..aa48cf3f595 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -23,6 +23,14 @@ soc { aips-bus@02000000 { /* AIPS1 */ + spba-bus@02000000 { + ssi@0202c000 { /* SSI2 */ + status = "okay"; + fsl,ssi-uses-dma; + fsl,ssi-synchronous-mode; + }; + }; + ldb@020e0000 { disp-pwr-gpios = <&gpio1 0 0>; /* gpio2 0 */ mode = "sin0"; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index dc504ffaac2..4c35c38993e 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -185,18 +185,27 @@ }; ssi@02028000 { /* SSI1 */ + compatible = "fsl,imx6q-ssi", "fsl,imx1-ssi"; reg = <0x02028000 0x4000>; interrupts = <0 46 0x04>; + fsl,dma-events = <38 37>; + status = "disabled"; }; ssi@0202c000 { /* SSI2 */ + compatible = "fsl,imx6q-ssi", "fsl,imx1-ssi"; reg = <0x0202c000 0x4000>; interrupts = <0 47 0x04>; + fsl,dma-events = <42 41>; + status = "disabled"; }; ssi@02030000 { /* SSI3 */ + compatible = "fsl,imx6q-ssi", "fsl,imx1-ssi"; reg = <0x02030000 0x4000>; interrupts = <0 48 0x04>; + fsl,dma-events = <46 45>; + status = "disabled"; }; asrc@02034000 { -- cgit v1.2.3 From e0527d5c992833482a09765d3c2822c31b9de368 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 16:34:49 +0800 Subject: dma/imx-sdma: let imx6q choose dma driver Signed-off-by: Richard Zhao --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ab8f469f5cf..98df8cb711f 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -216,7 +216,7 @@ config PCH_DMA config IMX_SDMA tristate "i.MX SDMA support" - depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5 + depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5 || SOC_IMX6Q select DMA_ENGINE help Support the i.MX SDMA engine. This engine is integrated into -- cgit v1.2.3 From b91a4a94acda83020b64bcb05fc5a75410021154 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 17:26:31 +0800 Subject: ARM: mxc/audmux-v2: add dt support Signed-off-by: Richard Zhao --- arch/arm/plat-mxc/audmux-v2.c | 63 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c index 8cced35009b..73eb555ecb8 100644 --- a/arch/arm/plat-mxc/audmux-v2.c +++ b/arch/arm/plat-mxc/audmux-v2.c @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include #include @@ -184,9 +186,66 @@ int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, } EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); +#ifdef CONFIG_OF + +static int audmux_v2_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + if (!request_mem_region(res->start, resource_size(res), "audmux_v2")) { + dev_err(&pdev->dev, "request_mem_region failed\n"); + return -EBUSY; + } + + audmux_base = ioremap(res->start, resource_size(res)); + if (!audmux_base) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENODEV; + goto failed_ioremap; + } + + audmux_clk = clk_get(NULL, "audmux"); + if (IS_ERR(audmux_clk)) { + dev_warn(&pdev->dev, "%s: cannot get clock: %d\n", + __func__, ret); + audmux_clk = NULL; + } + + audmux_debugfs_init(); + return 0; + +failed_ioremap: + release_mem_region(res->start, resource_size(res)); + + return ret; +} + +static const struct of_device_id audmux_v2_dt_ids[] = { + { .compatible = "fsl,audmux-v2", }, + { /* sentinel */ } +}; + +static struct platform_driver audmux_v2_driver = { + .probe = audmux_v2_probe, + .driver = { + .name = "audmux_v2", + .of_match_table = audmux_v2_dt_ids, + }, +}; + +#endif + static int mxc_audmux_v2_init(void) { +#ifdef CONFIG_OF + return platform_driver_register(&audmux_v2_driver); +#else int ret; + if (cpu_is_mx51()) { audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR); } else if (cpu_is_mx31()) { @@ -194,10 +253,9 @@ static int mxc_audmux_v2_init(void) } else if (cpu_is_mx35()) { audmux_clk = clk_get(NULL, "audmux"); if (IS_ERR(audmux_clk)) { - ret = PTR_ERR(audmux_clk); printk(KERN_ERR "%s: cannot get clock: %d\n", __func__, ret); - return ret; + audmux_clk = NULL; } audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR); } else if (cpu_is_mx25()) { @@ -212,6 +270,7 @@ static int mxc_audmux_v2_init(void) } audmux_debugfs_init(); +#endif return 0; } -- cgit v1.2.3 From b10993a6471f0ac28c9c7ac09b9ac72b71cd87d1 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 17:27:40 +0800 Subject: ARM: imx6q-sabrelite: add audmux Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q-sabrelite.dts | 4 ++++ arch/arm/boot/dts/imx6q.dtsi | 2 ++ arch/arm/mach-imx/Kconfig | 1 + 3 files changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index aa48cf3f595..40a775cf0da 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -62,6 +62,10 @@ status = "okay"; }; + audmux@021d8000 { + status = "okay"; + }; + uart2: uart@021e8000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 4c35c38993e..a57adf776ae 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -552,7 +552,9 @@ }; audmux@021d8000 { + compatible = "fsl,audmux-v2"; reg = <0x021d8000 0x4000>; + status = "disabled"; }; mipi@021dc000 { /* MIPI-CSI */ diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index a5884b20fcf..b92c24e5fce 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -596,6 +596,7 @@ comment "i.MX6 family:" config SOC_IMX6Q bool "i.MX6 Quad support" select ARCH_HAS_CPUFREQ + select ARCH_MXC_AUDMUX_V2 select ARM_GIC select CACHE_L2X0 select CPU_V7 -- cgit v1.2.3 From 09a54017a37a6ea748fe6a3f1fee099d83ba833d Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Fri, 30 Dec 2011 19:59:27 +0800 Subject: dts/imx6q: add sdma script Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index a57adf776ae..15f7c930102 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -430,6 +430,7 @@ compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; reg = <0x020ec000 0x4000>; interrupts = <0 2 0x04>; + fsl,sdma-ram-script-name = "sdma-imx6q-to1.bin"; }; }; -- cgit v1.2.3 From 4c714c9599495fdc95e429b3d67e9817d5dee2bb Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 31 Dec 2011 10:25:03 +0800 Subject: fw/imx: add sdma-imx6q-to1.bin.ihex Signed-off-by: Richard Zhao --- firmware/Makefile | 1 + firmware/imx/sdma/sdma-imx6q-to1.bin | Bin 0 -> 1568 bytes 2 files changed, 1 insertion(+) create mode 100644 firmware/imx/sdma/sdma-imx6q-to1.bin diff --git a/firmware/Makefile b/firmware/Makefile index 66d0e990285..fdfc88ced67 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -146,6 +146,7 @@ ifdef CONFIG_IMX_SDMA fw-shipped-$(CONFIG_SOC_IMX50) += imx/sdma/sdma-imx50-to1.bin fw-shipped-$(CONFIG_SOC_IMX51) += imx/sdma/sdma-imx51-to3.bin fw-shipped-$(CONFIG_SOC_IMX53) += imx/sdma/sdma-imx53-to1.bin +fw-shipped-$(CONFIG_SOC_IMX6Q) += imx/sdma/sdma-imx6q-to1.bin endif fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-) diff --git a/firmware/imx/sdma/sdma-imx6q-to1.bin b/firmware/imx/sdma/sdma-imx6q-to1.bin new file mode 100644 index 00000000000..d20b897c75b Binary files /dev/null and b/firmware/imx/sdma/sdma-imx6q-to1.bin differ -- cgit v1.2.3 From 3a5def4a7f037d8713301c590ef622cd07c0a9f8 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 31 Dec 2011 10:27:56 +0800 Subject: arm/imx6q: add imx-sgtl5000 device from sabrelite board Signed-off-by: Richard Zhao --- arch/arm/mach-imx/mach-imx6q.c | 51 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/imx/Kconfig | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 3f46730ac06..dc4e99f2b95 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -124,6 +126,52 @@ static const struct of_dev_auxdata imx6q_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("fsl,vpu", MX6Q_VPU_BASE_ADDR, "mxc_vpu.0", &vpu_pdata), }; +static struct mxc_audio_platform_data mx6_sabrelite_audio_data; + +static int mx6_sabrelite_sgtl5000_init(void) +{ + struct clk *clko; + struct clk *new_parent; + int rate; + + clko = clk_get(NULL, "clko_clk"); + if (IS_ERR(clko)) { + pr_err("can't get CLKO clock.\n"); + return PTR_ERR(clko); + } + new_parent = clk_get(NULL, "ahb"); + if (!IS_ERR(new_parent)) { + clk_set_parent(clko, new_parent); + clk_put(new_parent); + } + rate = clk_round_rate(clko, 16000000); + if (rate < 8000000 || rate > 27000000) { + pr_err("Error:SGTL5000 mclk freq %d out of range!\n", rate); + clk_put(clko); + return -1; + } + + mx6_sabrelite_audio_data.sysclk = rate; + clk_set_rate(clko, rate); + clk_enable(clko); + return 0; +} + +static struct mxc_audio_platform_data mx6_sabrelite_audio_data = { + .ssi_num = 1, + .src_port = 2, + .ext_port = 4, + .init = mx6_sabrelite_sgtl5000_init, + .hp_gpio = -1, +}; + +static struct platform_device mx6_sabrelite_audio_device = { + .name = "imx-sgtl5000", + .dev = { + .platform_data = &mx6_sabrelite_audio_data, + }, +}; + static void __init imx6q_init_machine(void) { if (of_machine_is_compatible("fsl,imx6q-sabrelite")) { @@ -138,6 +186,9 @@ static void __init imx6q_init_machine(void) iram_init(MX6Q_IRAM_BASE_ADDR, MX6Q_IRAM_SIZE); + if (of_machine_is_compatible("fsl,imx6q-sabrelite")) + platform_device_register(&mx6_sabrelite_audio_device); + imx6q_pm_init(); } diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 7ffeed2d351..32f0af77869 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -49,7 +49,7 @@ config SND_SOC_PHYCORE_AC97 config SND_SOC_IMX_SGTL5000 tristate "SoC Audio support for i.MX boards with sgtl5000" - depends on MACH_MX35_3DS || MACH_MX51_BABBAGE || MACH_MX53_LOCO + depends on MACH_MX35_3DS || MACH_MX51_BABBAGE || MACH_MX53_LOCO || SOC_IMX6Q select SND_SOC_SGTL5000 select SND_MXC_SOC_MX2 help -- cgit v1.2.3 From 453c207a74c0ff3b89e8852fe3653f64ef35837f Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 31 Dec 2011 11:38:37 +0800 Subject: arm/imx6q: add cko1 clock imx6q-sabrelite board use it as audio codec clock. Signed-off-by: Richard Zhao --- arch/arm/mach-imx/clock-imx6q.c | 75 ++++++++++++++++++++++++++++++++++++++++- arch/arm/mach-imx/mach-imx6q.c | 6 ---- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c index 0ce3693ca7c..a0f1eb4a0b3 100644 --- a/arch/arm/mach-imx/clock-imx6q.c +++ b/arch/arm/mach-imx/clock-imx6q.c @@ -330,6 +330,12 @@ #define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) #define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) +#define BP_CCOSR_CKO1_EN 7 +#define BP_CCOSR_CKO1_PODF 4 +#define BM_CCOSR_CKO1_PODF (0x7 << 4) +#define BP_CCOSR_CKO1_SEL 0 +#define BM_CCOSR_CKO1_SEL (0xf << 0) + #define FREQ_480M 480000000 #define FREQ_528M 528000000 #define FREQ_594M 594000000 @@ -400,6 +406,7 @@ static struct clk ipu1_di1_clk; static struct clk ipu2_di0_clk; static struct clk ipu2_di1_clk; static struct clk enfc_clk; +static struct clk cko1_clk; static struct clk dummy_clk = {}; static unsigned long external_high_reference; @@ -945,6 +952,24 @@ static void _clk_disable(struct clk *clk) writel_relaxed(reg, clk->enable_reg); } +static int _clk_enable_1b(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg |= 0x1 << clk->enable_shift; + writel_relaxed(reg, clk->enable_reg); + + return 0; +} + +static void _clk_disable_1b(struct clk *clk) +{ + u32 reg; + reg = readl_relaxed(clk->enable_reg); + reg &= ~(0x1 << clk->enable_shift); + writel_relaxed(reg, clk->enable_reg); +} + struct divider { struct clk *clk; void __iomem *reg; @@ -990,6 +1015,7 @@ DEF_CLK_DIV1(ipu2_di0_pre_div, &ipu2_di0_pre_clk, CSCDR2, IPU2_DI0_PRE); DEF_CLK_DIV1(ipu2_di1_pre_div, &ipu2_di1_pre_clk, CSCDR2, IPU2_DI1_PRE); DEF_CLK_DIV1(ipu1_div, &ipu1_clk, CSCDR3, IPU1_HSP); DEF_CLK_DIV1(ipu2_div, &ipu2_clk, CSCDR3, IPU2_HSP); +DEF_CLK_DIV1(cko1_div, &cko1_clk, CCOSR, CKO1); #define DEF_CLK_DIV2(d, c, r, b) \ static struct divider d = { \ @@ -1045,6 +1071,7 @@ static struct divider *dividers[] = { &enfc_div, &spdif_div, &asrc_serial_div, + &cko1_div, }; static unsigned long ldb_di_clk_get_rate(struct clk *clk) @@ -1632,6 +1659,31 @@ DEF_IPU_DI_MUX(CSCDR2, 2, 1); DEF_IPU_MUX(1); DEF_IPU_MUX(2); +static struct multiplexer cko1_mux = { + .clk = &cko1_clk, + .reg = CCOSR, + .bp = BP_CCOSR_CKO1_SEL, + .bm = BM_CCOSR_CKO1_SEL, + .parents = { + &pll3_usb_otg, + &pll2_bus, + &pll1_sys, + &pll5_video, + &axi_clk, + &enfc_clk, + &ipu1_di0_clk, + &ipu1_di1_clk, + &ipu2_di0_clk, + &ipu2_di1_clk, + &ahb_clk, + &ipg_clk, + &ipg_perclk, + &ckil_clk, + &pll4_audio, + NULL + }, +}; + static struct multiplexer *multiplexers[] = { &axi_mux, &periph_mux, @@ -1674,6 +1726,7 @@ static struct multiplexer *multiplexers[] = { &ipu2_di1_mux, &ipu1_mux, &ipu2_mux, + &cko1_mux, }; static int _clk_set_parent(struct clk *clk, struct clk *parent) @@ -1754,6 +1807,21 @@ DEF_NG_CLK(asrc_serial_clk, &pll3_usb_otg); .secondary = s, \ } +#define DEF_CLK_1B(name, er, es, p, s) \ + static struct clk name = { \ + __INIT_CLK_DEBUG(name) \ + .enable_reg = er, \ + .enable_shift = es, \ + .enable = _clk_enable_1b, \ + .disable = _clk_disable_1b, \ + .get_rate = _clk_get_rate, \ + .set_rate = _clk_set_rate, \ + .round_rate = _clk_round_rate, \ + .set_parent = _clk_set_parent, \ + .parent = p, \ + .secondary = s, \ + } + DEF_CLK(aips_tz1_clk, CCGR0, CG0, &ahb_clk, NULL); DEF_CLK(aips_tz2_clk, CCGR0, CG1, &ahb_clk, NULL); DEF_CLK(apbh_dma_clk, CCGR0, CG2, &ahb_clk, NULL); @@ -1820,7 +1888,8 @@ DEF_CLK(usdhc3_clk, CCGR6, CG3, &pll2_pfd_400m, NULL); DEF_CLK(usdhc4_clk, CCGR6, CG4, &pll2_pfd_400m, NULL); DEF_CLK(emi_slow_clk, CCGR6, CG5, &axi_clk, NULL); DEF_CLK(vdo_axi_clk, CCGR6, CG6, &axi_clk, NULL); -DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, NULL); +DEF_CLK(vpu_clk, CCGR6, CG7, &axi_clk, &ocram_clk); +DEF_CLK_1B(cko1_clk, CCOSR, BP_CCOSR_CKO1_EN, &pll2_bus, NULL); static int pcie_clk_enable(struct clk *clk) { @@ -1948,6 +2017,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "gpu3d_clk", gpu3d_core_clk), _REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_core_clk), _REGISTER_CLOCK(NULL, "gpu3d_shader_clk", gpu3d_shader_clk), + _REGISTER_CLOCK("202c000.ssi", NULL, ssi2_clk), + _REGISTER_CLOCK(NULL, "clko_clk", cko1_clk), }; static u32 ccr, clpcr, ccgr1, ccgr6; @@ -2110,6 +2181,8 @@ int __init mx6q_clocks_init(void) clk_set_rate(&usdhc3_clk, 49500000); clk_set_rate(&usdhc4_clk, 49500000); + clk_set_parent(&cko1_clk, &ahb_clk); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); base = of_iomap(np, 0); WARN_ON(!base); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index dc4e99f2b95..d273c0ab189 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -131,7 +131,6 @@ static struct mxc_audio_platform_data mx6_sabrelite_audio_data; static int mx6_sabrelite_sgtl5000_init(void) { struct clk *clko; - struct clk *new_parent; int rate; clko = clk_get(NULL, "clko_clk"); @@ -139,11 +138,6 @@ static int mx6_sabrelite_sgtl5000_init(void) pr_err("can't get CLKO clock.\n"); return PTR_ERR(clko); } - new_parent = clk_get(NULL, "ahb"); - if (!IS_ERR(new_parent)) { - clk_set_parent(clko, new_parent); - clk_put(new_parent); - } rate = clk_round_rate(clko, 16000000); if (rate < 8000000 || rate > 27000000) { pr_err("Error:SGTL5000 mclk freq %d out of range!\n", rate); -- cgit v1.2.3 From 135ef23e212bb5fef4acee3c57c500da1a101cc7 Mon Sep 17 00:00:00 2001 From: Zeng Zhaoming Date: Tue, 9 Aug 2011 02:27:05 +0800 Subject: ENGR00154525 SDMA: SDMA not works when event number bigger than 32 New sdma driver in 2.6.38 kernel not map event to channel correctly by ignore events bigger than 32. Fix it by remove this restriction Signed-off-by: Zeng Zhaoming --- drivers/dma/imx-sdma.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index c3d135afe66..3d3e75aeeab 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -713,11 +713,11 @@ static int sdma_config_channel(struct sdma_channel *sdmac) sdmac->shp_addr = 0; sdmac->per_addr = 0; - if (sdmac->event_id0) { - if (sdmac->event_id0 > 32) - return -EINVAL; + if (sdmac->event_id0) sdma_event_enable(sdmac, sdmac->event_id0); - } + + if (sdmac->event_id1) + sdma_event_enable(sdmac, sdmac->event_id1); switch (sdmac->peripheral_type) { case IMX_DMATYPE_DSP: @@ -739,10 +739,10 @@ static int sdma_config_channel(struct sdma_channel *sdmac) if (sdmac->event_id1) { sdmac->event_mask1 = 1 << (sdmac->event_id1 % 32); if (sdmac->event_id1 > 31) - sdmac->watermark_level |= 1 << 31; + sdmac->watermark_level |= 1 << 29; sdmac->event_mask0 = 1 << (sdmac->event_id0 % 32); if (sdmac->event_id0 > 31) - sdmac->watermark_level |= 1 << 30; + sdmac->watermark_level |= 1 << 28; } else { sdmac->event_mask0 = 1 << sdmac->event_id0; sdmac->event_mask1 = 1 << (sdmac->event_id0 - 32); -- cgit v1.2.3 From 1152a4e7443c928b8b061480dd06d813c4006ba6 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 31 Dec 2011 20:39:13 +0800 Subject: make sgtl5000 work -- need to split to small patch Signed-off-by: Richard Zhao --- arch/arm/boot/dts/imx6q.dtsi | 2 +- arch/arm/mach-imx/clock-imx6q.c | 3 ++- arch/arm/mach-imx/mach-imx6q.c | 12 +++++++++++- arch/arm/plat-mxc/include/mach/dma.h | 3 +-- drivers/dma/imx-sdma.c | 2 ++ drivers/regulator/fixed.c | 2 +- sound/soc/imx/imx-sgtl5000.c | 8 ++++---- 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 15f7c930102..c7a26cd23e0 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -430,7 +430,7 @@ compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; reg = <0x020ec000 0x4000>; interrupts = <0 2 0x04>; - fsl,sdma-ram-script-name = "sdma-imx6q-to1.bin"; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q-to1.bin"; }; }; diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c index a0f1eb4a0b3..51cdc39a605 100644 --- a/arch/arm/mach-imx/clock-imx6q.c +++ b/arch/arm/mach-imx/clock-imx6q.c @@ -1669,6 +1669,7 @@ static struct multiplexer cko1_mux = { &pll2_bus, &pll1_sys, &pll5_video, + &dummy_clk, &axi_clk, &enfc_clk, &ipu1_di0_clk, @@ -1750,7 +1751,7 @@ static int _clk_set_parent(struct clk *clk, struct clk *parent) break; i++; } - if (!m->parents[i]) + if (!m->parents[i] || m->parents[i] == &dummy_clk) return -EINVAL; val = readl_relaxed(m->reg); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index d273c0ab189..7be60b27f13 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -35,6 +35,12 @@ #include static iomux_v3_cfg_t imx6q_sabrelite_pads[] = { + /* AUDMUX */ + MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD, + MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC, + MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD, + MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS, + /* DISPLAY */ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, MX6Q_PAD_DI0_PIN15__IPU1_DI0_PIN15, @@ -66,6 +72,11 @@ static iomux_v3_cfg_t imx6q_sabrelite_pads[] = { MX6Q_PAD_DISP0_DAT23__IPU1_DISP0_DAT_23, /* PWM1 */ MX6Q_PAD_SD1_CMD__PWM4_PWMO, + /* sgtl5000 clock */ + MX6Q_PAD_GPIO_0__CCM_CLKO, + /* I2C1, SGTL5000 */ + MX6Q_PAD_EIM_D21__I2C1_SCL, /* GPIO3[21] */ + MX6Q_PAD_EIM_D28__I2C1_SDA, /* GPIO3[28] */ /* I2C2 */ MX6Q_PAD_KEY_COL3__I2C2_SCL, MX6Q_PAD_KEY_ROW3__I2C2_SDA, @@ -144,7 +155,6 @@ static int mx6_sabrelite_sgtl5000_init(void) clk_put(clko); return -1; } - mx6_sabrelite_audio_data.sysclk = rate; clk_set_rate(clko, rate); clk_enable(clko); diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h index dd41a6475be..2003f44fca5 100644 --- a/arch/arm/plat-mxc/include/mach/dma.h +++ b/arch/arm/plat-mxc/include/mach/dma.h @@ -67,8 +67,7 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan) static inline int imx_dma_is_general_purpose(struct dma_chan *chan) { - return !strcmp(dev_name(chan->device->dev), "imx31-sdma") || - !strcmp(dev_name(chan->device->dev), "imx35-sdma") || + return strstr(dev_name(chan->device->dev), "sdma") || !strcmp(dev_name(chan->device->dev), "imx-dma"); } diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 3d3e75aeeab..248469b051b 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -403,6 +403,7 @@ static int sdma_run_channel(struct sdma_channel *sdmac) init_completion(&sdmac->done); + wmb(); __raw_writel(1 << channel, sdma->regs + SDMA_H_START); ret = wait_for_completion_timeout(&sdmac->done, HZ); @@ -809,6 +810,7 @@ out: static void sdma_enable_channel(struct sdma_engine *sdma, int channel) { + wmb(); __raw_writel(1 << channel, sdma->regs + SDMA_H_START); } diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 5a214b4c7c3..eedc9939632 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -244,7 +244,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata, NULL); + config->init_data, drvdata, pdev->dev.of_node); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); diff --git a/sound/soc/imx/imx-sgtl5000.c b/sound/soc/imx/imx-sgtl5000.c index 0ff8ee00b3c..2b025631779 100644 --- a/sound/soc/imx/imx-sgtl5000.c +++ b/sound/soc/imx/imx-sgtl5000.c @@ -275,9 +275,9 @@ static struct snd_soc_dai_link imx_sgtl5000_dai[] = { .name = "HiFi", .stream_name = "HiFi", .codec_dai_name = "sgtl5000", - .codec_name = "sgtl5000.1-000a", - .cpu_dai_name = "imx-ssi.1", - .platform_name = "imx-pcm-audio.1", + .codec_name = "sgtl5000.0-000a", + .cpu_dai_name = "202c000.ssi", + .platform_name = "imx-pcm-audio", .init = imx_3stack_sgtl5000_init, .ops = &imx_sgtl5000_hifi_ops, }, @@ -361,7 +361,7 @@ static int __init imx_sgtl5000_init(void) if (ret) return -ENOMEM; - if (machine_is_mx35_3ds()) + if (machine_is_mx35_3ds() || of_machine_is_compatible("fsl,imx6q-sabrelite")) imx_sgtl5000_dai[0].codec_name = "sgtl5000.0-000a"; else imx_sgtl5000_dai[0].codec_name = "sgtl5000.1-000a"; -- cgit v1.2.3