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];  };  /**  |