From c7827e45a3659869ec7fd6f74b0717a751474f17 Mon Sep 17 00:00:00 2001 From: Ofir Cohen Date: Tue, 13 Dec 2011 20:10:01 +0200 Subject: [PATCH 1/3] usb: gadget: SPS BAM-to-BAM - USB BAM driver USB BAM driver to support BAM-to-BAM USB<->Peripheral transactions. Change-Id: Ib49a41f5dcdccb6f6bff2492fa64ead40f18b870 Signed-off-by: Ofir Cohen --- arch/arm/mach-msm/include/mach/usb_bam.h | 40 ++++ drivers/platform/msm/Kconfig | 8 + drivers/platform/msm/Makefile | 1 + drivers/platform/msm/usb_bam.c | 238 +++++++++++++++++++++++ include/linux/usb/msm_hsusb.h | 30 +++ 5 files changed, 317 insertions(+) create mode 100644 arch/arm/mach-msm/include/mach/usb_bam.h create mode 100644 drivers/platform/msm/usb_bam.c 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 00000000000..4caa71bb3de --- /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 26441cd45d4..23efb008c33 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -23,6 +23,14 @@ config SPS 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 f6f212ec221..92eb492591a 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 00000000000..b34c35ed414 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 68fc67c4ef6..eb2c5437b2e 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -131,6 +131,19 @@ enum usb_chg_type { USB_ACA_DOCK_CHARGER, }; +/** + * 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. @@ -258,4 +271,21 @@ struct msm_hsic_host_platform_data { 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 From 40a4e86b76cc8d45af2d1e02d36ed0e940fae681 Mon Sep 17 00:00:00 2001 From: Ofir Cohen Date: Thu, 8 Dec 2011 15:17:52 +0200 Subject: [PATCH 2/3] msm: board-9615: Add USB BAM driver Add USB BAM driver to 9615 to support SPS BAM-to-BAM Change-Id: Iac66d7682f12aa860d92a9c9e3ac0ffb0b9aa175 Signed-off-by: Ofir Cohen --- arch/arm/mach-msm/board-9615.c | 35 ++++++++++++++++++++++++++++++++ arch/arm/mach-msm/devices-9615.c | 25 +++++++++++++++++++++++ arch/arm/mach-msm/devices.h | 1 + 3 files changed, 61 insertions(+) diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c index 5efafae768e..be0e4e64a32 100644 --- a/arch/arm/mach-msm/board-9615.c +++ b/arch/arm/mach-msm/board-9615.c @@ -727,6 +727,39 @@ static int shelby_phy_init_seq[] = { 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 @@ static struct platform_device *common_devices[] = { &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 @@ static void __init msm9615_common_init(void) 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 012eb851ddd..63a86cbbf0e 100644 --- a/arch/arm/mach-msm/devices-9615.c +++ b/arch/arm/mach-msm/devices-9615.c @@ -99,6 +99,9 @@ struct platform_device msm9615_device_dmov = { }, }; +#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_hsusb[] = { }, }; +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 2fac2ef1554..ffe22f877fd 100644 --- a/arch/arm/mach-msm/devices.h +++ b/arch/arm/mach-msm/devices.h @@ -118,6 +118,7 @@ extern struct platform_device msm_gsbi12_qup_i2c_device; 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; From 0ea48c04865d34d7164b8b8c79541dccef2cd679 Mon Sep 17 00:00:00 2001 From: Ofir Cohen Date: Mon, 5 Dec 2011 16:38:52 +0200 Subject: [PATCH 3/3] defconfig: 9615: Enable USB BAM driver Enable USB BAM driver to support SPS BAM-to-BAM in 9615 Change-Id: Ief2357bbd4e2f9ddcea103829d3f95507bf1c404 Signed-off-by: Ofir Cohen --- arch/arm/configs/msm9615_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig index 003f9c16ae2..b5aa1b45547 100644 --- a/arch/arm/configs/msm9615_defconfig +++ b/arch/arm/configs/msm9615_defconfig @@ -188,6 +188,7 @@ CONFIG_RTC_DRV_PM8XXX=y 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