diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-08-20 07:39:22 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-08-20 07:39:22 -0400 |
commit | 144c7494239f12d554806439a17ad8203c7b2d3a (patch) | |
tree | def630d167f5e25ca926faf462653075a69c7566 /arch/sh/drivers/pci | |
parent | d2d5bc58d79321bd29ed1c8c61e806ec0541e3bf (diff) | |
parent | 65c23f54c01fabae171d54c0e78df354b3709b93 (diff) |
Merge branch 'sh/pci-express-integration'
Diffstat (limited to 'arch/sh/drivers/pci')
-rw-r--r-- | arch/sh/drivers/pci/ops-sh7786.c | 27 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pcie-sh7786.c | 30 |
2 files changed, 36 insertions, 21 deletions
diff --git a/arch/sh/drivers/pci/ops-sh7786.c b/arch/sh/drivers/pci/ops-sh7786.c index 48f594b9582b..79a5ddae733d 100644 --- a/arch/sh/drivers/pci/ops-sh7786.c +++ b/arch/sh/drivers/pci/ops-sh7786.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Generic SH7786 PCI-Express operations. | 2 | * Generic SH7786 PCI-Express operations. |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Paul Mundt | 4 | * Copyright (C) 2009 - 2010 Paul Mundt |
5 | * | 5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 6 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License v2. See the file "COPYING" in the main directory of this archive | 7 | * License v2. See the file "COPYING" in the main directory of this archive |
@@ -25,32 +25,39 @@ static int sh7786_pcie_config_access(unsigned char access_type, | |||
25 | struct pci_bus *bus, unsigned int devfn, int where, u32 *data) | 25 | struct pci_bus *bus, unsigned int devfn, int where, u32 *data) |
26 | { | 26 | { |
27 | struct pci_channel *chan = bus->sysdata; | 27 | struct pci_channel *chan = bus->sysdata; |
28 | int dev, func; | 28 | int dev, func, type; |
29 | 29 | ||
30 | dev = PCI_SLOT(devfn); | 30 | dev = PCI_SLOT(devfn); |
31 | func = PCI_FUNC(devfn); | 31 | func = PCI_FUNC(devfn); |
32 | type = !!bus->parent; | ||
32 | 33 | ||
33 | if (bus->number > 255 || dev > 31 || func > 7) | 34 | if (bus->number > 255 || dev > 31 || func > 7) |
34 | return PCIBIOS_FUNC_NOT_SUPPORTED; | 35 | return PCIBIOS_FUNC_NOT_SUPPORTED; |
35 | if (devfn) | 36 | if (bus->parent == NULL && dev) |
36 | return PCIBIOS_DEVICE_NOT_FOUND; | 37 | return PCIBIOS_DEVICE_NOT_FOUND; |
37 | 38 | ||
39 | /* Clear errors */ | ||
40 | pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR); | ||
41 | |||
38 | /* Set the PIO address */ | 42 | /* Set the PIO address */ |
39 | pci_write_reg(chan, (bus->number << 24) | (dev << 19) | | 43 | pci_write_reg(chan, (bus->number << 24) | (dev << 19) | |
40 | (func << 16) | (where & ~3), SH4A_PCIEPAR); | 44 | (func << 16) | (where & ~3), SH4A_PCIEPAR); |
41 | 45 | ||
42 | /* Enable the configuration access */ | 46 | /* Enable the configuration access */ |
43 | pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR); | 47 | pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR); |
48 | |||
49 | /* Check for errors */ | ||
50 | if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10) | ||
51 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
52 | /* Check for master and target aborts */ | ||
53 | if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) | ||
54 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
44 | 55 | ||
45 | if (access_type == PCI_ACCESS_READ) | 56 | if (access_type == PCI_ACCESS_READ) |
46 | *data = pci_read_reg(chan, SH4A_PCIEPDR); | 57 | *data = pci_read_reg(chan, SH4A_PCIEPDR); |
47 | else | 58 | else |
48 | pci_write_reg(chan, *data, SH4A_PCIEPDR); | 59 | pci_write_reg(chan, *data, SH4A_PCIEPDR); |
49 | 60 | ||
50 | /* Check for master and target aborts */ | ||
51 | if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) | ||
52 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
53 | |||
54 | return PCIBIOS_SUCCESSFUL; | 61 | return PCIBIOS_SUCCESSFUL; |
55 | } | 62 | } |
56 | 63 | ||
@@ -69,8 +76,10 @@ static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn, | |||
69 | spin_lock_irqsave(&sh7786_pcie_lock, flags); | 76 | spin_lock_irqsave(&sh7786_pcie_lock, flags); |
70 | ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus, | 77 | ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus, |
71 | devfn, where, &data); | 78 | devfn, where, &data); |
72 | if (ret != PCIBIOS_SUCCESSFUL) | 79 | if (ret != PCIBIOS_SUCCESSFUL) { |
80 | *val = 0xffffffff; | ||
73 | goto out; | 81 | goto out; |
82 | } | ||
74 | 83 | ||
75 | if (size == 1) | 84 | if (size == 1) |
76 | *val = (data >> ((where & 3) << 3)) & 0xff; | 85 | *val = (data >> ((where & 3) << 3)) & 0xff; |
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 78f378731858..d053ffca8196 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c | |||
@@ -148,16 +148,11 @@ static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask) | |||
148 | static void phy_write_reg(struct pci_channel *chan, unsigned int addr, | 148 | static void phy_write_reg(struct pci_channel *chan, unsigned int addr, |
149 | unsigned int lane, unsigned int data) | 149 | unsigned int lane, unsigned int data) |
150 | { | 150 | { |
151 | unsigned long phyaddr, ctrl; | 151 | unsigned long phyaddr; |
152 | 152 | ||
153 | phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) + | 153 | phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) + |
154 | ((addr & 0xff) << BITS_ADR); | 154 | ((addr & 0xff) << BITS_ADR); |
155 | 155 | ||
156 | /* Enable clock */ | ||
157 | ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); | ||
158 | ctrl |= (1 << BITS_CKE); | ||
159 | pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); | ||
160 | |||
161 | /* Set write data */ | 156 | /* Set write data */ |
162 | pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR); | 157 | pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR); |
163 | pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR); | 158 | pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR); |
@@ -165,20 +160,22 @@ static void phy_write_reg(struct pci_channel *chan, unsigned int addr, | |||
165 | phy_wait_for_ack(chan); | 160 | phy_wait_for_ack(chan); |
166 | 161 | ||
167 | /* Clear command */ | 162 | /* Clear command */ |
163 | pci_write_reg(chan, 0, SH4A_PCIEPHYDOUTR); | ||
168 | pci_write_reg(chan, 0, SH4A_PCIEPHYADRR); | 164 | pci_write_reg(chan, 0, SH4A_PCIEPHYADRR); |
169 | 165 | ||
170 | phy_wait_for_ack(chan); | 166 | phy_wait_for_ack(chan); |
171 | |||
172 | /* Disable clock */ | ||
173 | ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); | ||
174 | ctrl &= ~(1 << BITS_CKE); | ||
175 | pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); | ||
176 | } | 167 | } |
177 | 168 | ||
178 | static int phy_init(struct pci_channel *chan) | 169 | static int phy_init(struct pci_channel *chan) |
179 | { | 170 | { |
171 | unsigned long ctrl; | ||
180 | unsigned int timeout = 100; | 172 | unsigned int timeout = 100; |
181 | 173 | ||
174 | /* Enable clock */ | ||
175 | ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); | ||
176 | ctrl |= (1 << BITS_CKE); | ||
177 | pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); | ||
178 | |||
182 | /* Initialize the phy */ | 179 | /* Initialize the phy */ |
183 | phy_write_reg(chan, 0x60, 0xf, 0x004b008b); | 180 | phy_write_reg(chan, 0x60, 0xf, 0x004b008b); |
184 | phy_write_reg(chan, 0x61, 0xf, 0x00007b41); | 181 | phy_write_reg(chan, 0x61, 0xf, 0x00007b41); |
@@ -187,9 +184,15 @@ static int phy_init(struct pci_channel *chan) | |||
187 | phy_write_reg(chan, 0x66, 0xf, 0x00000010); | 184 | phy_write_reg(chan, 0x66, 0xf, 0x00000010); |
188 | phy_write_reg(chan, 0x74, 0xf, 0x0007001c); | 185 | phy_write_reg(chan, 0x74, 0xf, 0x0007001c); |
189 | phy_write_reg(chan, 0x79, 0xf, 0x01fc000d); | 186 | phy_write_reg(chan, 0x79, 0xf, 0x01fc000d); |
187 | phy_write_reg(chan, 0xb0, 0xf, 0x00000610); | ||
190 | 188 | ||
191 | /* Deassert Standby */ | 189 | /* Deassert Standby */ |
192 | phy_write_reg(chan, 0x67, 0xf, 0x00000400); | 190 | phy_write_reg(chan, 0x67, 0x1, 0x00000400); |
191 | |||
192 | /* Disable clock */ | ||
193 | ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); | ||
194 | ctrl &= ~(1 << BITS_CKE); | ||
195 | pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); | ||
193 | 196 | ||
194 | while (timeout--) { | 197 | while (timeout--) { |
195 | if (pci_read_reg(chan, SH4A_PCIEPHYSR)) | 198 | if (pci_read_reg(chan, SH4A_PCIEPHYSR)) |
@@ -287,6 +290,9 @@ static int pcie_init(struct sh7786_pcie_port *port) | |||
287 | __raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0); | 290 | __raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0); |
288 | __raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0); | 291 | __raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0); |
289 | 292 | ||
293 | __raw_writel(memphys, chan->reg_base + SH4A_PCIEPCICONF4); | ||
294 | __raw_writel(0, chan->reg_base + SH4A_PCIEPCICONF5); | ||
295 | |||
290 | /* Finish initialization */ | 296 | /* Finish initialization */ |
291 | data = pci_read_reg(chan, SH4A_PCIETCTLR); | 297 | data = pci_read_reg(chan, SH4A_PCIETCTLR); |
292 | data |= 0x1; | 298 | data |= 0x1; |