mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 14:41:39 +00:00
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:
parent
52eb6d31a1
commit
f51cf9e23b
@ -375,15 +375,6 @@ config DS1682
|
||||
This driver can also be built as a module. If so, the module
|
||||
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
|
||||
tristate "VMware Balloon Driver"
|
||||
depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST
|
||||
|
@ -37,7 +37,6 @@ obj-$(CONFIG_C2PORT) += c2port/
|
||||
obj-$(CONFIG_HMC6352) += hmc6352.o
|
||||
obj-y += eeprom/
|
||||
obj-y += cb710/
|
||||
obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o
|
||||
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
|
||||
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
|
||||
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");
|
Loading…
Reference in New Issue
Block a user