summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/omap3-minnow-p0.dts138
-rw-r--r--arch/arm/boot/dts/omap3-minnow.dtsi4
-rw-r--r--arch/arm/configs/minnow_defconfig5
-rw-r--r--arch/arm/mach-omap2/board-minnow-spi.c2
-rw-r--r--drivers/mfd/tps65912-core.c62
-rw-r--r--drivers/mfd/tps65912-spi.c11
-rw-r--r--drivers/regulator/tps65912-regulator.c122
-rw-r--r--drivers/spi/spi-omap2-mcspi.c3
-rw-r--r--include/linux/mfd/tps65912.h12
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];
};
/**