Merge changes Ief2357bb,Iac66d768,Ib49a41f5 into msm-3.0
* changes:
defconfig: 9615: Enable USB BAM driver
msm: board-9615: Add USB BAM driver
usb: gadget: SPS BAM-to-BAM - USB BAM driver
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 003f9c1..b5aa1b4 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -188,6 +188,7 @@
CONFIG_MSM_SSBI=y
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_USB_BAM=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 5efafae..be0e4e6 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -727,6 +727,39 @@
0x13, 0x83,/* set source impedance adjustment */
-1};
+#define USB_BAM_PHY_BASE 0x12502000
+#define USB_BAM_PHY_SIZE 0x10000
+#define A2_BAM_PHY_BASE 0x124C2000
+static struct usb_bam_pipe_connect msm_usb_bam_connections[4][2] = {
+ [0][USB_TO_PEER_PERIPHERAL] = {
+ .src_phy_addr = USB_BAM_PHY_BASE,
+ .src_pipe_index = 11,
+ .dst_phy_addr = A2_BAM_PHY_BASE,
+ .dst_pipe_index = 0,
+ .data_fifo_base_offset = 0xf00,
+ .data_fifo_size = 0x400,
+ .desc_fifo_base_offset = 0x1300,
+ .desc_fifo_size = 0x300,
+ },
+ [0][PEER_PERIPHERAL_TO_USB] = {
+ .src_phy_addr = A2_BAM_PHY_BASE,
+ .src_pipe_index = 1,
+ .dst_phy_addr = USB_BAM_PHY_BASE,
+ .dst_pipe_index = 10,
+ .data_fifo_base_offset = 0xa00,
+ .data_fifo_size = 0x400,
+ .desc_fifo_base_offset = 0xe00,
+ .desc_fifo_size = 0x100,
+ },
+};
+
+static struct msm_usb_bam_platform_data msm_usb_bam_pdata = {
+ .connections = &msm_usb_bam_connections[0][0],
+ .usb_bam_phy_base = USB_BAM_PHY_BASE,
+ .usb_bam_phy_size = USB_BAM_PHY_SIZE,
+ .usb_bam_num_pipes = 32,
+};
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PHY_CONTROL,
@@ -781,6 +814,7 @@
&msm_device_otg,
&msm_device_gadget_peripheral,
&msm_device_hsusb_host,
+ &msm_device_usb_bam,
&android_usb_device,
&msm9615_device_uart_gsbi4,
&msm9615_device_ext_2p95v_vreg,
@@ -833,6 +867,7 @@
msm_device_otg.dev.platform_data = &msm_otg_pdata;
msm_otg_pdata.phy_init_seq = shelby_phy_init_seq;
+ msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
acpuclk_init(&acpuclk_9615_soc_data);
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 012eb85..63a86cb 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -99,6 +99,9 @@
},
};
+#define MSM_USB_BAM_BASE 0x12502000
+#define MSM_USB_BAM_SIZE 0x3DFFF
+
static struct resource resources_otg[] = {
{
.start = MSM9615_HSUSB_PHYS,
@@ -135,6 +138,28 @@
},
};
+static struct resource resources_usb_bam[] = {
+ {
+ .name = "usb_bam_addr",
+ .start = MSM_USB_BAM_BASE,
+ .end = MSM_USB_BAM_BASE + MSM_USB_BAM_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "usb_bam_irq",
+ .start = USB1_HS_BAM_IRQ,
+ .end = USB1_HS_BAM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_device_usb_bam = {
+ .name = "usb_bam",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_usb_bam),
+ .resource = resources_usb_bam,
+};
+
struct platform_device msm_device_gadget_peripheral = {
.name = "msm_hsusb",
.id = -1,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 2fac2ef..ffe22f8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -118,6 +118,7 @@
extern struct platform_device msm_slim_ctrl;
extern struct platform_device msm_device_sps;
+extern struct platform_device msm_device_usb_bam;
extern struct platform_device msm_device_sps_apq8064;
extern struct platform_device msm_device_bam_dmux;
extern struct platform_device msm_device_smd;
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
new file mode 100644
index 0000000..4caa71b
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _USB_BAM_H_
+#define _USB_BAM_H_
+
+/**
+ * Connect USB-to-Periperal SPS connection.
+ *
+ * This function returns the allocated pipes number.
+ *
+ * @idx - Connection index.
+ *
+ * @src_pipe_idx - allocated pipe index - USB as a
+ * source (output)
+ *
+ * @dst_pipe_idx - allocated pipe index - USB as a
+ * destination (output)
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+#ifdef CONFIG_USB_BAM
+int usb_bam_connect(u8 idx, u8 *src_pipe_idx, u8 *dst_pipe_idx);
+#else
+int usb_bam_connect(u8 idx, u8 *src_pipe_idx, u8 *dst_pipe_idx)
+{
+ return -ENODEV;
+}
+#endif
+#endif /* _USB_BAM_H_ */
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 26441cd..23efb00 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -23,6 +23,14 @@
2. Peripheral-to-Memory.
3. Memory-to-Memory.
+config USB_BAM
+ boolean "USB BAM Driver"
+ depends on SPS && USB_GADGET
+ help
+ Enabling this option adds USB BAM Driver.
+ USB BAM driver was added to supports SPS Peripheral-to-Peripheral
+ transfers between the USB and other peripheral.
+
config SPS_SUPPORT_BAMDMA
bool "SPS support BAM DMA"
depends on SPS
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index f6f212e..92eb492 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -2,4 +2,5 @@
# Makefile for the MSM specific device drivers.
#
obj-$(CONFIG_MSM_SSBI) += ssbi.o
+obj-$(CONFIG_USB_BAM) += usb_bam.o
obj-$(CONFIG_SPS) += sps/
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
new file mode 100644
index 0000000..b34c35e
--- /dev/null
+++ b/drivers/platform/msm/usb_bam.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/usb/msm_hsusb.h>
+#include <mach/usb_bam.h>
+#include <mach/sps.h>
+
+#define USB_SUMMING_THRESHOLD 512
+#define CONNECTIONS_NUM 4
+
+static struct sps_bam_props usb_props;
+static struct sps_pipe *sps_pipes[CONNECTIONS_NUM][2];
+static struct sps_connect sps_connections[CONNECTIONS_NUM][2];
+static struct sps_mem_buffer data_mem_buf[CONNECTIONS_NUM][2];
+static struct sps_mem_buffer desc_mem_buf[CONNECTIONS_NUM][2];
+static struct platform_device *usb_bam_pdev;
+
+struct usb_bam_connect_info {
+ u8 idx;
+ u8 *src_pipe;
+ u8 *dst_pipe;
+ bool enabled;
+};
+
+static struct usb_bam_connect_info usb_bam_connections[CONNECTIONS_NUM];
+
+static int connect_pipe(u8 connection_idx, enum usb_bam_pipe_dir pipe_dir,
+ u8 *usb_pipe_idx)
+{
+ int ret;
+ struct sps_pipe *pipe = sps_pipes[connection_idx][pipe_dir];
+ struct sps_connect *connection =
+ &sps_connections[connection_idx][pipe_dir];
+ struct msm_usb_bam_platform_data *pdata =
+ (struct msm_usb_bam_platform_data *)
+ (usb_bam_pdev->dev.platform_data);
+ struct usb_bam_pipe_connect *pipe_connection =
+ (struct usb_bam_pipe_connect *)(pdata->connections +
+ (2*connection_idx+pipe_dir));
+
+ pipe = sps_alloc_endpoint();
+ if (pipe == NULL) {
+ pr_err("%s: sps_alloc_endpoint failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = sps_get_config(pipe, connection);
+ if (ret) {
+ pr_err("%s: tx get config failed %d\n", __func__, ret);
+ goto get_config_failed;
+ }
+
+ ret = sps_phy2h(pipe_connection->src_phy_addr, &(connection->source));
+ if (ret) {
+ pr_err("%s: sps_phy2h failed (src BAM) %d\n", __func__, ret);
+ goto get_config_failed;
+ }
+
+ connection->src_pipe_index = pipe_connection->src_pipe_index;
+ ret = sps_phy2h(pipe_connection->dst_phy_addr,
+ &(connection->destination));
+ if (ret) {
+ pr_err("%s: sps_phy2h failed (dst BAM) %d\n", __func__, ret);
+ goto get_config_failed;
+ }
+ connection->dest_pipe_index = pipe_connection->dst_pipe_index;
+
+ if (pipe_dir == USB_TO_PEER_PERIPHERAL) {
+ connection->mode = SPS_MODE_SRC;
+ *usb_pipe_idx = connection->src_pipe_index;
+ } else {
+ connection->mode = SPS_MODE_DEST;
+ *usb_pipe_idx = connection->dest_pipe_index;
+ }
+
+ ret = sps_setup_bam2bam_fifo(
+ &data_mem_buf[connection_idx][pipe_dir],
+ pipe_connection->data_fifo_base_offset,
+ pipe_connection->data_fifo_size, 1);
+ if (ret) {
+ pr_err("%s: data fifo setup failure %d\n", __func__, ret);
+ goto fifo_setup_error;
+ }
+ connection->data = data_mem_buf[connection_idx][pipe_dir];
+
+ ret = sps_setup_bam2bam_fifo(
+ &desc_mem_buf[connection_idx][pipe_dir],
+ pipe_connection->desc_fifo_base_offset,
+ pipe_connection->desc_fifo_size, 1);
+ if (ret) {
+ pr_err("%s: desc. fifo setup failure %d\n", __func__, ret);
+ goto fifo_setup_error;
+ }
+ connection->desc = desc_mem_buf[connection_idx][pipe_dir];
+ connection->event_thresh = 512;
+
+ ret = sps_connect(pipe, connection);
+ if (ret < 0) {
+ pr_err("%s: tx connect error %d\n", __func__, ret);
+ goto error;
+ }
+ return 0;
+
+error:
+ sps_disconnect(pipe);
+fifo_setup_error:
+get_config_failed:
+ sps_free_endpoint(pipe);
+ return ret;
+}
+
+int usb_bam_connect(u8 idx, u8 *src_pipe_idx, u8 *dst_pipe_idx)
+{
+ struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
+ int ret;
+
+ if (idx >= CONNECTIONS_NUM) {
+ pr_err("%s: Invalid connection index\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (connection->enabled) {
+ pr_info("%s: connection %d was already established\n",
+ __func__, idx);
+ return 0;
+ }
+ connection->src_pipe = src_pipe_idx;
+ connection->dst_pipe = dst_pipe_idx;
+ connection->idx = idx;
+
+ /* open USB -> Peripheral pipe */
+ ret = connect_pipe(connection->idx, USB_TO_PEER_PERIPHERAL,
+ connection->src_pipe);
+ if (ret) {
+ pr_err("%s: src pipe connection failure\n", __func__);
+ return ret;
+ }
+ /* open Peripheral -> USB pipe */
+ ret = connect_pipe(connection->idx, PEER_PERIPHERAL_TO_USB,
+ connection->dst_pipe);
+ if (ret) {
+ pr_err("%s: dst pipe connection failure\n", __func__);
+ return ret;
+ }
+ connection->enabled = 1;
+
+ return 0;
+}
+static int usb_bam_init(void)
+{
+ u32 h_usb;
+ int ret;
+ void *usb_virt_addr;
+ struct msm_usb_bam_platform_data *pdata =
+ (struct msm_usb_bam_platform_data *)
+ (usb_bam_pdev->dev.platform_data);
+
+ usb_virt_addr = ioremap_nocache(
+ pdata->usb_bam_phy_base,
+ pdata->usb_bam_phy_size);
+ if (!usb_virt_addr) {
+ pr_err("%s: ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+ usb_props.phys_addr = pdata->usb_bam_phy_base;
+ usb_props.virt_addr = usb_virt_addr;
+ usb_props.virt_size = pdata->usb_bam_phy_size;
+ usb_props.irq = USB1_HS_BAM_IRQ;
+ usb_props.num_pipes = pdata->usb_bam_num_pipes;
+ usb_props.summing_threshold = USB_SUMMING_THRESHOLD;
+ ret = sps_register_bam_device(&usb_props, &h_usb);
+ if (ret < 0) {
+ pr_err("%s: register bam error %d\n", __func__, ret);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int usb_bam_probe(struct platform_device *pdev)
+{
+ int ret, i;
+
+ dev_dbg(&pdev->dev, "usb_bam_probe\n");
+
+ for (i = 0; i < CONNECTIONS_NUM; i++)
+ usb_bam_connections[i].enabled = 0;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "missing platform_data\n");
+ return -ENODEV;
+ }
+ usb_bam_pdev = pdev;
+
+ ret = usb_bam_init();
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get platform resource mem\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver usb_bam_driver = {
+ .probe = usb_bam_probe,
+ .driver = { .name = "usb_bam", },
+};
+
+static int __init init(void)
+{
+ return platform_driver_register(&usb_bam_driver);
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+ platform_driver_unregister(&usb_bam_driver);
+}
+module_exit(cleanup);
+
+MODULE_DESCRIPTION("MSM USB BAM DRIVER");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 68fc67c..eb2c543 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -132,6 +132,19 @@
};
/**
+ * SPS Pipes direction.
+ *
+ * USB_TO_PEER_PERIPHERAL USB (as Producer) to other
+ * peer peripheral.
+ * PEER_PERIPHERAL_TO_USB Other Peripheral to
+ * USB (as consumer).
+ */
+enum usb_bam_pipe_dir {
+ USB_TO_PEER_PERIPHERAL,
+ PEER_PERIPHERAL_TO_USB,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -258,4 +271,21 @@
unsigned hub_reset;
};
+struct usb_bam_pipe_connect {
+ u32 src_phy_addr;
+ int src_pipe_index;
+ u32 dst_phy_addr;
+ int dst_pipe_index;
+ u32 data_fifo_base_offset;
+ u32 data_fifo_size;
+ u32 desc_fifo_base_offset;
+ u32 desc_fifo_size;
+};
+
+struct msm_usb_bam_platform_data {
+ struct usb_bam_pipe_connect *connections;
+ unsigned long usb_bam_phy_base;
+ unsigned long usb_bam_phy_size;
+ int usb_bam_num_pipes;
+};
#endif