uboot/drivers/pci/pci_sh7751.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * SH7751 PCI Controller (PCIC) for U-Boot.
   4 * (C) Dustin McIntire (dustin@sensoria.com)
   5 * (C) 2007,2008 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <pci.h>
  11#include <asm/processor.h>
  12#include <asm/io.h>
  13#include <asm/pci.h>
  14#include <linux/bitops.h>
  15#include <linux/delay.h>
  16
  17/* Register addresses and such */
  18#define SH7751_BCR1     (vu_long *)0xFF800000
  19#define SH7751_BCR2     (vu_short *)0xFF800004
  20#define SH7751_WCR1     (vu_long *)0xFF800008
  21#define SH7751_WCR2     (vu_long *)0xFF80000C
  22#define SH7751_WCR3     (vu_long *)0xFF800010
  23#define SH7751_MCR      (vu_long *)0xFF800014
  24#define SH7751_BCR3     (vu_short *)0xFF800050
  25#define SH7751_PCICONF0 (vu_long *)0xFE200000
  26#define SH7751_PCICONF1 (vu_long *)0xFE200004
  27#define SH7751_PCICONF2 (vu_long *)0xFE200008
  28#define SH7751_PCICONF3 (vu_long *)0xFE20000C
  29#define SH7751_PCICONF4 (vu_long *)0xFE200010
  30#define SH7751_PCICONF5 (vu_long *)0xFE200014
  31#define SH7751_PCICONF6 (vu_long *)0xFE200018
  32#define SH7751_PCICR    (vu_long *)0xFE200100
  33#define SH7751_PCILSR0  (vu_long *)0xFE200104
  34#define SH7751_PCILSR1  (vu_long *)0xFE200108
  35#define SH7751_PCILAR0  (vu_long *)0xFE20010C
  36#define SH7751_PCILAR1  (vu_long *)0xFE200110
  37#define SH7751_PCIMBR   (vu_long *)0xFE2001C4
  38#define SH7751_PCIIOBR  (vu_long *)0xFE2001C8
  39#define SH7751_PCIPINT  (vu_long *)0xFE2001CC
  40#define SH7751_PCIPINTM (vu_long *)0xFE2001D0
  41#define SH7751_PCICLKR  (vu_long *)0xFE2001D4
  42#define SH7751_PCIBCR1  (vu_long *)0xFE2001E0
  43#define SH7751_PCIBCR2  (vu_long *)0xFE2001E4
  44#define SH7751_PCIWCR1  (vu_long *)0xFE2001E8
  45#define SH7751_PCIWCR2  (vu_long *)0xFE2001EC
  46#define SH7751_PCIWCR3  (vu_long *)0xFE2001F0
  47#define SH7751_PCIMCR   (vu_long *)0xFE2001F4
  48#define SH7751_PCIBCR3  (vu_long *)0xFE2001F8
  49
  50#define BCR1_BREQEN             0x00080000
  51#define PCI_SH7751_ID           0x35051054
  52#define PCI_SH7751R_ID          0x350E1054
  53#define SH7751_PCICONF1_WCC     0x00000080
  54#define SH7751_PCICONF1_PER     0x00000040
  55#define SH7751_PCICONF1_BUM     0x00000004
  56#define SH7751_PCICONF1_MES     0x00000002
  57#define SH7751_PCICONF1_CMDS    0x000000C6
  58#define SH7751_PCI_HOST_BRIDGE  0x6
  59#define SH7751_PCICR_PREFIX     0xa5000000
  60#define SH7751_PCICR_PRST       0x00000002
  61#define SH7751_PCICR_CFIN       0x00000001
  62#define SH7751_PCIPINT_D3       0x00000002
  63#define SH7751_PCIPINT_D0       0x00000001
  64#define SH7751_PCICLKR_PREFIX   0xa5000000
  65
  66#define SH7751_PCI_MEM_BASE     0xFD000000
  67#define SH7751_PCI_MEM_SIZE     0x01000000
  68#define SH7751_PCI_IO_BASE      0xFE240000
  69#define SH7751_PCI_IO_SIZE      0x00040000
  70
  71#define SH7751_PCIPAR   (vu_long *)0xFE2001C0
  72#define SH7751_PCIPDR   (vu_long *)0xFE200220
  73
  74#define p4_in(addr)     (*addr)
  75#define p4_out(data, addr) (*addr) = (data)
  76
  77static int sh7751_pci_addr_valid(pci_dev_t d, uint offset)
  78{
  79        if (PCI_FUNC(d))
  80                return -EINVAL;
  81
  82        return 0;
  83}
  84
  85static u32 get_bus_address(const struct udevice *dev, pci_dev_t bdf, u32 offset)
  86{
  87        return BIT(31) | (PCI_DEV(bdf) << 8) | (offset & ~3);
  88}
  89
  90static int sh7751_pci_read_config(const struct udevice *dev, pci_dev_t bdf,
  91                                  uint offset, ulong *value,
  92                                  enum pci_size_t size)
  93{
  94        u32 addr, reg;
  95        int ret;
  96
  97        ret = sh7751_pci_addr_valid(bdf, offset);
  98        if (ret) {
  99                *value = pci_get_ff(size);
 100                return 0;
 101        }
 102
 103        addr = get_bus_address(dev, bdf, offset);
 104        p4_out(addr, SH7751_PCIPAR);
 105        reg = p4_in(SH7751_PCIPDR);
 106        *value = pci_conv_32_to_size(reg, offset, size);
 107
 108        return 0;
 109}
 110
 111static int sh7751_pci_write_config(struct udevice *dev, pci_dev_t bdf,
 112                                      uint offset, ulong value,
 113                                      enum pci_size_t size)
 114{
 115        u32 addr, reg, old;
 116        int ret;
 117
 118        ret = sh7751_pci_addr_valid(bdf, offset);
 119        if (ret)
 120                return ret;
 121
 122        addr = get_bus_address(dev, bdf, offset);
 123        p4_out(addr, SH7751_PCIPAR);
 124        old = p4_in(SH7751_PCIPDR);
 125        reg = pci_conv_size_to_32(old, value, offset, size);
 126        p4_out(reg, SH7751_PCIPDR);
 127
 128        return 0;
 129}
 130
 131static int sh7751_pci_probe(struct udevice *dev)
 132{
 133        /* Double-check that we're a 7751 or 7751R chip */
 134        if (p4_in(SH7751_PCICONF0) != PCI_SH7751_ID
 135            && p4_in(SH7751_PCICONF0) != PCI_SH7751R_ID) {
 136                printf("PCI: Unknown PCI host bridge.\n");
 137                return 1;
 138        }
 139        printf("PCI: SH7751 PCI host bridge found.\n");
 140
 141        /* Double-check some BSC config settings */
 142        /* (Area 3 non-MPX 32-bit, PCI bus pins) */
 143        if ((p4_in(SH7751_BCR1) & 0x20008) == 0x20000) {
 144                printf("SH7751_BCR1 value is wrong(0x%08X)\n",
 145                        (unsigned int)p4_in(SH7751_BCR1));
 146                return 2;
 147        }
 148        if ((p4_in(SH7751_BCR2) & 0xC0) != 0xC0) {
 149                printf("SH7751_BCR2 value is wrong(0x%08X)\n",
 150                        (unsigned int)p4_in(SH7751_BCR2));
 151                return 3;
 152        }
 153        if (p4_in(SH7751_BCR2) & 0x01) {
 154                printf("SH7751_BCR2 value is wrong(0x%08X)\n",
 155                        (unsigned int)p4_in(SH7751_BCR2));
 156                return 4;
 157        }
 158
 159        /* Force BREQEN in BCR1 to allow PCIC access */
 160        p4_out((p4_in(SH7751_BCR1) | BCR1_BREQEN), SH7751_BCR1);
 161
 162        /* Toggle PCI reset pin */
 163        p4_out((SH7751_PCICR_PREFIX | SH7751_PCICR_PRST), SH7751_PCICR);
 164        udelay(32);
 165        p4_out(SH7751_PCICR_PREFIX, SH7751_PCICR);
 166
 167        /* Set cmd bits: WCC, PER, BUM, MES */
 168        /* (Addr/Data stepping, Parity enabled, Bus Master, Memory enabled) */
 169        p4_out(0xfb900047, SH7751_PCICONF1);    /* K.Kino */
 170
 171        /* Define this host as the host bridge */
 172        p4_out((SH7751_PCI_HOST_BRIDGE << 24), SH7751_PCICONF2);
 173
 174        /* Force PCI clock(s) on */
 175        p4_out(0, SH7751_PCICLKR);
 176        p4_out(0x03, SH7751_PCICLKR);
 177
 178        /* Clear powerdown IRQs, also mask them (unused) */
 179        p4_out((SH7751_PCIPINT_D0 | SH7751_PCIPINT_D3), SH7751_PCIPINT);
 180        p4_out(0, SH7751_PCIPINTM);
 181
 182        p4_out(0xab000001, SH7751_PCICONF4);
 183
 184        /* Set up target memory mappings (for external DMA access) */
 185        /* Map both P0 and P2 range to Area 3 RAM for ease of use */
 186        p4_out(CONFIG_SYS_SDRAM_SIZE - 0x100000, SH7751_PCILSR0);
 187        p4_out(CONFIG_SYS_SDRAM_BASE & 0x1FF00000, SH7751_PCILAR0);
 188        p4_out(CONFIG_SYS_SDRAM_BASE & 0xFFF00000, SH7751_PCICONF5);
 189
 190        p4_out(0, SH7751_PCILSR1);
 191        p4_out(0, SH7751_PCILAR1);
 192        p4_out(0xd0000000, SH7751_PCICONF6);
 193
 194        /* Map memory window to same address on PCI bus */
 195        p4_out(SH7751_PCI_MEM_BASE, SH7751_PCIMBR);
 196
 197        /* Map IO window to same address on PCI bus */
 198        p4_out(SH7751_PCI_IO_BASE, SH7751_PCIIOBR);
 199
 200        /* set BREQEN */
 201        p4_out(inl(SH7751_BCR1) | 0x00080000, SH7751_BCR1);
 202
 203        /* Copy BSC registers into PCI BSC */
 204        p4_out(inl(SH7751_BCR1), SH7751_PCIBCR1);
 205        p4_out(inw(SH7751_BCR2), SH7751_PCIBCR2);
 206        p4_out(inw(SH7751_BCR3), SH7751_PCIBCR3);
 207        p4_out(inl(SH7751_WCR1), SH7751_PCIWCR1);
 208        p4_out(inl(SH7751_WCR2), SH7751_PCIWCR2);
 209        p4_out(inl(SH7751_WCR3), SH7751_PCIWCR3);
 210        p4_out(inl(SH7751_MCR), SH7751_PCIMCR);
 211
 212        /* Finally, set central function init complete */
 213        p4_out((SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN), SH7751_PCICR);
 214
 215        return 0;
 216}
 217
 218static const struct dm_pci_ops sh7751_pci_ops = {
 219        .read_config    = sh7751_pci_read_config,
 220        .write_config   = sh7751_pci_write_config,
 221};
 222
 223static const struct udevice_id sh7751_pci_ids[] = {
 224        { .compatible = "renesas,pci-sh7751" },
 225        { }
 226};
 227
 228U_BOOT_DRIVER(sh7751_pci) = {
 229        .name           = "sh7751_pci",
 230        .id             = UCLASS_PCI,
 231        .of_match       = sh7751_pci_ids,
 232        .ops            = &sh7751_pci_ops,
 233        .probe          = sh7751_pci_probe,
 234};
 235