kernel: generic: spi: allow empty (un)prepare transfer
[openwrt.git] / target / linux / brcm63xx / patches-3.3 / 317-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch
1 From e170282d7d12f4a26f10d4b666b158d24810d2f6 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jonas.gorski@gmail.com>
3 Date: Sun, 3 Jul 2011 03:41:02 +0200
4 Subject: [PATCH 47/79] MIPS: BCM63XX: Add PCIe Support for BCM6328
5
6 Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
7 ---
8  arch/mips/pci/ops-bcm63xx.c |   61 +++++++++++++++++++++++
9  arch/mips/pci/pci-bcm63xx.c |  112 +++++++++++++++++++++++++++++++++++++++++++
10  arch/mips/pci/pci-bcm63xx.h |    5 ++
11  3 files changed, 178 insertions(+)
12
13 --- a/arch/mips/pci/ops-bcm63xx.c
14 +++ b/arch/mips/pci/ops-bcm63xx.c
15 @@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev
16  
17  DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
18  #endif
19 +
20 +static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
21 +{
22 +       switch (bus->number) {
23 +       case PCIE_BUS_BRIDGE:
24 +               return (PCI_SLOT(devfn) == 0);
25 +       case PCIE_BUS_DEVICE:
26 +               if (PCI_SLOT(devfn) == 0)
27 +                       return bcm_pcie_readl(PCIE_DLSTATUS_REG)
28 +                                       & DLSTATUS_PHYLINKUP;
29 +       default:
30 +               return false;
31 +       }
32 +}
33 +
34 +static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
35 +                            int where, int size, u32 *val)
36 +{
37 +       u32 data;
38 +       u32 reg = where & ~3;
39 +
40 +       if (!bcm63xx_pcie_can_access(bus, devfn))
41 +               return PCIBIOS_DEVICE_NOT_FOUND;
42 +
43 +       if (bus->number == PCIE_BUS_DEVICE)
44 +               reg += PCIE_DEVICE_OFFSET;
45 +
46 +       data = bcm_pcie_readl(reg);
47 +
48 +       *val = postprocess_read(data, where, size);
49 +
50 +       return PCIBIOS_SUCCESSFUL;
51 +
52 +}
53 +
54 +static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
55 +                             int where, int size, u32 val)
56 +{
57 +       u32 data;
58 +       u32 reg = where & ~3;
59 +
60 +       if (!bcm63xx_pcie_can_access(bus, devfn))
61 +               return PCIBIOS_DEVICE_NOT_FOUND;
62 +
63 +       if (bus->number == PCIE_BUS_DEVICE)
64 +               reg += PCIE_DEVICE_OFFSET;
65 +
66 +
67 +       data = bcm_pcie_readl(reg);
68 +
69 +       data = preprocess_write(data, val, where, size);
70 +       bcm_pcie_writel(data, reg);
71 +
72 +       return PCIBIOS_SUCCESSFUL;
73 +}
74 +
75 +
76 +struct pci_ops bcm63xx_pcie_ops = {
77 +       .read   = bcm63xx_pcie_read,
78 +       .write  = bcm63xx_pcie_write
79 +};
80 --- a/arch/mips/pci/pci-bcm63xx.c
81 +++ b/arch/mips/pci/pci-bcm63xx.c
82 @@ -10,6 +10,7 @@
83  #include <linux/pci.h>
84  #include <linux/kernel.h>
85  #include <linux/init.h>
86 +#include <linux/delay.h>
87  #include <asm/bootinfo.h>
88  
89  #include "pci-bcm63xx.h"
90 @@ -65,6 +66,26 @@ struct pci_controller bcm63xx_cb_control
91  };
92  #endif
93  
94 +static struct resource bcm_pcie_mem_resource = {
95 +       .name   = "bcm63xx PCIe memory space",
96 +       .start  = BCM_PCIE_MEM_BASE_PA,
97 +       .end    = BCM_PCIE_MEM_END_PA,
98 +       .flags  = IORESOURCE_MEM,
99 +};
100 +
101 +static struct resource bcm_pcie_io_resource = {
102 +       .name   = "bcm63xx PCIe IO space",
103 +       .start  = 0,
104 +       .end    = 0,
105 +       .flags  = 0,
106 +};
107 +
108 +struct pci_controller bcm63xx_pcie_controller = {
109 +       .pci_ops        = &bcm63xx_pcie_ops,
110 +       .io_resource    = &bcm_pcie_io_resource,
111 +       .mem_resource   = &bcm_pcie_mem_resource,
112 +};
113 +
114  static u32 bcm63xx_int_cfg_readl(u32 reg)
115  {
116         u32 tmp;
117 @@ -88,6 +109,95 @@ static void bcm63xx_int_cfg_writel(u32 v
118  
119  void __iomem *pci_iospace_start;
120  
121 +static void __init bcm63xx_reset_pcie(void)
122 +{
123 +       u32 val;
124 +
125 +       /* enable clock */
126 +       val = bcm_perf_readl(PERF_CKCTL_REG);
127 +       val |= CKCTL_6328_PCIE_EN;
128 +       bcm_perf_writel(val, PERF_CKCTL_REG);
129 +
130 +       /* enable SERDES */
131 +       val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
132 +       val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
133 +       bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
134 +
135 +       /* reset the PCIe core */
136 +       val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
137 +
138 +       val &= ~SOFTRESET_6328_PCIE_MASK;
139 +       val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
140 +       val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
141 +       val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
142 +       bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
143 +       mdelay(10);
144 +
145 +       val |= SOFTRESET_6328_PCIE_MASK;
146 +       val |= SOFTRESET_6328_PCIE_CORE_MASK;
147 +       val |= SOFTRESET_6328_PCIE_HARD_MASK;
148 +       bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
149 +       mdelay(10);
150 +
151 +       val |= SOFTRESET_6328_PCIE_EXT_MASK;
152 +       bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
153 +       mdelay(200);
154 +}
155 +
156 +static int __init bcm63xx_register_pcie(void)
157 +{
158 +       u32 val;
159 +
160 +       bcm63xx_reset_pcie();
161 +
162 +       /* configure the PCIe bridge */
163 +       val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
164 +       val |= OPT1_RD_BE_OPT_EN;
165 +       val |= OPT1_RD_REPLY_BE_FIX_EN;
166 +       val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
167 +       val |= OPT1_L1_INT_STATUS_MASK_POL;
168 +       bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
169 +
170 +       /* setup the interrupts */
171 +       val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
172 +       val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
173 +       bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
174 +
175 +       val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
176 +       /* enable credit checking and error checking */
177 +       val |= OPT2_TX_CREDIT_CHK_EN;
178 +       val |= OPT2_UBUS_UR_DECODE_DIS;
179 +
180 +       /* set device bus/func for the pcie device */
181 +       val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
182 +       val |= OPT2_CFG_TYPE1_BD_SEL;
183 +       bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
184 +
185 +       /* setup class code as bridge */
186 +       val = bcm_pcie_readl(PCIE_IDVAL3_REG);
187 +       val &= ~IDVAL3_CLASS_CODE_MASK;
188 +       val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
189 +       bcm_pcie_writel(val, PCIE_IDVAL3_REG);
190 +
191 +       /* disable bar1 size */
192 +       val = bcm_pcie_readl(PCIE_CONFIG2_REG);
193 +       val &= ~CONFIG2_BAR1_SIZE_MASK;
194 +       bcm_pcie_writel(val, PCIE_CONFIG2_REG);
195 +
196 +       /* set bar0 to little endian */
197 +       val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
198 +       val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
199 +       val |= BASEMASK_REMAP_EN;
200 +       bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
201 +
202 +       val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
203 +       bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
204 +
205 +       register_pci_controller(&bcm63xx_pcie_controller);
206 +
207 +       return 0;
208 +}
209 +
210  static int __init bcm63xx_register_pci(void)
211  {
212         unsigned int mem_size;
213 @@ -211,6 +321,8 @@ static int __init bcm63xx_register_pci(v
214  int __init bcm63xx_pci_register(void)
215  {
216         switch (bcm63xx_get_cpu_id()) {
217 +       case BCM6328_CPU_ID:
218 +               return bcm63xx_register_pcie();
219         case BCM6348_CPU_ID:
220         case BCM6358_CPU_ID:
221         case BCM6368_CPU_ID:
222 --- a/arch/mips/pci/pci-bcm63xx.h
223 +++ b/arch/mips/pci/pci-bcm63xx.h
224 @@ -13,11 +13,16 @@
225   */
226  #define CARDBUS_PCI_IDSEL      0x8
227  
228 +
229 +#define PCIE_BUS_BRIDGE                0
230 +#define PCIE_BUS_DEVICE                1
231 +
232  /*
233   * defined in ops-bcm63xx.c
234   */
235  extern struct pci_ops bcm63xx_pci_ops;
236  extern struct pci_ops bcm63xx_cb_ops;
237 +extern struct pci_ops bcm63xx_pcie_ops;
238  
239  /*
240   * defined in pci-bcm63xx.c