misc: Remove spear13xx pcie gadget driver
This driver has been marked broken since 2013, see commit 98097858cc
("misc: mark spear13xx-pcie-gadget as broken"). Let's remove this file
now that it's been more than 5 years of existing in a broken state.
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/5d41a2b7.1c69fb81.c8d56.edb6@mx.google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
52eb6d31a1
commit
f51cf9e23b
@@ -375,15 +375,6 @@ config DS1682
|
|||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called ds1682.
|
will be called ds1682.
|
||||||
|
|
||||||
config SPEAR13XX_PCIE_GADGET
|
|
||||||
bool "PCIe gadget support for SPEAr13XX platform"
|
|
||||||
depends on ARCH_SPEAR13XX && BROKEN
|
|
||||||
help
|
|
||||||
This option enables gadget support for PCIe controller. If
|
|
||||||
board file defines any controller as PCIe endpoint then a sysfs
|
|
||||||
entry will be created for that controller. User can use these
|
|
||||||
sysfs node to configure PCIe EP as per his requirements.
|
|
||||||
|
|
||||||
config VMWARE_BALLOON
|
config VMWARE_BALLOON
|
||||||
tristate "VMware Balloon Driver"
|
tristate "VMware Balloon Driver"
|
||||||
depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST
|
depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST
|
||||||
|
@@ -37,7 +37,6 @@ obj-$(CONFIG_C2PORT) += c2port/
|
|||||||
obj-$(CONFIG_HMC6352) += hmc6352.o
|
obj-$(CONFIG_HMC6352) += hmc6352.o
|
||||||
obj-y += eeprom/
|
obj-y += eeprom/
|
||||||
obj-y += cb710/
|
obj-y += cb710/
|
||||||
obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o
|
|
||||||
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
|
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
|
||||||
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
|
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
|
||||||
obj-y += ti-st/
|
obj-y += ti-st/
|
||||||
|
@@ -1,797 +0,0 @@
|
|||||||
/*
|
|
||||||
* drivers/misc/spear13xx_pcie_gadget.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 ST Microelectronics
|
|
||||||
* Pratyush Anand<pratyush.anand@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is licensed under the terms of the GNU General Public
|
|
||||||
* License version 2. This program is licensed "as is" without any
|
|
||||||
* warranty of any kind, whether express or implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/irq.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/pci_regs.h>
|
|
||||||
#include <linux/configfs.h>
|
|
||||||
#include <mach/pcie.h>
|
|
||||||
#include <mach/misc_regs.h>
|
|
||||||
|
|
||||||
#define IN0_MEM_SIZE (200 * 1024 * 1024 - 1)
|
|
||||||
/* In current implementation address translation is done using IN0 only.
|
|
||||||
* So IN1 start address and IN0 end address has been kept same
|
|
||||||
*/
|
|
||||||
#define IN1_MEM_SIZE (0 * 1024 * 1024 - 1)
|
|
||||||
#define IN_IO_SIZE (20 * 1024 * 1024 - 1)
|
|
||||||
#define IN_CFG0_SIZE (12 * 1024 * 1024 - 1)
|
|
||||||
#define IN_CFG1_SIZE (12 * 1024 * 1024 - 1)
|
|
||||||
#define IN_MSG_SIZE (12 * 1024 * 1024 - 1)
|
|
||||||
/* Keep default BAR size as 4K*/
|
|
||||||
/* AORAM would be mapped by default*/
|
|
||||||
#define INBOUND_ADDR_MASK (SPEAR13XX_SYSRAM1_SIZE - 1)
|
|
||||||
|
|
||||||
#define INT_TYPE_NO_INT 0
|
|
||||||
#define INT_TYPE_INTX 1
|
|
||||||
#define INT_TYPE_MSI 2
|
|
||||||
struct spear_pcie_gadget_config {
|
|
||||||
void __iomem *base;
|
|
||||||
void __iomem *va_app_base;
|
|
||||||
void __iomem *va_dbi_base;
|
|
||||||
char int_type[10];
|
|
||||||
ulong requested_msi;
|
|
||||||
ulong configured_msi;
|
|
||||||
ulong bar0_size;
|
|
||||||
ulong bar0_rw_offset;
|
|
||||||
void __iomem *va_bar0_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pcie_gadget_target {
|
|
||||||
struct configfs_subsystem subsys;
|
|
||||||
struct spear_pcie_gadget_config config;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pcie_gadget_target_attr {
|
|
||||||
struct configfs_attribute attr;
|
|
||||||
ssize_t (*show)(struct spear_pcie_gadget_config *config,
|
|
||||||
char *buf);
|
|
||||||
ssize_t (*store)(struct spear_pcie_gadget_config *config,
|
|
||||||
const char *buf,
|
|
||||||
size_t count);
|
|
||||||
};
|
|
||||||
|
|
||||||
static void enable_dbi_access(struct pcie_app_reg __iomem *app_reg)
|
|
||||||
{
|
|
||||||
/* Enable DBI access */
|
|
||||||
writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
|
|
||||||
&app_reg->slv_armisc);
|
|
||||||
writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
|
|
||||||
&app_reg->slv_awmisc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disable_dbi_access(struct pcie_app_reg __iomem *app_reg)
|
|
||||||
{
|
|
||||||
/* disable DBI access */
|
|
||||||
writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
|
|
||||||
&app_reg->slv_armisc);
|
|
||||||
writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
|
|
||||||
&app_reg->slv_awmisc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
|
|
||||||
int where, int size, u32 *val)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
|
|
||||||
ulong va_address;
|
|
||||||
|
|
||||||
/* Enable DBI access */
|
|
||||||
enable_dbi_access(app_reg);
|
|
||||||
|
|
||||||
va_address = (ulong)config->va_dbi_base + (where & ~0x3);
|
|
||||||
|
|
||||||
*val = readl(va_address);
|
|
||||||
|
|
||||||
if (size == 1)
|
|
||||||
*val = (*val >> (8 * (where & 3))) & 0xff;
|
|
||||||
else if (size == 2)
|
|
||||||
*val = (*val >> (8 * (where & 3))) & 0xffff;
|
|
||||||
|
|
||||||
/* Disable DBI access */
|
|
||||||
disable_dbi_access(app_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
|
|
||||||
int where, int size, u32 val)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
|
|
||||||
ulong va_address;
|
|
||||||
|
|
||||||
/* Enable DBI access */
|
|
||||||
enable_dbi_access(app_reg);
|
|
||||||
|
|
||||||
va_address = (ulong)config->va_dbi_base + (where & ~0x3);
|
|
||||||
|
|
||||||
if (size == 4)
|
|
||||||
writel(val, va_address);
|
|
||||||
else if (size == 2)
|
|
||||||
writew(val, va_address + (where & 2));
|
|
||||||
else if (size == 1)
|
|
||||||
writeb(val, va_address + (where & 3));
|
|
||||||
|
|
||||||
/* Disable DBI access */
|
|
||||||
disable_dbi_access(app_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PCI_FIND_CAP_TTL 48
|
|
||||||
|
|
||||||
static int pci_find_own_next_cap_ttl(struct spear_pcie_gadget_config *config,
|
|
||||||
u32 pos, int cap, int *ttl)
|
|
||||||
{
|
|
||||||
u32 id;
|
|
||||||
|
|
||||||
while ((*ttl)--) {
|
|
||||||
spear_dbi_read_reg(config, pos, 1, &pos);
|
|
||||||
if (pos < 0x40)
|
|
||||||
break;
|
|
||||||
pos &= ~3;
|
|
||||||
spear_dbi_read_reg(config, pos + PCI_CAP_LIST_ID, 1, &id);
|
|
||||||
if (id == 0xff)
|
|
||||||
break;
|
|
||||||
if (id == cap)
|
|
||||||
return pos;
|
|
||||||
pos += PCI_CAP_LIST_NEXT;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_find_own_next_cap(struct spear_pcie_gadget_config *config,
|
|
||||||
u32 pos, int cap)
|
|
||||||
{
|
|
||||||
int ttl = PCI_FIND_CAP_TTL;
|
|
||||||
|
|
||||||
return pci_find_own_next_cap_ttl(config, pos, cap, &ttl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pci_find_own_cap_start(struct spear_pcie_gadget_config *config,
|
|
||||||
u8 hdr_type)
|
|
||||||
{
|
|
||||||
u32 status;
|
|
||||||
|
|
||||||
spear_dbi_read_reg(config, PCI_STATUS, 2, &status);
|
|
||||||
if (!(status & PCI_STATUS_CAP_LIST))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (hdr_type) {
|
|
||||||
case PCI_HEADER_TYPE_NORMAL:
|
|
||||||
case PCI_HEADER_TYPE_BRIDGE:
|
|
||||||
return PCI_CAPABILITY_LIST;
|
|
||||||
case PCI_HEADER_TYPE_CARDBUS:
|
|
||||||
return PCI_CB_CAPABILITY_LIST;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tell if a device supports a given PCI capability.
|
|
||||||
* Returns the address of the requested capability structure within the
|
|
||||||
* device's PCI configuration space or 0 in case the device does not
|
|
||||||
* support it. Possible values for @cap:
|
|
||||||
*
|
|
||||||
* %PCI_CAP_ID_PM Power Management
|
|
||||||
* %PCI_CAP_ID_AGP Accelerated Graphics Port
|
|
||||||
* %PCI_CAP_ID_VPD Vital Product Data
|
|
||||||
* %PCI_CAP_ID_SLOTID Slot Identification
|
|
||||||
* %PCI_CAP_ID_MSI Message Signalled Interrupts
|
|
||||||
* %PCI_CAP_ID_CHSWP CompactPCI HotSwap
|
|
||||||
* %PCI_CAP_ID_PCIX PCI-X
|
|
||||||
* %PCI_CAP_ID_EXP PCI Express
|
|
||||||
*/
|
|
||||||
static int pci_find_own_capability(struct spear_pcie_gadget_config *config,
|
|
||||||
int cap)
|
|
||||||
{
|
|
||||||
u32 pos;
|
|
||||||
u32 hdr_type;
|
|
||||||
|
|
||||||
spear_dbi_read_reg(config, PCI_HEADER_TYPE, 1, &hdr_type);
|
|
||||||
|
|
||||||
pos = pci_find_own_cap_start(config, hdr_type);
|
|
||||||
if (pos)
|
|
||||||
pos = pci_find_own_next_cap(config, pos, cap);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* configfs interfaces show/store functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct pcie_gadget_target *to_target(struct config_item *item)
|
|
||||||
{
|
|
||||||
return item ?
|
|
||||||
container_of(to_configfs_subsystem(to_config_group(item)),
|
|
||||||
struct pcie_gadget_target, subsys) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_link_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
|
|
||||||
|
|
||||||
if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
|
|
||||||
return sprintf(buf, "UP");
|
|
||||||
else
|
|
||||||
return sprintf(buf, "DOWN");
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_link_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
|
|
||||||
|
|
||||||
if (sysfs_streq(buf, "UP"))
|
|
||||||
writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
|
|
||||||
&app_reg->app_ctrl_0);
|
|
||||||
else if (sysfs_streq(buf, "DOWN"))
|
|
||||||
writel(readl(&app_reg->app_ctrl_0)
|
|
||||||
& ~(1 << APP_LTSSM_ENABLE_ID),
|
|
||||||
&app_reg->app_ctrl_0);
|
|
||||||
else
|
|
||||||
return -EINVAL;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_int_type_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
return sprintf(buf, "%s", to_target(item)->int_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_int_type_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
u32 cap, vec, flags;
|
|
||||||
ulong vector;
|
|
||||||
|
|
||||||
if (sysfs_streq(buf, "INTA"))
|
|
||||||
spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
|
|
||||||
|
|
||||||
else if (sysfs_streq(buf, "MSI")) {
|
|
||||||
vector = config->requested_msi;
|
|
||||||
vec = 0;
|
|
||||||
while (vector > 1) {
|
|
||||||
vector /= 2;
|
|
||||||
vec++;
|
|
||||||
}
|
|
||||||
spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
|
|
||||||
cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
|
|
||||||
spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
|
|
||||||
flags &= ~PCI_MSI_FLAGS_QMASK;
|
|
||||||
flags |= vec << 1;
|
|
||||||
spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
|
|
||||||
} else
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
strcpy(config->int_type, buf);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_no_of_msi_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
|
|
||||||
u32 cap, vec, flags;
|
|
||||||
ulong vector;
|
|
||||||
|
|
||||||
if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
|
|
||||||
!= (1 << CFG_MSI_EN_ID))
|
|
||||||
vector = 0;
|
|
||||||
else {
|
|
||||||
cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
|
|
||||||
spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
|
|
||||||
flags &= ~PCI_MSI_FLAGS_QSIZE;
|
|
||||||
vec = flags >> 4;
|
|
||||||
vector = 1;
|
|
||||||
while (vec--)
|
|
||||||
vector *= 2;
|
|
||||||
}
|
|
||||||
config->configured_msi = vector;
|
|
||||||
|
|
||||||
return sprintf(buf, "%lu", vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_no_of_msi_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &to_target(item)->requested_msi);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (config->requested_msi > 32)
|
|
||||||
config->requested_msi = 32;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_inta_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
|
|
||||||
ulong en;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &en);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (en)
|
|
||||||
writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
|
|
||||||
&app_reg->app_ctrl_0);
|
|
||||||
else
|
|
||||||
writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
|
|
||||||
&app_reg->app_ctrl_0);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_send_msi_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
|
|
||||||
ulong vector;
|
|
||||||
u32 ven_msi;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &vector);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!config->configured_msi)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (vector >= config->configured_msi)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ven_msi = readl(&app_reg->ven_msi_1);
|
|
||||||
ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
|
|
||||||
ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
|
|
||||||
ven_msi &= ~VEN_MSI_TC_MASK;
|
|
||||||
ven_msi |= 0 << VEN_MSI_TC_ID;
|
|
||||||
ven_msi &= ~VEN_MSI_VECTOR_MASK;
|
|
||||||
ven_msi |= vector << VEN_MSI_VECTOR_ID;
|
|
||||||
|
|
||||||
/* generating interrupt for msi vector */
|
|
||||||
ven_msi |= VEN_MSI_REQ_EN;
|
|
||||||
writel(ven_msi, &app_reg->ven_msi_1);
|
|
||||||
udelay(1);
|
|
||||||
ven_msi &= ~VEN_MSI_REQ_EN;
|
|
||||||
writel(ven_msi, &app_reg->ven_msi_1);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_vendor_id_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
u32 id;
|
|
||||||
|
|
||||||
spear_dbi_read_reg(to_target(item), PCI_VENDOR_ID, 2, &id);
|
|
||||||
|
|
||||||
return sprintf(buf, "%x", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_vendor_id_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
ulong id;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &id);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
spear_dbi_write_reg(to_target(item), PCI_VENDOR_ID, 2, id);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_device_id_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
u32 id;
|
|
||||||
|
|
||||||
spear_dbi_read_reg(to_target(item), PCI_DEVICE_ID, 2, &id);
|
|
||||||
|
|
||||||
return sprintf(buf, "%x", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_device_id_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
ulong id;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &id);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
spear_dbi_write_reg(to_target(item), PCI_DEVICE_ID, 2, id);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_size_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
return sprintf(buf, "%lx", to_target(item)->bar0_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_size_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
ulong size;
|
|
||||||
u32 pos, pos1;
|
|
||||||
u32 no_of_bit = 0;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &size);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* min bar size is 256 */
|
|
||||||
if (size <= 0x100)
|
|
||||||
size = 0x100;
|
|
||||||
/* max bar size is 1MB*/
|
|
||||||
else if (size >= 0x100000)
|
|
||||||
size = 0x100000;
|
|
||||||
else {
|
|
||||||
pos = 0;
|
|
||||||
pos1 = 0;
|
|
||||||
while (pos < 21) {
|
|
||||||
pos = find_next_bit((ulong *)&size, 21, pos);
|
|
||||||
if (pos != 21)
|
|
||||||
pos1 = pos + 1;
|
|
||||||
pos++;
|
|
||||||
no_of_bit++;
|
|
||||||
}
|
|
||||||
if (no_of_bit == 2)
|
|
||||||
pos1--;
|
|
||||||
|
|
||||||
size = 1 << pos1;
|
|
||||||
}
|
|
||||||
config->bar0_size = size;
|
|
||||||
spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_address_show(struct config_item *item,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
|
|
||||||
|
|
||||||
u32 address = readl(&app_reg->pim0_mem_addr_start);
|
|
||||||
|
|
||||||
return sprintf(buf, "%x", address);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_address_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
|
|
||||||
ulong address;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &address);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
address &= ~(config->bar0_size - 1);
|
|
||||||
if (config->va_bar0_address)
|
|
||||||
iounmap(config->va_bar0_address);
|
|
||||||
config->va_bar0_address = ioremap(address, config->bar0_size);
|
|
||||||
if (!config->va_bar0_address)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
writel(address, &app_reg->pim0_mem_addr_start);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_rw_offset_show(struct config_item *item,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
return sprintf(buf, "%lx", to_target(item)->bar0_rw_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_rw_offset_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
ulong offset;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &offset);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (offset % 4)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
to_target(item)->bar0_rw_offset = offset;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_data_show(struct config_item *item, char *buf)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
ulong data;
|
|
||||||
|
|
||||||
if (!config->va_bar0_address)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
data = readl((ulong)config->va_bar0_address + config->bar0_rw_offset);
|
|
||||||
|
|
||||||
return sprintf(buf, "%lx", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pcie_gadget_bar0_data_store(struct config_item *item,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
struct spear_pcie_gadget_config *config = to_target(item)
|
|
||||||
ulong data;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = kstrtoul(buf, 0, &data);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (!config->va_bar0_address)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
writel(data, (ulong)config->va_bar0_address + config->bar0_rw_offset);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, link);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, int_type);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, no_of_msi);
|
|
||||||
CONFIGFS_ATTR_WO(pcie_gadget_, inta);
|
|
||||||
CONFIGFS_ATTR_WO(pcie_gadget_, send_msi);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, vendor_id);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, device_id);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, bar0_size);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, bar0_address);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, bar0_rw_offset);
|
|
||||||
CONFIGFS_ATTR(pcie_gadget_, bar0_data);
|
|
||||||
|
|
||||||
static struct configfs_attribute *pcie_gadget_target_attrs[] = {
|
|
||||||
&pcie_gadget_attr_link,
|
|
||||||
&pcie_gadget_attr_int_type,
|
|
||||||
&pcie_gadget_attr_no_of_msi,
|
|
||||||
&pcie_gadget_attr_inta,
|
|
||||||
&pcie_gadget_attr_send_msi,
|
|
||||||
&pcie_gadget_attr_vendor_id,
|
|
||||||
&pcie_gadget_attr_device_id,
|
|
||||||
&pcie_gadget_attr_bar0_size,
|
|
||||||
&pcie_gadget_attr_bar0_address,
|
|
||||||
&pcie_gadget_attr_bar0_rw_offset,
|
|
||||||
&pcie_gadget_attr_bar0_data,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct config_item_type pcie_gadget_target_type = {
|
|
||||||
.ct_attrs = pcie_gadget_target_attrs,
|
|
||||||
.ct_owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
|
|
||||||
{
|
|
||||||
struct pcie_app_reg __iomem *app_reg = config->va_app_base;
|
|
||||||
|
|
||||||
/*setup registers for outbound translation */
|
|
||||||
|
|
||||||
writel(config->base, &app_reg->in0_mem_addr_start);
|
|
||||||
writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE,
|
|
||||||
&app_reg->in0_mem_addr_limit);
|
|
||||||
writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start);
|
|
||||||
writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE,
|
|
||||||
&app_reg->in1_mem_addr_limit);
|
|
||||||
writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start);
|
|
||||||
writel(app_reg->in_io_addr_start + IN_IO_SIZE,
|
|
||||||
&app_reg->in_io_addr_limit);
|
|
||||||
writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start);
|
|
||||||
writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE,
|
|
||||||
&app_reg->in_cfg0_addr_limit);
|
|
||||||
writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start);
|
|
||||||
writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE,
|
|
||||||
&app_reg->in_cfg1_addr_limit);
|
|
||||||
writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start);
|
|
||||||
writel(app_reg->in_msg_addr_start + IN_MSG_SIZE,
|
|
||||||
&app_reg->in_msg_addr_limit);
|
|
||||||
|
|
||||||
writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start);
|
|
||||||
writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start);
|
|
||||||
writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start);
|
|
||||||
|
|
||||||
/*setup registers for inbound translation */
|
|
||||||
|
|
||||||
/* Keep AORAM mapped at BAR0 as default */
|
|
||||||
config->bar0_size = INBOUND_ADDR_MASK + 1;
|
|
||||||
spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK);
|
|
||||||
spear_dbi_write_reg(config, PCI_BASE_ADDRESS_0, 4, 0xC);
|
|
||||||
config->va_bar0_address = ioremap(SPEAR13XX_SYSRAM1_BASE,
|
|
||||||
config->bar0_size);
|
|
||||||
|
|
||||||
writel(SPEAR13XX_SYSRAM1_BASE, &app_reg->pim0_mem_addr_start);
|
|
||||||
writel(0, &app_reg->pim1_mem_addr_start);
|
|
||||||
writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit);
|
|
||||||
|
|
||||||
writel(0x0, &app_reg->pim_io_addr_start);
|
|
||||||
writel(0x0, &app_reg->pim_io_addr_start);
|
|
||||||
writel(0x0, &app_reg->pim_rom_addr_start);
|
|
||||||
|
|
||||||
writel(DEVICE_TYPE_EP | (1 << MISCTRL_EN_ID)
|
|
||||||
| ((u32)1 << REG_TRANSLATION_ENABLE),
|
|
||||||
&app_reg->app_ctrl_0);
|
|
||||||
/* disable all rx interrupts */
|
|
||||||
writel(0, &app_reg->int_mask);
|
|
||||||
|
|
||||||
/* Select INTA as default*/
|
|
||||||
spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spear_pcie_gadget_probe(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct resource *res0, *res1;
|
|
||||||
unsigned int status = 0;
|
|
||||||
int irq;
|
|
||||||
struct clk *clk;
|
|
||||||
static struct pcie_gadget_target *target;
|
|
||||||
struct spear_pcie_gadget_config *config;
|
|
||||||
struct config_item *cg_item;
|
|
||||||
struct configfs_subsystem *subsys;
|
|
||||||
|
|
||||||
target = devm_kzalloc(&pdev->dev, sizeof(*target), GFP_KERNEL);
|
|
||||||
if (!target) {
|
|
||||||
dev_err(&pdev->dev, "out of memory\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
cg_item = &target->subsys.su_group.cg_item;
|
|
||||||
sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id);
|
|
||||||
cg_item->ci_type = &pcie_gadget_target_type;
|
|
||||||
config = &target->config;
|
|
||||||
|
|
||||||
/* get resource for application registers*/
|
|
||||||
res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
config->va_app_base = devm_ioremap_resource(&pdev->dev, res0);
|
|
||||||
if (IS_ERR(config->va_app_base)) {
|
|
||||||
dev_err(&pdev->dev, "ioremap fail\n");
|
|
||||||
return PTR_ERR(config->va_app_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get resource for dbi registers*/
|
|
||||||
res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
||||||
config->base = (void __iomem *)res1->start;
|
|
||||||
|
|
||||||
config->va_dbi_base = devm_ioremap_resource(&pdev->dev, res1);
|
|
||||||
if (IS_ERR(config->va_dbi_base)) {
|
|
||||||
dev_err(&pdev->dev, "ioremap fail\n");
|
|
||||||
return PTR_ERR(config->va_dbi_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
platform_set_drvdata(pdev, target);
|
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
|
||||||
if (irq < 0) {
|
|
||||||
dev_err(&pdev->dev, "no update irq?\n");
|
|
||||||
return irq;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = devm_request_irq(&pdev->dev, irq, spear_pcie_gadget_irq,
|
|
||||||
0, pdev->name, NULL);
|
|
||||||
if (status) {
|
|
||||||
dev_err(&pdev->dev,
|
|
||||||
"pcie gadget interrupt IRQ%d already claimed\n", irq);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register configfs hooks */
|
|
||||||
subsys = &target->subsys;
|
|
||||||
config_group_init(&subsys->su_group);
|
|
||||||
mutex_init(&subsys->su_mutex);
|
|
||||||
status = configfs_register_subsystem(subsys);
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* init basic pcie application registers
|
|
||||||
* do not enable clock if it is PCIE0.Ideally , all controller should
|
|
||||||
* have been independent from others with respect to clock. But PCIE1
|
|
||||||
* and 2 depends on PCIE0.So PCIE0 clk is provided during board init.
|
|
||||||
*/
|
|
||||||
if (pdev->id == 1) {
|
|
||||||
/*
|
|
||||||
* Ideally CFG Clock should have been also enabled here. But
|
|
||||||
* it is done currently during board init routne
|
|
||||||
*/
|
|
||||||
clk = clk_get_sys("pcie1", NULL);
|
|
||||||
if (IS_ERR(clk)) {
|
|
||||||
pr_err("%s:couldn't get clk for pcie1\n", __func__);
|
|
||||||
return PTR_ERR(clk);
|
|
||||||
}
|
|
||||||
status = clk_enable(clk);
|
|
||||||
if (status) {
|
|
||||||
pr_err("%s:couldn't enable clk for pcie1\n", __func__);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
} else if (pdev->id == 2) {
|
|
||||||
/*
|
|
||||||
* Ideally CFG Clock should have been also enabled here. But
|
|
||||||
* it is done currently during board init routne
|
|
||||||
*/
|
|
||||||
clk = clk_get_sys("pcie2", NULL);
|
|
||||||
if (IS_ERR(clk)) {
|
|
||||||
pr_err("%s:couldn't get clk for pcie2\n", __func__);
|
|
||||||
return PTR_ERR(clk);
|
|
||||||
}
|
|
||||||
status = clk_enable(clk);
|
|
||||||
if (status) {
|
|
||||||
pr_err("%s:couldn't enable clk for pcie2\n", __func__);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spear13xx_pcie_device_init(config);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spear_pcie_gadget_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
static struct pcie_gadget_target *target;
|
|
||||||
|
|
||||||
target = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
configfs_unregister_subsystem(&target->subsys);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spear_pcie_gadget_shutdown(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver spear_pcie_gadget_driver = {
|
|
||||||
.probe = spear_pcie_gadget_probe,
|
|
||||||
.remove = spear_pcie_gadget_remove,
|
|
||||||
.shutdown = spear_pcie_gadget_shutdown,
|
|
||||||
.driver = {
|
|
||||||
.name = "pcie-gadget-spear",
|
|
||||||
.bus = &platform_bus_type
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module_platform_driver(spear_pcie_gadget_driver);
|
|
||||||
|
|
||||||
MODULE_ALIAS("platform:pcie-gadget-spear");
|
|
||||||
MODULE_AUTHOR("Pratyush Anand");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
Reference in New Issue
Block a user