summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-02-05 11:00:45 -0800
committerGerrit Code Review <fermi-cygwin@git-master-01.nvidia.com>2010-02-05 11:00:45 -0800
commit70596967537090788100027f0e0bf8eae9db39b4 (patch)
tree568cf49865f9122e93e852096acaf61034ad1552
parentd289f584b9a0be78232e1c8c5844eaaa211aa984 (diff)
parent394c6535f18005ca80336b1b7128b488243e0381 (diff)
Merge "tegra: Add 1-wire bus master driver for Tegra SOCs" into android-tegra-2.6.29
-rw-r--r--arch/arm/configs/tegra_whistler_android_defconfig23
-rw-r--r--arch/arm/mach-tegra/include/mach/nvrm_linux.h1
-rw-r--r--arch/arm/mach-tegra/include/nvodm_query_pinmux.h21
-rwxr-xr-xarch/arm/mach-tegra/init_common.c37
-rw-r--r--drivers/w1/masters/Kconfig7
-rw-r--r--drivers/w1/masters/Makefile1
-rw-r--r--drivers/w1/masters/tegra_w1.c222
-rwxr-xr-xinclude/linux/tegra_devices.h7
8 files changed, 317 insertions, 2 deletions
diff --git a/arch/arm/configs/tegra_whistler_android_defconfig b/arch/arm/configs/tegra_whistler_android_defconfig
index 6e341676dba1..868c3471983e 100644
--- a/arch/arm/configs/tegra_whistler_android_defconfig
+++ b/arch/arm/configs/tegra_whistler_android_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.29
-# Mon Jan 18 12:46:38 2010
+# Thu Jan 28 11:24:02 2010
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -871,7 +871,26 @@ CONFIG_SPI_TEGRA=y
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
-# CONFIG_W1 is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+CONFIG_W1_MASTER_TEGRA=y
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
diff --git a/arch/arm/mach-tegra/include/mach/nvrm_linux.h b/arch/arm/mach-tegra/include/mach/nvrm_linux.h
index 035de018f01d..cdf00221dc48 100644
--- a/arch/arm/mach-tegra/include/mach/nvrm_linux.h
+++ b/arch/arm/mach-tegra/include/mach/nvrm_linux.h
@@ -48,6 +48,7 @@
#include <nvrm_init.h>
#include <nvrm_i2c.h>
+#include <nvrm_owr.h>
#include <nvrm_gpio.h>
#include <nvodm_query_pinmux.h>
#include <nvodm_query.h>
diff --git a/arch/arm/mach-tegra/include/nvodm_query_pinmux.h b/arch/arm/mach-tegra/include/nvodm_query_pinmux.h
index c0b2e48cb134..5365201b8457 100644
--- a/arch/arm/mach-tegra/include/nvodm_query_pinmux.h
+++ b/arch/arm/mach-tegra/include/nvodm_query_pinmux.h
@@ -194,6 +194,27 @@ typedef enum
} NvOdmHsmmcPinMap;
/**
+ * Defines the OWR pin-mux configurations.
+ */
+typedef enum
+{
+ NvOdmOwrPinMap_Config1 = 1,
+ NvOdmOwrPinMap_Config2,
+ NvOdmOwrPinMap_Config3,
+
+ /**
+ * This configuration disables (tristates) OWR pins. This option may be
+ * used to change which pins an attached OWR device is using at runtime.
+ * In some cases, one device might set up OWR, communicate across this bus,
+ * and then set the OWR bus configuration to "multiplexed" so that another
+ * device can opt to use OWR with its own configurations at a later time.
+ */
+ NvOdmOwrPinMap_Multiplexed = NVODM_QUERY_PINMAP_MULTIPLEXED,
+ /** Ignore -- Forces compilers to make 32-bit enums. */
+ NvOdmOwrPinMap_Force32 = 0x7FFFFFFF,
+} NvOdmOwrPinMap;
+
+/**
* Defines I2C pin-mux configurations.
*/
typedef enum
diff --git a/arch/arm/mach-tegra/init_common.c b/arch/arm/mach-tegra/init_common.c
index 97809fc0d086..b054a1bf40af 100755
--- a/arch/arm/mach-tegra/init_common.c
+++ b/arch/arm/mach-tegra/init_common.c
@@ -256,6 +256,42 @@ static void __init tegra_register_spi(void)
}
#endif
+#if !defined(CONFIG_W1_MASTER_TEGRA)
+#define tegra_register_w1() do { } while (0)
+#else
+static void __init tegra_register_w1(void)
+{
+ const NvU32 *pPinMuxes;
+ NvU32 NumPinMuxes, NumModules;
+ struct platform_device *pDev;
+ struct tegra_w1_platform_data W1Data;
+ NvU32 i;
+
+ NumModules = NvRmModuleGetNumInstances(s_hRmGlobal, NvOdmIoModule_OneWire);
+ NvOdmQueryPinMux(NvOdmIoModule_OneWire, &pPinMuxes, &NumPinMuxes);
+
+ for (i=0; i < NumModules && i < NumPinMuxes; i++)
+ {
+ if (!pPinMuxes[i])
+ continue;
+
+ pDev = platform_device_alloc("tegra_w1", i);
+ if (!pDev)
+ goto fail;
+ W1Data.Instance = i;
+ W1Data.PinMuxConfig = pPinMuxes[i];
+ if (platform_device_add_data(pDev, &W1Data, sizeof(W1Data)))
+ goto fail;
+ if (platform_device_add(pDev))
+ goto fail;
+ }
+ return;
+fail:
+ if (pDev)
+ platform_device_del(pDev);
+}
+#endif
+
#if !defined(CONFIG_I2C_TEGRA)
#define tegra_register_i2c() do { } while (0)
#else
@@ -873,6 +909,7 @@ void __init tegra_common_init(void)
tegra_register_uart();
tegra_register_sdio();
tegra_register_usb();
+ tegra_register_w1();
#ifdef CONFIG_PM
/* FIXME : Uncomment this for actual suspend/resume
tegra_set_suspend_ops(); */
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 96d2f8e4c275..5bad3a3effac 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -40,6 +40,13 @@ config W1_MASTER_MXC
help
Say Y here to enable MXC 1-wire host
+config W1_MASTER_TEGRA
+ boolean "NVIDIA Tegra internal 1-wire controller"
+ depends on W1 && ARCH_TEGRA
+ help
+ If you say yes to this option, support will be included for the
+ 1-wire controller embedded in NVIDIA Tegra SOCs
+
config W1_MASTER_DS1WM
tristate "Maxim DS1WM 1-wire busmaster"
depends on W1 && ARM && HAVE_CLK
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index c5a3e96fcbab..45eeae881ee7 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o
obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o
obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o
+obj-$(CONFIG_W1_MASTER_TEGRA) += tegra_w1.o
obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o
obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o
diff --git a/drivers/w1/masters/tegra_w1.c b/drivers/w1/masters/tegra_w1.c
new file mode 100644
index 000000000000..f0418da1c5b8
--- /dev/null
+++ b/drivers/w1/masters/tegra_w1.c
@@ -0,0 +1,222 @@
+/*
+ * drivers/w1/masters/tegra-w1.c
+ *
+ * ONE WIRE (OWR) bus driver for internal OWR controllers in NVIDIA Tegra SoCs
+ *
+ * Copyright (C) 2010 NVIDIA Corporation
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/tegra_devices.h>
+#include <asm/uaccess.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_log.h"
+
+#include <mach/nvrm_linux.h>
+#include <nvrm_module.h>
+#include <nvos.h>
+#include <nvodm_query_discovery.h>
+
+struct tegra_w1_dev
+{
+ NvRmOwrHandle OwrHandle;
+ NvOdmOwrPinMap pin_map;
+ struct w1_bus_master bus_master;
+};
+
+static u8 tegra_w1_read_byte(void *data)
+{
+ struct tegra_w1_dev *dev = data;
+ NvRmOwrTransactionInfo tInfo;
+ NvError err;
+ u8 buffer[1];
+
+ tInfo.Flags = NvRmOwr_ReadByte;
+ tInfo.NumBytes = 1;
+ tInfo.Address = 0;
+ tInfo.Offset = 0;
+
+ err = NvRmOwrTransaction(dev->OwrHandle, dev->pin_map,
+ buffer, tInfo.NumBytes, &tInfo, 1);
+ if (err != NvSuccess)
+ {
+ printk(KERN_ERR "tegra_w1_read_byte failed 0x%x\r\n", err);
+ err = -EIO;
+ }
+
+ if (!err)
+ return buffer[0];
+ else
+ return 0;
+}
+
+static void tegra_w1_write_byte(void *data, u8 a_byte)
+{
+ struct tegra_w1_dev *dev = data;
+ NvRmOwrTransactionInfo tInfo;
+ NvError err;
+ u8 buffer[1];
+
+ tInfo.Flags = NvRmOwr_WriteByte;
+ tInfo.NumBytes = 1;
+ tInfo.Address = 0;
+ tInfo.Offset = 0;
+ buffer[0] = a_byte;
+
+ err = NvRmOwrTransaction(dev->OwrHandle, dev->pin_map,
+ buffer, tInfo.NumBytes, &tInfo, 1);
+ if (err != NvSuccess)
+ {
+ printk(KERN_ERR "tegra_w1_write_byte failed 0x%x\r\n", err);
+ err = -EIO;
+ }
+}
+
+static u8 tegra_w1_reset_bus(void *data)
+{
+ struct tegra_w1_dev *dev = data;
+ NvRmOwrTransactionInfo tInfo;
+ NvError err;
+ u8 buffer[1];
+
+ tInfo.Flags = NvRmOwr_CheckPresence;
+ tInfo.NumBytes = 1;
+ tInfo.Address = 0;
+ tInfo.Offset = 0;
+
+ err = NvRmOwrTransaction(dev->OwrHandle, dev->pin_map,
+ buffer, tInfo.NumBytes, &tInfo, 1);
+ if (err != NvSuccess)
+ {
+ printk(KERN_ERR "tegra_w1_reset_bus failed 0x%x\r\n", err);
+ err = -EIO;
+ }
+
+ if (!err)
+ {
+ /* Device present */
+ return 0;
+ }
+ else
+ {
+ /* No Device present */
+ return 1;
+ }
+}
+
+static int tegra_w1_probe(struct platform_device *pdev)
+{
+ struct tegra_w1_dev *dev;
+ struct tegra_w1_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+ NvError err;
+
+ printk(KERN_INFO "tegra_w1_probe\r\n");
+ printk(KERN_INFO "Instance = %d, PinMuxConfig = %d\r\n",
+ pdata->Instance, pdata->PinMuxConfig);
+
+ if (pdata == NULL)
+ return -ENODEV;
+
+ dev = kzalloc(sizeof(struct tegra_w1_dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ err = NvRmOwrOpen(s_hRmGlobal, pdata->Instance, &dev->OwrHandle);
+ if (err)
+ {
+ ret = -ENODEV;
+ printk(KERN_INFO "Failed to open NvRmOwrOpen - returned %d\n", err);
+ goto err_rmapi_failed;
+ }
+
+ dev->pin_map = pdata->PinMuxConfig;
+ dev->bus_master.data = dev;
+ dev->bus_master.read_byte = tegra_w1_read_byte;
+ dev->bus_master.write_byte = tegra_w1_write_byte;
+ dev->bus_master.reset_bus = tegra_w1_reset_bus;
+
+ ret = w1_add_master_device(&dev->bus_master);
+ if (ret)
+ {
+ printk(KERN_INFO "w1_add_master_device - failed %d\r\n", ret);
+ goto err_w1_add_master_device_failed;
+ }
+
+ platform_set_drvdata(pdev, dev);
+
+ return 0;
+
+err_rmapi_failed:
+err_w1_add_master_device_failed:
+ kfree(dev);
+ return ret;
+}
+
+static int
+tegra_w1_remove(struct platform_device *pdev)
+{
+ struct tegra_w1_dev *dev = platform_get_drvdata(pdev);
+
+ NvRmOwrClose(dev->OwrHandle);
+ w1_remove_master_device(&dev->bus_master);
+ platform_set_drvdata(pdev, NULL);
+ kfree(dev);
+ return 0;
+}
+
+static int tegra_w1_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+static int tegra_w1_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver tegra_w1_driver = {
+ .probe = tegra_w1_probe,
+ .remove = tegra_w1_remove,
+ .suspend = tegra_w1_suspend,
+ .resume = tegra_w1_resume,
+ .driver =
+ {
+ .name = "tegra_w1",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init
+tegra_w1_init(void)
+{
+ return platform_driver_register(&tegra_w1_driver);
+}
+module_init(tegra_w1_init);
+
+static void __exit tegra_w1_exit(void)
+{
+ platform_driver_unregister(&tegra_w1_driver);
+}
+module_exit(tegra_w1_exit);
diff --git a/include/linux/tegra_devices.h b/include/linux/tegra_devices.h
index 143037a4a64e..adbfffe92f53 100755
--- a/include/linux/tegra_devices.h
+++ b/include/linux/tegra_devices.h
@@ -66,6 +66,13 @@ struct tegra_i2c_platform_data {
NvOdmI2cPinMap PinMuxConfig;
};
+/* Platfrom data for W1 bus driver */
+struct tegra_w1_platform_data {
+ NvU32 Instance;
+ NvOdmOwrPinMap PinMuxConfig;
+};
+
+
/* Platfrom data for SPI bus driver */
struct tegra_spi_platform_data {
NvU32 IoModuleID;