diff options
| -rw-r--r-- | arch/arm/boot/dts/omap3-minnow-p0.dts | 138 | ||||
| -rw-r--r-- | arch/arm/boot/dts/omap3-minnow.dtsi | 4 | ||||
| -rw-r--r-- | arch/arm/configs/minnow_defconfig | 5 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-minnow-spi.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/tps65912-core.c | 62 | ||||
| -rw-r--r-- | drivers/mfd/tps65912-spi.c | 11 | ||||
| -rw-r--r-- | drivers/regulator/tps65912-regulator.c | 122 | ||||
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 3 | ||||
| -rw-r--r-- | include/linux/mfd/tps65912.h | 12 |
9 files changed, 340 insertions, 19 deletions
diff --git a/arch/arm/boot/dts/omap3-minnow-p0.dts b/arch/arm/boot/dts/omap3-minnow-p0.dts index bfa9f4f354d..bd485b0af11 100644 --- a/arch/arm/boot/dts/omap3-minnow-p0.dts +++ b/arch/arm/boot/dts/omap3-minnow-p0.dts @@ -12,4 +12,142 @@ / { mmi,revision = "p0"; mmi,hwrev = <0x00>; + +}; + +&mcspi1 { + + tps65912 { + + compatible = "ti,tps65912"; + reg = <0>; /* CS 0 */ + spi-max-frequency = <1000000>; + spi-cs-high; + + dcdc1_avs; + dcdc4_avs; + + regulators { + sw1_iva_reg: regulator@0 { + reg = <0>; + regulator-compatible = "DCDC1"; + regulator-name = "DCDC1"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1287500>; + regulator-boot-on; + regulator-always-on; + }; + + sw2_reg: regulator@1 { + reg = <1>; + regulator-compatible = "DCDC2"; + regulator-name = "DCDC2"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3_reg: regulator@2 { + reg = <2>; + regulator-compatible = "DCDC3"; + regulator-name = "DCDC3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + sw4_core_reg: regulator@3 { + reg = <3>; + regulator-compatible = "DCDC4"; + regulator-name = "DCDC4"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1287500>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@4 { + reg = <4>; + regulator-compatible = "LDO1"; + regulator-name = "LDO1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo2_reg: regulator@5 { + reg = <5>; + regulator-compatible = "LDO2"; + regulator-name = "LDO2"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1700000>; + }; + + ldo3_reg: regulator@6 { + reg = <6>; + regulator-compatible = "LDO3"; + regulator-name = "LDO3"; + regulator-min-microvolt = <2950000>; + regulator-max-microvolt = <2950000>; + }; + + ldo4_reg: regulator@7 { + reg = <7>; + regulator-compatible = "LDO4"; + regulator-name = "LDO4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo5_reg: regulator@8 { + reg = <8>; + regulator-compatible = "LDO5"; + regulator-name = "LDO5"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo6_reg: regulator@9 { + reg = <9>; + regulator-compatible = "LDO6"; + regulator-name = "LDO6"; + regulator-min-microvolt = <2300000>; + regulator-max-microvolt = <2300000>; + }; + + ldo7_reg: regulator@10 { + reg = <10>; + regulator-compatible = "LDO7"; + regulator-name = "LDO7"; + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + + ldo8_reg: regulator@11 { + reg = <11>; + regulator-compatible = "LDO8"; + regulator-name = "LDO8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + ldo9_reg: regulator@12 { + reg = <12>; + regulator-compatible = "LDO9"; + regulator-name = "LDO9"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + }; + + ldo10_reg: regulator@13 { + reg = <13>; + regulator-compatible = "LDO10"; + regulator-name = "LDO10"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + }; + }; + }; }; diff --git a/arch/arm/boot/dts/omap3-minnow.dtsi b/arch/arm/boot/dts/omap3-minnow.dtsi index 46ff9960edf..ce18245f0ed 100644 --- a/arch/arm/boot/dts/omap3-minnow.dtsi +++ b/arch/arm/boot/dts/omap3-minnow.dtsi @@ -174,6 +174,10 @@ 0x1a0 0x11b /* MCSPI1_CS1, MODE3 | INPUT_PULLUP */ 0x18e 0x118 /* I2C2_SCL, MODE0 | INPUT_PULLUP */ 0x190 0x118 /* I2C2_SDA, MODE0 | INPUT_PULLUP */ + 0x198 0x100 /* MCSPI1_CLK, MODE0 | INPUT */ + 0x19a 0x000 /* MCSPI1_SIMO, MODE0 | OUTPUT */ + 0x19c 0x100 /* MCSPI1_SOMI, MODE0 | INPUT */ + 0x19e 0x000 /* MCSPI1_CS0, MODE0 | OUTPUT */ 0x1a6 0x100 /* MCSPI2_CLK, MODE0 | INPUT */ 0x1a8 0x000 /* MCSPI2_SIMO, MODE0 | OUTPUT */ 0x1aa 0x100 /* MCSPI2_SOMI, MODE0 | INPUT */ diff --git a/arch/arm/configs/minnow_defconfig b/arch/arm/configs/minnow_defconfig index cf5d45a31b4..eab32287d7d 100644 --- a/arch/arm/configs/minnow_defconfig +++ b/arch/arm/configs/minnow_defconfig @@ -1458,9 +1458,9 @@ CONFIG_MFD_CPCAP=y # CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912 is not set +CONFIG_MFD_TPS65912=y # CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_MFD_TPS65912_SPI is not set +CONFIG_MFD_TPS65912_SPI=y # CONFIG_MFD_TPS80031 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_TWL6040_CORE is not set @@ -1502,6 +1502,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_TPS65912=y CONFIG_REGULATOR_CPCAP=y # CONFIG_MEDIA_SUPPORT is not set CONFIG_MFD_M4SENSORHUB=m diff --git a/arch/arm/mach-omap2/board-minnow-spi.c b/arch/arm/mach-omap2/board-minnow-spi.c index a00cb01c0d9..bc0a1abd38c 100644 --- a/arch/arm/mach-omap2/board-minnow-spi.c +++ b/arch/arm/mach-omap2/board-minnow-spi.c @@ -452,7 +452,7 @@ static struct spi_board_info minnow_spi_board_info[] __initdata = { { .modalias = "cpcap", .bus_num = 1, - .chip_select = 0, + .chip_select = 1, .max_speed_hz = 3000000, .controller_data = &minnow_cpcap_data, .mode = SPI_CS_HIGH, diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index dfd832d0aef..6165c1fc36d 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -20,6 +20,7 @@ #include <linux/gpio.h> #include <linux/mfd/core.h> #include <linux/mfd/tps65912.h> +#include <linux/of_device.h> static struct mfd_cell tps65912s[] = { { @@ -121,9 +122,53 @@ int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val) } EXPORT_SYMBOL_GPL(tps65912_reg_write); +#ifdef CONFIG_OF +static struct tps65912_board *tps65912_parse_dt(struct tps65912 *tps65912) +{ + struct device_node *np = tps65912->dev->of_node; + struct tps65912_board *board_info; + + board_info = kzalloc(sizeof(struct tps65912_board), GFP_KERNEL); + if (!board_info) { + pr_info("kzalloc failed in tps65912_parse_dt\n"); + return NULL; + } + + if (of_find_property(np, "dcdc1_avs", NULL)) { + board_info->is_dcdc1_avs = 1; + pr_info("dcdc1_avs is 1\n"); + } + + if (of_find_property(np, "dcdc2_avs", NULL)) { + board_info->is_dcdc2_avs = 1; + pr_info("dcdc2_avs is 1\n"); + } + + if (of_find_property(np, "dcdc3_avs", NULL)) { + board_info->is_dcdc3_avs = 1; + pr_info("dcdc3_avs is 1\n"); + } + + if (of_find_property(np, "dcdc4_avs", NULL)) { + board_info->is_dcdc4_avs = 1; + pr_info("dcdc4_avs is 1\n"); + } + + board_info->irq = tps65912->irq_num; + board_info->irq_base = 0; + return board_info; +} +#else +static inline +struct tps65912_board *tps65912_parse_dt(struct tps65912 *tps65912) +{ + return NULL; +} +#endif + int tps65912_device_init(struct tps65912 *tps65912) { - struct tps65912_board *pmic_plat_data = tps65912->dev->platform_data; + struct tps65912_board *pmic_plat_data; struct tps65912_platform_data *init_data; int ret, dcdc_avs, value; @@ -131,6 +176,17 @@ int tps65912_device_init(struct tps65912 *tps65912) if (init_data == NULL) return -ENOMEM; + pmic_plat_data = dev_get_platdata(tps65912->dev); + + if (!pmic_plat_data && tps65912->dev->of_node) + pmic_plat_data = tps65912_parse_dt(tps65912); + + if (!pmic_plat_data) { + pr_info("Platform data not found\n"); + kfree(init_data); + return -EINVAL; + } + mutex_init(&tps65912->io_mutex); dev_set_drvdata(tps65912->dev, tps65912); @@ -138,6 +194,7 @@ int tps65912_device_init(struct tps65912 *tps65912) pmic_plat_data->is_dcdc2_avs << 1 | pmic_plat_data->is_dcdc3_avs << 2 | pmic_plat_data->is_dcdc4_avs << 3); + if (dcdc_avs) { tps65912->read(tps65912, TPS65912_I2C_SPI_CFG, 1, &value); dcdc_avs |= value; @@ -165,10 +222,13 @@ int tps65912_device_init(struct tps65912 *tps65912) kfree(init_data); return ret; +#ifdef CONFIG_MFD_TPS65912_DEBUGFS err_debugfs: +#endif tps65912_irq_exit(tps65912); err: kfree(init_data); + kfree(pmic_plat_data); mfd_remove_devices(tps65912->dev); kfree(tps65912); return ret; diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index b45f460d299..bf520899b13 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -21,6 +21,7 @@ #include <linux/spi/spi.h> #include <linux/mfd/core.h> #include <linux/mfd/tps65912.h> +#include <linux/of_device.h> static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr, int bytes, void *src) @@ -81,6 +82,14 @@ static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr, return ret; } +#ifdef CONFIG_OF +static struct of_device_id tps65912_of_match[] = { + { .compatible = "ti,tps65912" }, + { }, +}; +MODULE_DEVICE_TABLE(of, tps65912_of_match); +#endif + static int tps65912_spi_probe(struct spi_device *spi) { struct tps65912 *tps65912; @@ -111,7 +120,9 @@ static int tps65912_spi_remove(struct spi_device *spi) static struct spi_driver tps65912_spi_driver = { .driver = { .name = "tps65912", + .bus = &spi_bus_type, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tps65912_of_match), }, .probe = tps65912_spi_probe, .remove = tps65912_spi_remove, diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 17e994e47dc..6126d107a18 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -23,6 +23,9 @@ #include <linux/slab.h> #include <linux/gpio.h> #include <linux/mfd/tps65912.h> +#include <linux/of_device.h> +#include <linux/regulator/of_regulator.h> +#include <linux/delay.h> /* DCDC's */ #define TPS65912_REG_DCDC1 0 @@ -42,15 +45,6 @@ #define TPS65912_REG_LDO9 12 #define TPS65912_REG_LDO10 13 -/* Number of step-down converters available */ -#define TPS65912_NUM_DCDC 4 - -/* Number of LDO voltage regulators available */ -#define TPS65912_NUM_LDO 10 - -/* Number of total regulators available */ -#define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO) - #define TPS65912_REG_ENABLED 0x80 #define OP_SELREG_MASK 0x40 #define OP_SELREG_SHIFT 6 @@ -121,7 +115,7 @@ struct tps65912_reg { static int tps65912_get_range(struct tps65912_reg *pmic, int id) { struct tps65912 *mfd = pmic->mfd; - int range; + int range = 0; switch (id) { case TPS65912_REG_DCDC1: @@ -459,6 +453,76 @@ static struct regulator_ops tps65912_ops_ldo = { .list_voltage = tps65912_list_voltage, }; +#ifdef CONFIG_OF + +static struct of_regulator_match tps65912_matches[] = { + { .name = "DCDC1" }, + { .name = "DCDC2" }, + { .name = "DCDC3" }, + { .name = "DCDC4" }, + { .name = "LDO1" }, + { .name = "LDO2" }, + { .name = "LDO3" }, + { .name = "LDO4" }, + { .name = "LDO5" }, + { .name = "LDO6" }, + { .name = "LDO7" }, + { .name = "LDO8" }, + { .name = "LDO9" }, + { .name = "LDO10" }, +}; + +static struct tps65912_board *tps65912_parse_dt_reg_data( + struct platform_device *pdev) +{ + struct tps65912_board *pmic_plat_data; + struct device_node *np, *regulators; + struct of_regulator_match *matches; + int idx = 0, ret, count; + + pmic_plat_data = devm_kzalloc(&pdev->dev, sizeof(*pmic_plat_data), + GFP_KERNEL); + + if (!pmic_plat_data) { + dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n"); + return NULL; + } + + np = of_node_get(pdev->dev.parent->of_node); + regulators = of_find_node_by_name(np, "regulators"); + if (!regulators) { + dev_err(&pdev->dev, "regulator node not found\n"); + return NULL; + } + count = ARRAY_SIZE(tps65912_matches); + matches = tps65912_matches; + + ret = of_regulator_match(&pdev->dev, regulators, matches, count); + of_node_put(regulators); + if (ret < 0) { + dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", + ret); + return NULL; + } + + for (idx = 0; idx < count; idx++) { + if (!matches[idx].init_data || !matches[idx].of_node) + continue; + + pmic_plat_data->tps65912_pmic_init_data[idx] = + matches[idx].init_data; + } + + return pmic_plat_data; +} +#else +static inline struct tps65912_board *tps65912_parse_dt_reg_data( + struct platform_device *pdev) +{ + return NULL; +} +#endif + static int tps65912_probe(struct platform_device *pdev) { struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); @@ -469,12 +533,18 @@ static int tps65912_probe(struct platform_device *pdev) struct tps65912_reg *pmic; struct tps65912_board *pmic_plat_data; int i, err; + char *ldo_string[] = {"LDO1", "LDO2", "LDO3", "LDO4", "LDO5", + "LDO6", "LDO7", "LDO8", "LDO9", "LDO10"}; + struct regulator *ldo; pmic_plat_data = dev_get_platdata(tps65912->dev); - if (!pmic_plat_data) - return -EINVAL; + if (!pmic_plat_data && tps65912->dev->of_node) + pmic_plat_data = tps65912_parse_dt_reg_data(pdev); - reg_data = pmic_plat_data->tps65912_pmic_init_data; + if (!pmic_plat_data) { + dev_err(&pdev->dev, "Platform data not found\n"); + return -EINVAL; + } pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) @@ -487,8 +557,9 @@ static int tps65912_probe(struct platform_device *pdev) pmic->get_ctrl_reg = &tps65912_get_ctrl_register; info = tps65912_regs; - for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) { + for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++) { int range = 0; + reg_data = pmic_plat_data->tps65912_pmic_init_data[i]; /* Register the regulators */ pmic->info[i] = info; @@ -517,6 +588,29 @@ static int tps65912_probe(struct platform_device *pdev) /* Save regulator for cleanup */ pmic->rdev[i] = rdev; } + + for (i = 0; i < TPS65912_NUM_LDO; i++) { + ldo = regulator_get(NULL, ldo_string[i]); + if (IS_ERR(ldo)) { + pr_info("%s regulator get fails\n", ldo_string[i]); + } else { + err = regulator_enable(ldo); + if (err == 0) + pr_info("%s regulator enables success\n", + ldo_string[i]); + else + pr_info("%s regulator enables fails%d\n", + ldo_string[i], err); + } + /* to disable the ldo for vibrator after a while */ + if (i == 5) { + mdelay(200); + regulator_disable(ldo); + pr_info("%s regulator disabled on purpose\n", + ldo_string[i]); + } + } + return 0; err: diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 86d2158946b..126289d99e1 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1070,6 +1070,9 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, const void *tx_buf = t->tx_buf; void *rx_buf = t->rx_buf; unsigned len = t->len; + if ((t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) || + t->speed_hz > OMAP2_MCSPI_MAX_FREQ) + t->speed_hz = 1000000; if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ || (len && !(rx_buf || tx_buf)) diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h index f456529d800..26c7897d1eb 100644 --- a/include/linux/mfd/tps65912.h +++ b/include/linux/mfd/tps65912.h @@ -264,6 +264,15 @@ #define DCDC_LIMIT_MAX_SEL_MASK 0x3F #define DCDC_LIMIT_MAX_SEL_SHIFT 0 +/* Number of step-down converters available */ +#define TPS65912_NUM_DCDC 4 + +/* Number of LDO voltage regulators available */ +#define TPS65912_NUM_LDO 10 + +/* Number of total regulators available */ +#define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO) + /** * struct tps65912_board * Board platform dat may be used to initialize regulators. @@ -276,7 +285,8 @@ struct tps65912_board { int irq; int irq_base; int gpio_base; - struct regulator_init_data *tps65912_pmic_init_data; + struct regulator_init_data + *tps65912_pmic_init_data[TPS65912_NUM_REGULATOR]; }; /** |