root/arch/mips/pci/pci-ar724x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ar724x_pci_check_link
  2. pci_bus_to_ar724x_controller
  3. ar724x_pci_local_write
  4. ar724x_pci_read
  5. ar724x_pci_write
  6. ar724x_pci_irq_handler
  7. ar724x_pci_irq_unmask
  8. ar724x_pci_irq_mask
  9. ar724x_pci_irq_init
  10. ar724x_pci_hw_init
  11. ar724x_pci_probe
  12. ar724x_pci_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  Atheros AR724X PCI host controller driver
   4  *
   5  *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
   6  *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
   7  */
   8 
   9 #include <linux/irq.h>
  10 #include <linux/pci.h>
  11 #include <linux/init.h>
  12 #include <linux/delay.h>
  13 #include <linux/platform_device.h>
  14 #include <asm/mach-ath79/ath79.h>
  15 #include <asm/mach-ath79/ar71xx_regs.h>
  16 
  17 #define AR724X_PCI_REG_APP              0x00
  18 #define AR724X_PCI_REG_RESET            0x18
  19 #define AR724X_PCI_REG_INT_STATUS       0x4c
  20 #define AR724X_PCI_REG_INT_MASK         0x50
  21 
  22 #define AR724X_PCI_APP_LTSSM_ENABLE     BIT(0)
  23 
  24 #define AR724X_PCI_RESET_LINK_UP        BIT(0)
  25 
  26 #define AR724X_PCI_INT_DEV0             BIT(14)
  27 
  28 #define AR724X_PCI_IRQ_COUNT            1
  29 
  30 #define AR7240_BAR0_WAR_VALUE   0xffff
  31 
  32 #define AR724X_PCI_CMD_INIT     (PCI_COMMAND_MEMORY |           \
  33                                  PCI_COMMAND_MASTER |           \
  34                                  PCI_COMMAND_INVALIDATE |       \
  35                                  PCI_COMMAND_PARITY |           \
  36                                  PCI_COMMAND_SERR |             \
  37                                  PCI_COMMAND_FAST_BACK)
  38 
  39 struct ar724x_pci_controller {
  40         void __iomem *devcfg_base;
  41         void __iomem *ctrl_base;
  42         void __iomem *crp_base;
  43 
  44         int irq;
  45         int irq_base;
  46 
  47         bool link_up;
  48         bool bar0_is_cached;
  49         u32  bar0_value;
  50 
  51         struct pci_controller pci_controller;
  52         struct resource io_res;
  53         struct resource mem_res;
  54 };
  55 
  56 static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
  57 {
  58         u32 reset;
  59 
  60         reset = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET);
  61         return reset & AR724X_PCI_RESET_LINK_UP;
  62 }
  63 
  64 static inline struct ar724x_pci_controller *
  65 pci_bus_to_ar724x_controller(struct pci_bus *bus)
  66 {
  67         struct pci_controller *hose;
  68 
  69         hose = (struct pci_controller *) bus->sysdata;
  70         return container_of(hose, struct ar724x_pci_controller, pci_controller);
  71 }
  72 
  73 static int ar724x_pci_local_write(struct ar724x_pci_controller *apc,
  74                                   int where, int size, u32 value)
  75 {
  76         void __iomem *base;
  77         u32 data;
  78         int s;
  79 
  80         WARN_ON(where & (size - 1));
  81 
  82         if (!apc->link_up)
  83                 return PCIBIOS_DEVICE_NOT_FOUND;
  84 
  85         base = apc->crp_base;
  86         data = __raw_readl(base + (where & ~3));
  87 
  88         switch (size) {
  89         case 1:
  90                 s = ((where & 3) * 8);
  91                 data &= ~(0xff << s);
  92                 data |= ((value & 0xff) << s);
  93                 break;
  94         case 2:
  95                 s = ((where & 2) * 8);
  96                 data &= ~(0xffff << s);
  97                 data |= ((value & 0xffff) << s);
  98                 break;
  99         case 4:
 100                 data = value;
 101                 break;
 102         default:
 103                 return PCIBIOS_BAD_REGISTER_NUMBER;
 104         }
 105 
 106         __raw_writel(data, base + (where & ~3));
 107         /* flush write */
 108         __raw_readl(base + (where & ~3));
 109 
 110         return PCIBIOS_SUCCESSFUL;
 111 }
 112 
 113 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 114                             int size, uint32_t *value)
 115 {
 116         struct ar724x_pci_controller *apc;
 117         void __iomem *base;
 118         u32 data;
 119 
 120         apc = pci_bus_to_ar724x_controller(bus);
 121         if (!apc->link_up)
 122                 return PCIBIOS_DEVICE_NOT_FOUND;
 123 
 124         if (devfn)
 125                 return PCIBIOS_DEVICE_NOT_FOUND;
 126 
 127         base = apc->devcfg_base;
 128         data = __raw_readl(base + (where & ~3));
 129 
 130         switch (size) {
 131         case 1:
 132                 if (where & 1)
 133                         data >>= 8;
 134                 if (where & 2)
 135                         data >>= 16;
 136                 data &= 0xff;
 137                 break;
 138         case 2:
 139                 if (where & 2)
 140                         data >>= 16;
 141                 data &= 0xffff;
 142                 break;
 143         case 4:
 144                 break;
 145         default:
 146                 return PCIBIOS_BAD_REGISTER_NUMBER;
 147         }
 148 
 149         if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
 150             apc->bar0_is_cached) {
 151                 /* use the cached value */
 152                 *value = apc->bar0_value;
 153         } else {
 154                 *value = data;
 155         }
 156 
 157         return PCIBIOS_SUCCESSFUL;
 158 }
 159 
 160 static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 161                              int size, uint32_t value)
 162 {
 163         struct ar724x_pci_controller *apc;
 164         void __iomem *base;
 165         u32 data;
 166         int s;
 167 
 168         apc = pci_bus_to_ar724x_controller(bus);
 169         if (!apc->link_up)
 170                 return PCIBIOS_DEVICE_NOT_FOUND;
 171 
 172         if (devfn)
 173                 return PCIBIOS_DEVICE_NOT_FOUND;
 174 
 175         if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
 176                 if (value != 0xffffffff) {
 177                         /*
 178                          * WAR for a hw issue. If the BAR0 register of the
 179                          * device is set to the proper base address, the
 180                          * memory space of the device is not accessible.
 181                          *
 182                          * Cache the intended value so it can be read back,
 183                          * and write a SoC specific constant value to the
 184                          * BAR0 register in order to make the device memory
 185                          * accessible.
 186                          */
 187                         apc->bar0_is_cached = true;
 188                         apc->bar0_value = value;
 189 
 190                         value = AR7240_BAR0_WAR_VALUE;
 191                 } else {
 192                         apc->bar0_is_cached = false;
 193                 }
 194         }
 195 
 196         base = apc->devcfg_base;
 197         data = __raw_readl(base + (where & ~3));
 198 
 199         switch (size) {
 200         case 1:
 201                 s = ((where & 3) * 8);
 202                 data &= ~(0xff << s);
 203                 data |= ((value & 0xff) << s);
 204                 break;
 205         case 2:
 206                 s = ((where & 2) * 8);
 207                 data &= ~(0xffff << s);
 208                 data |= ((value & 0xffff) << s);
 209                 break;
 210         case 4:
 211                 data = value;
 212                 break;
 213         default:
 214                 return PCIBIOS_BAD_REGISTER_NUMBER;
 215         }
 216 
 217         __raw_writel(data, base + (where & ~3));
 218         /* flush write */
 219         __raw_readl(base + (where & ~3));
 220 
 221         return PCIBIOS_SUCCESSFUL;
 222 }
 223 
 224 static struct pci_ops ar724x_pci_ops = {
 225         .read   = ar724x_pci_read,
 226         .write  = ar724x_pci_write,
 227 };
 228 
 229 static void ar724x_pci_irq_handler(struct irq_desc *desc)
 230 {
 231         struct ar724x_pci_controller *apc;
 232         void __iomem *base;
 233         u32 pending;
 234 
 235         apc = irq_desc_get_handler_data(desc);
 236         base = apc->ctrl_base;
 237 
 238         pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
 239                   __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 240 
 241         if (pending & AR724X_PCI_INT_DEV0)
 242                 generic_handle_irq(apc->irq_base + 0);
 243 
 244         else
 245                 spurious_interrupt();
 246 }
 247 
 248 static void ar724x_pci_irq_unmask(struct irq_data *d)
 249 {
 250         struct ar724x_pci_controller *apc;
 251         void __iomem *base;
 252         int offset;
 253         u32 t;
 254 
 255         apc = irq_data_get_irq_chip_data(d);
 256         base = apc->ctrl_base;
 257         offset = apc->irq_base - d->irq;
 258 
 259         switch (offset) {
 260         case 0:
 261                 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 262                 __raw_writel(t | AR724X_PCI_INT_DEV0,
 263                              base + AR724X_PCI_REG_INT_MASK);
 264                 /* flush write */
 265                 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 266         }
 267 }
 268 
 269 static void ar724x_pci_irq_mask(struct irq_data *d)
 270 {
 271         struct ar724x_pci_controller *apc;
 272         void __iomem *base;
 273         int offset;
 274         u32 t;
 275 
 276         apc = irq_data_get_irq_chip_data(d);
 277         base = apc->ctrl_base;
 278         offset = apc->irq_base - d->irq;
 279 
 280         switch (offset) {
 281         case 0:
 282                 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 283                 __raw_writel(t & ~AR724X_PCI_INT_DEV0,
 284                              base + AR724X_PCI_REG_INT_MASK);
 285 
 286                 /* flush write */
 287                 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
 288 
 289                 t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
 290                 __raw_writel(t | AR724X_PCI_INT_DEV0,
 291                              base + AR724X_PCI_REG_INT_STATUS);
 292 
 293                 /* flush write */
 294                 __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
 295         }
 296 }
 297 
 298 static struct irq_chip ar724x_pci_irq_chip = {
 299         .name           = "AR724X PCI ",
 300         .irq_mask       = ar724x_pci_irq_mask,
 301         .irq_unmask     = ar724x_pci_irq_unmask,
 302         .irq_mask_ack   = ar724x_pci_irq_mask,
 303 };
 304 
 305 static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
 306                                 int id)
 307 {
 308         void __iomem *base;
 309         int i;
 310 
 311         base = apc->ctrl_base;
 312 
 313         __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
 314         __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
 315 
 316         apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
 317 
 318         for (i = apc->irq_base;
 319              i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {
 320                 irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
 321                                          handle_level_irq);
 322                 irq_set_chip_data(i, apc);
 323         }
 324 
 325         irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
 326                                          apc);
 327 }
 328 
 329 static void ar724x_pci_hw_init(struct ar724x_pci_controller *apc)
 330 {
 331         u32 ppl, app;
 332         int wait = 0;
 333 
 334         /* deassert PCIe host controller and PCIe PHY reset */
 335         ath79_device_reset_clear(AR724X_RESET_PCIE);
 336         ath79_device_reset_clear(AR724X_RESET_PCIE_PHY);
 337 
 338         /* remove the reset of the PCIE PLL */
 339         ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
 340         ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET;
 341         ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
 342 
 343         /* deassert bypass for the PCIE PLL */
 344         ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
 345         ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS;
 346         ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
 347 
 348         /* set PCIE Application Control to ready */
 349         app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP);
 350         app |= AR724X_PCI_APP_LTSSM_ENABLE;
 351         __raw_writel(app, apc->ctrl_base + AR724X_PCI_REG_APP);
 352 
 353         /* wait up to 100ms for PHY link up */
 354         do {
 355                 mdelay(10);
 356                 wait++;
 357         } while (wait < 10 && !ar724x_pci_check_link(apc));
 358 }
 359 
 360 static int ar724x_pci_probe(struct platform_device *pdev)
 361 {
 362         struct ar724x_pci_controller *apc;
 363         struct resource *res;
 364         int id;
 365 
 366         id = pdev->id;
 367         if (id == -1)
 368                 id = 0;
 369 
 370         apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller),
 371                             GFP_KERNEL);
 372         if (!apc)
 373                 return -ENOMEM;
 374 
 375         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base");
 376         apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res);
 377         if (IS_ERR(apc->ctrl_base))
 378                 return PTR_ERR(apc->ctrl_base);
 379 
 380         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
 381         apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res);
 382         if (IS_ERR(apc->devcfg_base))
 383                 return PTR_ERR(apc->devcfg_base);
 384 
 385         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
 386         apc->crp_base = devm_ioremap_resource(&pdev->dev, res);
 387         if (IS_ERR(apc->crp_base))
 388                 return PTR_ERR(apc->crp_base);
 389 
 390         apc->irq = platform_get_irq(pdev, 0);
 391         if (apc->irq < 0)
 392                 return -EINVAL;
 393 
 394         res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
 395         if (!res)
 396                 return -EINVAL;
 397 
 398         apc->io_res.parent = res;
 399         apc->io_res.name = "PCI IO space";
 400         apc->io_res.start = res->start;
 401         apc->io_res.end = res->end;
 402         apc->io_res.flags = IORESOURCE_IO;
 403 
 404         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
 405         if (!res)
 406                 return -EINVAL;
 407 
 408         apc->mem_res.parent = res;
 409         apc->mem_res.name = "PCI memory space";
 410         apc->mem_res.start = res->start;
 411         apc->mem_res.end = res->end;
 412         apc->mem_res.flags = IORESOURCE_MEM;
 413 
 414         apc->pci_controller.pci_ops = &ar724x_pci_ops;
 415         apc->pci_controller.io_resource = &apc->io_res;
 416         apc->pci_controller.mem_resource = &apc->mem_res;
 417 
 418         /*
 419          * Do the full PCIE Root Complex Initialization Sequence if the PCIe
 420          * host controller is in reset.
 421          */
 422         if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE)
 423                 ar724x_pci_hw_init(apc);
 424 
 425         apc->link_up = ar724x_pci_check_link(apc);
 426         if (!apc->link_up)
 427                 dev_warn(&pdev->dev, "PCIe link is down\n");
 428 
 429         ar724x_pci_irq_init(apc, id);
 430 
 431         ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT);
 432 
 433         register_pci_controller(&apc->pci_controller);
 434 
 435         return 0;
 436 }
 437 
 438 static struct platform_driver ar724x_pci_driver = {
 439         .probe = ar724x_pci_probe,
 440         .driver = {
 441                 .name = "ar724x-pci",
 442         },
 443 };
 444 
 445 static int __init ar724x_pci_init(void)
 446 {
 447         return platform_driver_register(&ar724x_pci_driver);
 448 }
 449 
 450 postcore_initcall(ar724x_pci_init);

/* [<][>][^][v][top][bottom][index][help] */