Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.3-rc2 238 lines 5.7 kB view raw
1/* 2 * Broadcom specific AMBA 3 * PCI Core 4 * 5 * Copyright 2005, Broadcom Corporation 6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 7 * 8 * Licensed under the GNU/GPL. See COPYING for details. 9 */ 10 11#include "bcma_private.h" 12#include <linux/export.h> 13#include <linux/bcma/bcma.h> 14 15/************************************************** 16 * R/W ops. 17 **************************************************/ 18 19static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) 20{ 21 pcicore_write32(pc, 0x130, address); 22 pcicore_read32(pc, 0x130); 23 return pcicore_read32(pc, 0x134); 24} 25 26#if 0 27static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) 28{ 29 pcicore_write32(pc, 0x130, address); 30 pcicore_read32(pc, 0x130); 31 pcicore_write32(pc, 0x134, data); 32} 33#endif 34 35static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) 36{ 37 const u16 mdio_control = 0x128; 38 const u16 mdio_data = 0x12C; 39 u32 v; 40 int i; 41 42 v = (1 << 30); /* Start of Transaction */ 43 v |= (1 << 28); /* Write Transaction */ 44 v |= (1 << 17); /* Turnaround */ 45 v |= (0x1F << 18); 46 v |= (phy << 4); 47 pcicore_write32(pc, mdio_data, v); 48 49 udelay(10); 50 for (i = 0; i < 200; i++) { 51 v = pcicore_read32(pc, mdio_control); 52 if (v & 0x100 /* Trans complete */) 53 break; 54 msleep(1); 55 } 56} 57 58static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) 59{ 60 const u16 mdio_control = 0x128; 61 const u16 mdio_data = 0x12C; 62 int max_retries = 10; 63 u16 ret = 0; 64 u32 v; 65 int i; 66 67 v = 0x80; /* Enable Preamble Sequence */ 68 v |= 0x2; /* MDIO Clock Divisor */ 69 pcicore_write32(pc, mdio_control, v); 70 71 if (pc->core->id.rev >= 10) { 72 max_retries = 200; 73 bcma_pcie_mdio_set_phy(pc, device); 74 } 75 76 v = (1 << 30); /* Start of Transaction */ 77 v |= (1 << 29); /* Read Transaction */ 78 v |= (1 << 17); /* Turnaround */ 79 if (pc->core->id.rev < 10) 80 v |= (u32)device << 22; 81 v |= (u32)address << 18; 82 pcicore_write32(pc, mdio_data, v); 83 /* Wait for the device to complete the transaction */ 84 udelay(10); 85 for (i = 0; i < max_retries; i++) { 86 v = pcicore_read32(pc, mdio_control); 87 if (v & 0x100 /* Trans complete */) { 88 udelay(10); 89 ret = pcicore_read32(pc, mdio_data); 90 break; 91 } 92 msleep(1); 93 } 94 pcicore_write32(pc, mdio_control, 0); 95 return ret; 96} 97 98static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, 99 u8 address, u16 data) 100{ 101 const u16 mdio_control = 0x128; 102 const u16 mdio_data = 0x12C; 103 int max_retries = 10; 104 u32 v; 105 int i; 106 107 v = 0x80; /* Enable Preamble Sequence */ 108 v |= 0x2; /* MDIO Clock Divisor */ 109 pcicore_write32(pc, mdio_control, v); 110 111 if (pc->core->id.rev >= 10) { 112 max_retries = 200; 113 bcma_pcie_mdio_set_phy(pc, device); 114 } 115 116 v = (1 << 30); /* Start of Transaction */ 117 v |= (1 << 28); /* Write Transaction */ 118 v |= (1 << 17); /* Turnaround */ 119 if (pc->core->id.rev < 10) 120 v |= (u32)device << 22; 121 v |= (u32)address << 18; 122 v |= data; 123 pcicore_write32(pc, mdio_data, v); 124 /* Wait for the device to complete the transaction */ 125 udelay(10); 126 for (i = 0; i < max_retries; i++) { 127 v = pcicore_read32(pc, mdio_control); 128 if (v & 0x100 /* Trans complete */) 129 break; 130 msleep(1); 131 } 132 pcicore_write32(pc, mdio_control, 0); 133} 134 135/************************************************** 136 * Workarounds. 137 **************************************************/ 138 139static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) 140{ 141 return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; 142} 143 144static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) 145{ 146 const u8 serdes_pll_device = 0x1D; 147 const u8 serdes_rx_device = 0x1F; 148 u16 tmp; 149 150 bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, 151 bcma_pcicore_polarity_workaround(pc)); 152 tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); 153 if (tmp & 0x4000) 154 bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); 155} 156 157/************************************************** 158 * Init. 159 **************************************************/ 160 161static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) 162{ 163 bcma_pcicore_serdes_workaround(pc); 164} 165 166static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) 167{ 168 struct bcma_bus *bus = pc->core->bus; 169 u16 chipid_top; 170 171 chipid_top = (bus->chipinfo.id & 0xFF00); 172 if (chipid_top != 0x4700 && 173 chipid_top != 0x5300) 174 return false; 175 176#ifdef CONFIG_SSB_DRIVER_PCICORE 177 if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI) 178 return false; 179#endif /* CONFIG_SSB_DRIVER_PCICORE */ 180 181#if 0 182 /* TODO: on BCMA we use address from EROM instead of magic formula */ 183 u32 tmp; 184 return !mips_busprobe32(tmp, (bus->mmio + 185 (pc->core->core_index * BCMA_CORE_SIZE))); 186#endif 187 188 return true; 189} 190 191void bcma_core_pci_init(struct bcma_drv_pci *pc) 192{ 193 if (pc->setup_done) 194 return; 195 196 if (bcma_core_pci_is_in_hostmode(pc)) { 197#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE 198 bcma_core_pci_hostmode_init(pc); 199#else 200 pr_err("Driver compiled without support for hostmode PCI\n"); 201#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ 202 } else { 203 bcma_core_pci_clientmode_init(pc); 204 } 205 206 pc->setup_done = true; 207} 208 209int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, 210 bool enable) 211{ 212 struct pci_dev *pdev = pc->core->bus->host_pci; 213 u32 coremask, tmp; 214 int err = 0; 215 216 if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { 217 /* This bcma device is not on a PCI host-bus. So the IRQs are 218 * not routed through the PCI core. 219 * So we must not enable routing through the PCI core. */ 220 goto out; 221 } 222 223 err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); 224 if (err) 225 goto out; 226 227 coremask = BIT(core->core_index) << 8; 228 if (enable) 229 tmp |= coremask; 230 else 231 tmp &= ~coremask; 232 233 err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); 234 235out: 236 return err; 237} 238EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);