diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/tegra_hsuart.c | 15 | ||||
-rw-r--r-- | drivers/w1/masters/Kconfig | 7 | ||||
-rw-r--r-- | drivers/w1/masters/Makefile | 1 | ||||
-rw-r--r-- | drivers/w1/masters/tegra_w1.c | 222 |
4 files changed, 238 insertions, 7 deletions
diff --git a/drivers/serial/tegra_hsuart.c b/drivers/serial/tegra_hsuart.c index 489283a88402..e409b4ef8438 100644 --- a/drivers/serial/tegra_hsuart.c +++ b/drivers/serial/tegra_hsuart.c @@ -301,6 +301,12 @@ static void tegra_tx_dma_workqueue(struct work_struct *w) return; } + /* PIO is in flight. Just return */ + if (t->tx_pio_inflight == true) { + spin_unlock_irqrestore(&u->lock, flags); + return; + } + /* DMA just finished. Wait for the FIFO to drain. */ if (t->tx_dma_req.size) { /* FIXME: Do a better job on computing the delay */ @@ -324,16 +330,11 @@ static void tegra_tx_dma_workqueue(struct work_struct *w) u->icount.tx += t->tx_dma_req.size; t->tx_dma_req.size = 0; - /* PIO is in flight. Just return */ - if (t->tx_pio_inflight == true) { - spin_unlock_irqrestore(&u->lock, flags); - return; - } - if (uart_circ_empty(xmit)) { spin_unlock_irqrestore(&u->lock, flags); return; } + to_send = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); to_send &= ~0x3; @@ -729,7 +730,7 @@ static int tegra_startup(struct uart_port *u) t->use_tx_dma = true; } if (t->use_tx_dma) { - t->tx_dma_virt = dma_alloc_writecombine(t->uport.dev, + t->tx_dma_virt = dma_alloc_coherent(t->uport.dev, UART_XMIT_SIZE, &t->tx_dma_phys, GFP_KERNEL); if (t->tx_dma_virt) { t->tx_dma_size = UART_XMIT_SIZE; 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); |