linux/drivers/misc/spear13xx_pcie_gadget.c
<<
>>
Prefs
   1/*
   2 * drivers/misc/spear13xx_pcie_gadget.c
   3 *
   4 * Copyright (C) 2010 ST Microelectronics
   5 * Pratyush Anand<pratyush.anand@st.com>
   6 *
   7 * This file is licensed under the terms of the GNU General Public
   8 * License version 2. This program is licensed "as is" without any
   9 * warranty of any kind, whether express or implied.
  10 */
  11
  12#include <linux/clk.h>
  13#include <linux/slab.h>
  14#include <linux/delay.h>
  15#include <linux/io.h>
  16#include <linux/interrupt.h>
  17#include <linux/irq.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/platform_device.h>
  21#include <linux/pci_regs.h>
  22#include <linux/configfs.h>
  23#include <mach/pcie.h>
  24#include <mach/misc_regs.h>
  25
  26#define IN0_MEM_SIZE    (200 * 1024 * 1024 - 1)
  27/* In current implementation address translation is done using IN0 only.
  28 * So IN1 start address and IN0 end address has been kept same
  29*/
  30#define IN1_MEM_SIZE    (0 * 1024 * 1024 - 1)
  31#define IN_IO_SIZE      (20 * 1024 * 1024 - 1)
  32#define IN_CFG0_SIZE    (12 * 1024 * 1024 - 1)
  33#define IN_CFG1_SIZE    (12 * 1024 * 1024 - 1)
  34#define IN_MSG_SIZE     (12 * 1024 * 1024 - 1)
  35/* Keep default BAR size as 4K*/
  36/* AORAM would be mapped by default*/
  37#define INBOUND_ADDR_MASK       (SPEAR13XX_SYSRAM1_SIZE - 1)
  38
  39#define INT_TYPE_NO_INT 0
  40#define INT_TYPE_INTX   1
  41#define INT_TYPE_MSI    2
  42struct spear_pcie_gadget_config {
  43        void __iomem *base;
  44        void __iomem *va_app_base;
  45        void __iomem *va_dbi_base;
  46        char int_type[10];
  47        ulong requested_msi;
  48        ulong configured_msi;
  49        ulong bar0_size;
  50        ulong bar0_rw_offset;
  51        void __iomem *va_bar0_address;
  52};
  53
  54struct pcie_gadget_target {
  55        struct configfs_subsystem subsys;
  56        struct spear_pcie_gadget_config config;
  57};
  58
  59struct pcie_gadget_target_attr {
  60        struct configfs_attribute       attr;
  61        ssize_t         (*show)(struct spear_pcie_gadget_config *config,
  62                                                char *buf);
  63        ssize_t         (*store)(struct spear_pcie_gadget_config *config,
  64                                                 const char *buf,
  65                                                 size_t count);
  66};
  67
  68static void enable_dbi_access(struct pcie_app_reg __iomem *app_reg)
  69{
  70        /* Enable DBI access */
  71        writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
  72                        &app_reg->slv_armisc);
  73        writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
  74                        &app_reg->slv_awmisc);
  75
  76}
  77
  78static void disable_dbi_access(struct pcie_app_reg __iomem *app_reg)
  79{
  80        /* disable DBI access */
  81        writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
  82                        &app_reg->slv_armisc);
  83        writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
  84                        &app_reg->slv_awmisc);
  85
  86}
  87
  88static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
  89                int where, int size, u32 *val)
  90{
  91        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
  92        ulong va_address;
  93
  94        /* Enable DBI access */
  95        enable_dbi_access(app_reg);
  96
  97        va_address = (ulong)config->va_dbi_base + (where & ~0x3);
  98
  99        *val = readl(va_address);
 100
 101        if (size == 1)
 102                *val = (*val >> (8 * (where & 3))) & 0xff;
 103        else if (size == 2)
 104                *val = (*val >> (8 * (where & 3))) & 0xffff;
 105
 106        /* Disable DBI access */
 107        disable_dbi_access(app_reg);
 108}
 109
 110static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
 111                int where, int size, u32 val)
 112{
 113        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 114        ulong va_address;
 115
 116        /* Enable DBI access */
 117        enable_dbi_access(app_reg);
 118
 119        va_address = (ulong)config->va_dbi_base + (where & ~0x3);
 120
 121        if (size == 4)
 122                writel(val, va_address);
 123        else if (size == 2)
 124                writew(val, va_address + (where & 2));
 125        else if (size == 1)
 126                writeb(val, va_address + (where & 3));
 127
 128        /* Disable DBI access */
 129        disable_dbi_access(app_reg);
 130}
 131
 132#define PCI_FIND_CAP_TTL        48
 133
 134static int pci_find_own_next_cap_ttl(struct spear_pcie_gadget_config *config,
 135                u32 pos, int cap, int *ttl)
 136{
 137        u32 id;
 138
 139        while ((*ttl)--) {
 140                spear_dbi_read_reg(config, pos, 1, &pos);
 141                if (pos < 0x40)
 142                        break;
 143                pos &= ~3;
 144                spear_dbi_read_reg(config, pos + PCI_CAP_LIST_ID, 1, &id);
 145                if (id == 0xff)
 146                        break;
 147                if (id == cap)
 148                        return pos;
 149                pos += PCI_CAP_LIST_NEXT;
 150        }
 151        return 0;
 152}
 153
 154static int pci_find_own_next_cap(struct spear_pcie_gadget_config *config,
 155                        u32 pos, int cap)
 156{
 157        int ttl = PCI_FIND_CAP_TTL;
 158
 159        return pci_find_own_next_cap_ttl(config, pos, cap, &ttl);
 160}
 161
 162static int pci_find_own_cap_start(struct spear_pcie_gadget_config *config,
 163                                u8 hdr_type)
 164{
 165        u32 status;
 166
 167        spear_dbi_read_reg(config, PCI_STATUS, 2, &status);
 168        if (!(status & PCI_STATUS_CAP_LIST))
 169                return 0;
 170
 171        switch (hdr_type) {
 172        case PCI_HEADER_TYPE_NORMAL:
 173        case PCI_HEADER_TYPE_BRIDGE:
 174                return PCI_CAPABILITY_LIST;
 175        case PCI_HEADER_TYPE_CARDBUS:
 176                return PCI_CB_CAPABILITY_LIST;
 177        default:
 178                return 0;
 179        }
 180
 181        return 0;
 182}
 183
 184/*
 185 * Tell if a device supports a given PCI capability.
 186 * Returns the address of the requested capability structure within the
 187 * device's PCI configuration space or 0 in case the device does not
 188 * support it. Possible values for @cap:
 189 *
 190 * %PCI_CAP_ID_PM       Power Management
 191 * %PCI_CAP_ID_AGP      Accelerated Graphics Port
 192 * %PCI_CAP_ID_VPD      Vital Product Data
 193 * %PCI_CAP_ID_SLOTID   Slot Identification
 194 * %PCI_CAP_ID_MSI      Message Signalled Interrupts
 195 * %PCI_CAP_ID_CHSWP    CompactPCI HotSwap
 196 * %PCI_CAP_ID_PCIX     PCI-X
 197 * %PCI_CAP_ID_EXP      PCI Express
 198 */
 199static int pci_find_own_capability(struct spear_pcie_gadget_config *config,
 200                int cap)
 201{
 202        u32 pos;
 203        u32 hdr_type;
 204
 205        spear_dbi_read_reg(config, PCI_HEADER_TYPE, 1, &hdr_type);
 206
 207        pos = pci_find_own_cap_start(config, hdr_type);
 208        if (pos)
 209                pos = pci_find_own_next_cap(config, pos, cap);
 210
 211        return pos;
 212}
 213
 214static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
 215{
 216        return 0;
 217}
 218
 219/*
 220 * configfs interfaces show/store functions
 221 */
 222static ssize_t pcie_gadget_show_link(
 223                struct spear_pcie_gadget_config *config,
 224                char *buf)
 225{
 226        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 227
 228        if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
 229                return sprintf(buf, "UP");
 230        else
 231                return sprintf(buf, "DOWN");
 232}
 233
 234static ssize_t pcie_gadget_store_link(
 235                struct spear_pcie_gadget_config *config,
 236                const char *buf, size_t count)
 237{
 238        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 239
 240        if (sysfs_streq(buf, "UP"))
 241                writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
 242                        &app_reg->app_ctrl_0);
 243        else if (sysfs_streq(buf, "DOWN"))
 244                writel(readl(&app_reg->app_ctrl_0)
 245                                & ~(1 << APP_LTSSM_ENABLE_ID),
 246                                &app_reg->app_ctrl_0);
 247        else
 248                return -EINVAL;
 249        return count;
 250}
 251
 252static ssize_t pcie_gadget_show_int_type(
 253                struct spear_pcie_gadget_config *config,
 254                char *buf)
 255{
 256        return sprintf(buf, "%s", config->int_type);
 257}
 258
 259static ssize_t pcie_gadget_store_int_type(
 260                struct spear_pcie_gadget_config *config,
 261                const char *buf, size_t count)
 262{
 263        u32 cap, vec, flags;
 264        ulong vector;
 265
 266        if (sysfs_streq(buf, "INTA"))
 267                spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
 268
 269        else if (sysfs_streq(buf, "MSI")) {
 270                vector = config->requested_msi;
 271                vec = 0;
 272                while (vector > 1) {
 273                        vector /= 2;
 274                        vec++;
 275                }
 276                spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
 277                cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
 278                spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
 279                flags &= ~PCI_MSI_FLAGS_QMASK;
 280                flags |= vec << 1;
 281                spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
 282        } else
 283                return -EINVAL;
 284
 285        strcpy(config->int_type, buf);
 286
 287        return count;
 288}
 289
 290static ssize_t pcie_gadget_show_no_of_msi(
 291                struct spear_pcie_gadget_config *config,
 292                char *buf)
 293{
 294        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 295        u32 cap, vec, flags;
 296        ulong vector;
 297
 298        if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
 299                        != (1 << CFG_MSI_EN_ID))
 300                vector = 0;
 301        else {
 302                cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
 303                spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
 304                flags &= ~PCI_MSI_FLAGS_QSIZE;
 305                vec = flags >> 4;
 306                vector = 1;
 307                while (vec--)
 308                        vector *= 2;
 309        }
 310        config->configured_msi = vector;
 311
 312        return sprintf(buf, "%lu", vector);
 313}
 314
 315static ssize_t pcie_gadget_store_no_of_msi(
 316                struct spear_pcie_gadget_config *config,
 317                const char *buf, size_t count)
 318{
 319        if (strict_strtoul(buf, 0, &config->requested_msi))
 320                return -EINVAL;
 321        if (config->requested_msi > 32)
 322                config->requested_msi = 32;
 323
 324        return count;
 325}
 326
 327static ssize_t pcie_gadget_store_inta(
 328                struct spear_pcie_gadget_config *config,
 329                const char *buf, size_t count)
 330{
 331        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 332        ulong en;
 333
 334        if (strict_strtoul(buf, 0, &en))
 335                return -EINVAL;
 336
 337        if (en)
 338                writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
 339                                &app_reg->app_ctrl_0);
 340        else
 341                writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
 342                                &app_reg->app_ctrl_0);
 343
 344        return count;
 345}
 346
 347static ssize_t pcie_gadget_store_send_msi(
 348                struct spear_pcie_gadget_config *config,
 349                const char *buf, size_t count)
 350{
 351        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 352        ulong vector;
 353        u32 ven_msi;
 354
 355        if (strict_strtoul(buf, 0, &vector))
 356                return -EINVAL;
 357
 358        if (!config->configured_msi)
 359                return -EINVAL;
 360
 361        if (vector >= config->configured_msi)
 362                return -EINVAL;
 363
 364        ven_msi = readl(&app_reg->ven_msi_1);
 365        ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
 366        ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
 367        ven_msi &= ~VEN_MSI_TC_MASK;
 368        ven_msi |= 0 << VEN_MSI_TC_ID;
 369        ven_msi &= ~VEN_MSI_VECTOR_MASK;
 370        ven_msi |= vector << VEN_MSI_VECTOR_ID;
 371
 372        /* generating interrupt for msi vector */
 373        ven_msi |= VEN_MSI_REQ_EN;
 374        writel(ven_msi, &app_reg->ven_msi_1);
 375        udelay(1);
 376        ven_msi &= ~VEN_MSI_REQ_EN;
 377        writel(ven_msi, &app_reg->ven_msi_1);
 378
 379        return count;
 380}
 381
 382static ssize_t pcie_gadget_show_vendor_id(
 383                struct spear_pcie_gadget_config *config,
 384                char *buf)
 385{
 386        u32 id;
 387
 388        spear_dbi_read_reg(config, PCI_VENDOR_ID, 2, &id);
 389
 390        return sprintf(buf, "%x", id);
 391}
 392
 393static ssize_t pcie_gadget_store_vendor_id(
 394                struct spear_pcie_gadget_config *config,
 395                const char *buf, size_t count)
 396{
 397        ulong id;
 398
 399        if (strict_strtoul(buf, 0, &id))
 400                return -EINVAL;
 401
 402        spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
 403
 404        return count;
 405}
 406
 407static ssize_t pcie_gadget_show_device_id(
 408                struct spear_pcie_gadget_config *config,
 409                char *buf)
 410{
 411        u32 id;
 412
 413        spear_dbi_read_reg(config, PCI_DEVICE_ID, 2, &id);
 414
 415        return sprintf(buf, "%x", id);
 416}
 417
 418static ssize_t pcie_gadget_store_device_id(
 419                struct spear_pcie_gadget_config *config,
 420                const char *buf, size_t count)
 421{
 422        ulong id;
 423
 424        if (strict_strtoul(buf, 0, &id))
 425                return -EINVAL;
 426
 427        spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
 428
 429        return count;
 430}
 431
 432static ssize_t pcie_gadget_show_bar0_size(
 433                struct spear_pcie_gadget_config *config,
 434                char *buf)
 435{
 436        return sprintf(buf, "%lx", config->bar0_size);
 437}
 438
 439static ssize_t pcie_gadget_store_bar0_size(
 440                struct spear_pcie_gadget_config *config,
 441                const char *buf, size_t count)
 442{
 443        ulong size;
 444        u32 pos, pos1;
 445        u32 no_of_bit = 0;
 446
 447        if (strict_strtoul(buf, 0, &size))
 448                return -EINVAL;
 449        /* min bar size is 256 */
 450        if (size <= 0x100)
 451                size = 0x100;
 452        /* max bar size is 1MB*/
 453        else if (size >= 0x100000)
 454                size = 0x100000;
 455        else {
 456                pos = 0;
 457                pos1 = 0;
 458                while (pos < 21) {
 459                        pos = find_next_bit((ulong *)&size, 21, pos);
 460                        if (pos != 21)
 461                                pos1 = pos + 1;
 462                        pos++;
 463                        no_of_bit++;
 464                }
 465                if (no_of_bit == 2)
 466                        pos1--;
 467
 468                size = 1 << pos1;
 469        }
 470        config->bar0_size = size;
 471        spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
 472
 473        return count;
 474}
 475
 476static ssize_t pcie_gadget_show_bar0_address(
 477                struct spear_pcie_gadget_config *config,
 478                char *buf)
 479{
 480        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 481
 482        u32 address = readl(&app_reg->pim0_mem_addr_start);
 483
 484        return sprintf(buf, "%x", address);
 485}
 486
 487static ssize_t pcie_gadget_store_bar0_address(
 488                struct spear_pcie_gadget_config *config,
 489                const char *buf, size_t count)
 490{
 491        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 492        ulong address;
 493
 494        if (strict_strtoul(buf, 0, &address))
 495                return -EINVAL;
 496
 497        address &= ~(config->bar0_size - 1);
 498        if (config->va_bar0_address)
 499                iounmap(config->va_bar0_address);
 500        config->va_bar0_address = ioremap(address, config->bar0_size);
 501        if (!config->va_bar0_address)
 502                return -ENOMEM;
 503
 504        writel(address, &app_reg->pim0_mem_addr_start);
 505
 506        return count;
 507}
 508
 509static ssize_t pcie_gadget_show_bar0_rw_offset(
 510                struct spear_pcie_gadget_config *config,
 511                char *buf)
 512{
 513        return sprintf(buf, "%lx", config->bar0_rw_offset);
 514}
 515
 516static ssize_t pcie_gadget_store_bar0_rw_offset(
 517                struct spear_pcie_gadget_config *config,
 518                const char *buf, size_t count)
 519{
 520        ulong offset;
 521
 522        if (strict_strtoul(buf, 0, &offset))
 523                return -EINVAL;
 524
 525        if (offset % 4)
 526                return -EINVAL;
 527
 528        config->bar0_rw_offset = offset;
 529
 530        return count;
 531}
 532
 533static ssize_t pcie_gadget_show_bar0_data(
 534                struct spear_pcie_gadget_config *config,
 535                char *buf)
 536{
 537        ulong data;
 538
 539        if (!config->va_bar0_address)
 540                return -ENOMEM;
 541
 542        data = readl((ulong)config->va_bar0_address + config->bar0_rw_offset);
 543
 544        return sprintf(buf, "%lx", data);
 545}
 546
 547static ssize_t pcie_gadget_store_bar0_data(
 548                struct spear_pcie_gadget_config *config,
 549                const char *buf, size_t count)
 550{
 551        ulong data;
 552
 553        if (strict_strtoul(buf, 0, &data))
 554                return -EINVAL;
 555
 556        if (!config->va_bar0_address)
 557                return -ENOMEM;
 558
 559        writel(data, (ulong)config->va_bar0_address + config->bar0_rw_offset);
 560
 561        return count;
 562}
 563
 564/*
 565 * Attribute definitions.
 566 */
 567
 568#define PCIE_GADGET_TARGET_ATTR_RO(_name)                               \
 569static struct pcie_gadget_target_attr pcie_gadget_target_##_name =      \
 570        __CONFIGFS_ATTR(_name, S_IRUGO, pcie_gadget_show_##_name, NULL)
 571
 572#define PCIE_GADGET_TARGET_ATTR_WO(_name)                               \
 573static struct pcie_gadget_target_attr pcie_gadget_target_##_name =      \
 574        __CONFIGFS_ATTR(_name, S_IWUSR, NULL, pcie_gadget_store_##_name)
 575
 576#define PCIE_GADGET_TARGET_ATTR_RW(_name)                               \
 577static struct pcie_gadget_target_attr pcie_gadget_target_##_name =      \
 578        __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, pcie_gadget_show_##_name, \
 579                        pcie_gadget_store_##_name)
 580PCIE_GADGET_TARGET_ATTR_RW(link);
 581PCIE_GADGET_TARGET_ATTR_RW(int_type);
 582PCIE_GADGET_TARGET_ATTR_RW(no_of_msi);
 583PCIE_GADGET_TARGET_ATTR_WO(inta);
 584PCIE_GADGET_TARGET_ATTR_WO(send_msi);
 585PCIE_GADGET_TARGET_ATTR_RW(vendor_id);
 586PCIE_GADGET_TARGET_ATTR_RW(device_id);
 587PCIE_GADGET_TARGET_ATTR_RW(bar0_size);
 588PCIE_GADGET_TARGET_ATTR_RW(bar0_address);
 589PCIE_GADGET_TARGET_ATTR_RW(bar0_rw_offset);
 590PCIE_GADGET_TARGET_ATTR_RW(bar0_data);
 591
 592static struct configfs_attribute *pcie_gadget_target_attrs[] = {
 593        &pcie_gadget_target_link.attr,
 594        &pcie_gadget_target_int_type.attr,
 595        &pcie_gadget_target_no_of_msi.attr,
 596        &pcie_gadget_target_inta.attr,
 597        &pcie_gadget_target_send_msi.attr,
 598        &pcie_gadget_target_vendor_id.attr,
 599        &pcie_gadget_target_device_id.attr,
 600        &pcie_gadget_target_bar0_size.attr,
 601        &pcie_gadget_target_bar0_address.attr,
 602        &pcie_gadget_target_bar0_rw_offset.attr,
 603        &pcie_gadget_target_bar0_data.attr,
 604        NULL,
 605};
 606
 607static struct pcie_gadget_target *to_target(struct config_item *item)
 608{
 609        return item ?
 610                container_of(to_configfs_subsystem(to_config_group(item)),
 611                                struct pcie_gadget_target, subsys) : NULL;
 612}
 613
 614/*
 615 * Item operations and type for pcie_gadget_target.
 616 */
 617
 618static ssize_t pcie_gadget_target_attr_show(struct config_item *item,
 619                                           struct configfs_attribute *attr,
 620                                           char *buf)
 621{
 622        ssize_t ret = -EINVAL;
 623        struct pcie_gadget_target *target = to_target(item);
 624        struct pcie_gadget_target_attr *t_attr =
 625                container_of(attr, struct pcie_gadget_target_attr, attr);
 626
 627        if (t_attr->show)
 628                ret = t_attr->show(&target->config, buf);
 629        return ret;
 630}
 631
 632static ssize_t pcie_gadget_target_attr_store(struct config_item *item,
 633                                        struct configfs_attribute *attr,
 634                                        const char *buf,
 635                                        size_t count)
 636{
 637        ssize_t ret = -EINVAL;
 638        struct pcie_gadget_target *target = to_target(item);
 639        struct pcie_gadget_target_attr *t_attr =
 640                container_of(attr, struct pcie_gadget_target_attr, attr);
 641
 642        if (t_attr->store)
 643                ret = t_attr->store(&target->config, buf, count);
 644        return ret;
 645}
 646
 647static struct configfs_item_operations pcie_gadget_target_item_ops = {
 648        .show_attribute         = pcie_gadget_target_attr_show,
 649        .store_attribute        = pcie_gadget_target_attr_store,
 650};
 651
 652static struct config_item_type pcie_gadget_target_type = {
 653        .ct_attrs               = pcie_gadget_target_attrs,
 654        .ct_item_ops            = &pcie_gadget_target_item_ops,
 655        .ct_owner               = THIS_MODULE,
 656};
 657
 658static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
 659{
 660        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 661
 662        /*setup registers for outbound translation */
 663
 664        writel(config->base, &app_reg->in0_mem_addr_start);
 665        writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE,
 666                        &app_reg->in0_mem_addr_limit);
 667        writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start);
 668        writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE,
 669                        &app_reg->in1_mem_addr_limit);
 670        writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start);
 671        writel(app_reg->in_io_addr_start + IN_IO_SIZE,
 672                        &app_reg->in_io_addr_limit);
 673        writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start);
 674        writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE,
 675                        &app_reg->in_cfg0_addr_limit);
 676        writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start);
 677        writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE,
 678                        &app_reg->in_cfg1_addr_limit);
 679        writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start);
 680        writel(app_reg->in_msg_addr_start + IN_MSG_SIZE,
 681                        &app_reg->in_msg_addr_limit);
 682
 683        writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start);
 684        writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start);
 685        writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start);
 686
 687        /*setup registers for inbound translation */
 688
 689        /* Keep AORAM mapped at BAR0 as default */
 690        config->bar0_size = INBOUND_ADDR_MASK + 1;
 691        spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK);
 692        spear_dbi_write_reg(config, PCI_BASE_ADDRESS_0, 4, 0xC);
 693        config->va_bar0_address = ioremap(SPEAR13XX_SYSRAM1_BASE,
 694                        config->bar0_size);
 695
 696        writel(SPEAR13XX_SYSRAM1_BASE, &app_reg->pim0_mem_addr_start);
 697        writel(0, &app_reg->pim1_mem_addr_start);
 698        writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit);
 699
 700        writel(0x0, &app_reg->pim_io_addr_start);
 701        writel(0x0, &app_reg->pim_io_addr_start);
 702        writel(0x0, &app_reg->pim_rom_addr_start);
 703
 704        writel(DEVICE_TYPE_EP | (1 << MISCTRL_EN_ID)
 705                        | ((u32)1 << REG_TRANSLATION_ENABLE),
 706                        &app_reg->app_ctrl_0);
 707        /* disable all rx interrupts */
 708        writel(0, &app_reg->int_mask);
 709
 710        /* Select INTA as default*/
 711        spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
 712}
 713
 714static int spear_pcie_gadget_probe(struct platform_device *pdev)
 715{
 716        struct resource *res0, *res1;
 717        unsigned int status = 0;
 718        int irq;
 719        struct clk *clk;
 720        static struct pcie_gadget_target *target;
 721        struct spear_pcie_gadget_config *config;
 722        struct config_item              *cg_item;
 723        struct configfs_subsystem *subsys;
 724
 725        /* get resource for application registers*/
 726
 727        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 728        if (!res0) {
 729                dev_err(&pdev->dev, "no resource defined\n");
 730                return -EBUSY;
 731        }
 732        if (!request_mem_region(res0->start, resource_size(res0),
 733                                pdev->name)) {
 734                dev_err(&pdev->dev, "pcie gadget region already claimed\n");
 735                return -EBUSY;
 736        }
 737        /* get resource for dbi registers*/
 738
 739        res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 740        if (!res1) {
 741                dev_err(&pdev->dev, "no resource defined\n");
 742                goto err_rel_res0;
 743        }
 744        if (!request_mem_region(res1->start, resource_size(res1),
 745                                pdev->name)) {
 746                dev_err(&pdev->dev, "pcie gadget region already claimed\n");
 747                goto err_rel_res0;
 748        }
 749
 750        target = kzalloc(sizeof(*target), GFP_KERNEL);
 751        if (!target) {
 752                dev_err(&pdev->dev, "out of memory\n");
 753                status = -ENOMEM;
 754                goto err_rel_res;
 755        }
 756
 757        cg_item = &target->subsys.su_group.cg_item;
 758        sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id);
 759        cg_item->ci_type        = &pcie_gadget_target_type;
 760        config = &target->config;
 761        config->va_app_base = (void __iomem *)ioremap(res0->start,
 762                        resource_size(res0));
 763        if (!config->va_app_base) {
 764                dev_err(&pdev->dev, "ioremap fail\n");
 765                status = -ENOMEM;
 766                goto err_kzalloc;
 767        }
 768
 769        config->base = (void __iomem *)res1->start;
 770
 771        config->va_dbi_base = (void __iomem *)ioremap(res1->start,
 772                        resource_size(res1));
 773        if (!config->va_dbi_base) {
 774                dev_err(&pdev->dev, "ioremap fail\n");
 775                status = -ENOMEM;
 776                goto err_iounmap_app;
 777        }
 778
 779        dev_set_drvdata(&pdev->dev, target);
 780
 781        irq = platform_get_irq(pdev, 0);
 782        if (irq < 0) {
 783                dev_err(&pdev->dev, "no update irq?\n");
 784                status = irq;
 785                goto err_iounmap;
 786        }
 787
 788        status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name, NULL);
 789        if (status) {
 790                dev_err(&pdev->dev,
 791                        "pcie gadget interrupt IRQ%d already claimed\n", irq);
 792                goto err_iounmap;
 793        }
 794
 795        /* Register configfs hooks */
 796        subsys = &target->subsys;
 797        config_group_init(&subsys->su_group);
 798        mutex_init(&subsys->su_mutex);
 799        status = configfs_register_subsystem(subsys);
 800        if (status)
 801                goto err_irq;
 802
 803        /*
 804         * init basic pcie application registers
 805         * do not enable clock if it is PCIE0.Ideally , all controller should
 806         * have been independent from others with respect to clock. But PCIE1
 807         * and 2 depends on PCIE0.So PCIE0 clk is provided during board init.
 808         */
 809        if (pdev->id == 1) {
 810                /*
 811                 * Ideally CFG Clock should have been also enabled here. But
 812                 * it is done currently during board init routne
 813                 */
 814                clk = clk_get_sys("pcie1", NULL);
 815                if (IS_ERR(clk)) {
 816                        pr_err("%s:couldn't get clk for pcie1\n", __func__);
 817                        goto err_irq;
 818                }
 819                if (clk_enable(clk)) {
 820                        pr_err("%s:couldn't enable clk for pcie1\n", __func__);
 821                        goto err_irq;
 822                }
 823        } else if (pdev->id == 2) {
 824                /*
 825                 * Ideally CFG Clock should have been also enabled here. But
 826                 * it is done currently during board init routne
 827                 */
 828                clk = clk_get_sys("pcie2", NULL);
 829                if (IS_ERR(clk)) {
 830                        pr_err("%s:couldn't get clk for pcie2\n", __func__);
 831                        goto err_irq;
 832                }
 833                if (clk_enable(clk)) {
 834                        pr_err("%s:couldn't enable clk for pcie2\n", __func__);
 835                        goto err_irq;
 836                }
 837        }
 838        spear13xx_pcie_device_init(config);
 839
 840        return 0;
 841err_irq:
 842        free_irq(irq, NULL);
 843err_iounmap:
 844        iounmap(config->va_dbi_base);
 845err_iounmap_app:
 846        iounmap(config->va_app_base);
 847err_kzalloc:
 848        kfree(target);
 849err_rel_res:
 850        release_mem_region(res1->start, resource_size(res1));
 851err_rel_res0:
 852        release_mem_region(res0->start, resource_size(res0));
 853        return status;
 854}
 855
 856static int spear_pcie_gadget_remove(struct platform_device *pdev)
 857{
 858        struct resource *res0, *res1;
 859        static struct pcie_gadget_target *target;
 860        struct spear_pcie_gadget_config *config;
 861        int irq;
 862
 863        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 864        res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 865        irq = platform_get_irq(pdev, 0);
 866        target = dev_get_drvdata(&pdev->dev);
 867        config = &target->config;
 868
 869        free_irq(irq, NULL);
 870        iounmap(config->va_dbi_base);
 871        iounmap(config->va_app_base);
 872        release_mem_region(res1->start, resource_size(res1));
 873        release_mem_region(res0->start, resource_size(res0));
 874        configfs_unregister_subsystem(&target->subsys);
 875        kfree(target);
 876
 877        return 0;
 878}
 879
 880static void spear_pcie_gadget_shutdown(struct platform_device *pdev)
 881{
 882}
 883
 884static struct platform_driver spear_pcie_gadget_driver = {
 885        .probe = spear_pcie_gadget_probe,
 886        .remove = spear_pcie_gadget_remove,
 887        .shutdown = spear_pcie_gadget_shutdown,
 888        .driver = {
 889                .name = "pcie-gadget-spear",
 890                .bus = &platform_bus_type
 891        },
 892};
 893
 894module_platform_driver(spear_pcie_gadget_driver);
 895
 896MODULE_ALIAS("platform:pcie-gadget-spear");
 897MODULE_AUTHOR("Pratyush Anand");
 898MODULE_LICENSE("GPL");
 899
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.