static void bcma_hcd_4716wa(struct bcma_device *dev) { #ifdef CONFIG_BCMA_DRIVER_MIPS /* Work around for 4716 failures. */ if (dev->bus->chipinfo.id == 0x4716) { u32 tmp; tmp = bcma_cpu_clock(&dev->bus->drv_mips); if (tmp >= 480000000) tmp = 0x1846b; /* set CDR to 0x11(fast) */ else if (tmp == 453000000) tmp = 0x1046b; /* set CDR to 0x10(slow) */ else tmp = 0; /* Change Shim mdio control reg to fix host not acking at * high frequencies */ if (tmp) { bcma_write32(dev, 0x524, 0x1); /* write sel to enable */ udelay(500); bcma_write32(dev, 0x524, tmp); udelay(500); bcma_write32(dev, 0x524, 0x4ab); udelay(500); bcma_read32(dev, 0x528); bcma_write32(dev, 0x528, 0x80000000); } } #endif /* CONFIG_BCMA_DRIVER_MIPS */ }
void si_pmu_res_init(struct si_pub *sih) { struct bcma_device *core; u32 min_mask = 0, max_mask = 0; /* */ core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); /* */ si_pmu_res_masks(sih, &min_mask, &max_mask); /* */ /* */ if (max_mask) bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask); /* */ if (min_mask) bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask); /* */ mdelay(2); }
static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, uint *val) { uint mdiodata; uint i = 0; uint pcie_serdes_spinwait = 10; /* enable mdio access to SERDES */ bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); if (ai_get_buscorerev(pi->sih) >= 10) { /* new serdes is slower in rw, * using two layers of reg address mapping */ if (!pcie_mdiosetblock(pi, physmedia)) return 1; mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | (regaddr << MDIODATA_REGADDR_SHF)); pcie_serdes_spinwait *= 20; } else { mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | (regaddr << MDIODATA_REGADDR_SHF_OLD)); } if (!write) mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); else mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val); bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); pr28829_delay(); /* retry till the transaction is complete */ while (i < pcie_serdes_spinwait) { if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & MDIOCTL_ACCESS_DONE) { if (!write) { pr28829_delay(); *val = (bcma_read32(pi->core, PCIEREGOFFS(mdiodata)) & MDIODATA_MASK); } /* Disable mdio access to SERDES */ bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 0; } udelay(1000); i++; } /* Timed out. Disable mdio access to SERDES. */ bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 1; }
static int pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, uint *val) { uint mdiodata; uint i = 0; uint pcie_serdes_spinwait = 10; bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); if (ai_get_buscorerev(pi->sih) >= 10) { if (!pcie_mdiosetblock(pi, physmedia)) return 1; mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | (regaddr << MDIODATA_REGADDR_SHF)); pcie_serdes_spinwait *= 20; } else { mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | (regaddr << MDIODATA_REGADDR_SHF_OLD)); } if (!write) mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); else mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val); bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); pr28829_delay(); while (i < pcie_serdes_spinwait) { if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & MDIOCTL_ACCESS_DONE) { if (!write) { pr28829_delay(); *val = (bcma_read32(pi->core, PCIEREGOFFS(mdiodata)) & MDIODATA_MASK); } bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 0; } udelay(1000); i++; } bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); return 1; }
static u16 bcma_mdio_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg) { struct bcma_device *core; u16 phy_access_addr; u16 phy_ctl_addr; u32 tmp; BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK); BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK); BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT); BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK); BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT); BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE); BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START); BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK); BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK); BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT); BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE); if (bgmac->bcma.core->id.id == BCMA_CORE_4706_MAC_GBIT) { core = bgmac->bcma.core->bus->drv_gmac_cmn.core; phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS; phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL; } else { core = bgmac->bcma.core; phy_access_addr = BGMAC_PHY_ACCESS; phy_ctl_addr = BGMAC_PHY_CNTL; } tmp = bcma_read32(core, phy_ctl_addr); tmp &= ~BGMAC_PC_EPA_MASK; tmp |= phyaddr; bcma_write32(core, phy_ctl_addr, tmp); tmp = BGMAC_PA_START; tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT; tmp |= reg << BGMAC_PA_REG_SHIFT; bcma_write32(core, phy_access_addr, tmp); if (!bcma_mdio_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) { dev_err(&core->dev, "Reading PHY %d register 0x%X failed\n", phyaddr, reg); return 0xffff; } return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK; }
u32 si_pmu_measure_alpclk(struct si_pub *sih) { struct si_info *sii = container_of(sih, struct si_info, pub); struct bcma_device *core; u32 alp_khz; if (ai_get_pmurev(sih) < 10) return 0; /* Remember original core before switch to chipc */ core = sii->icbus->drv_cc.core; if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) { u32 ilp_ctr, alp_hz; /* * Enable the reg to measure the freq, * in case it was disabled before */ bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); /* Delay for well over 4 ILP clocks */ udelay(1000); /* Read the latched number of ALP ticks per 4 ILP ticks */ ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) & PMU_XTALFREQ_REG_ILPCTR_MASK; /* * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT * bit to save power */ bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0); /* Calculate ALP frequency */ alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; /* * Round to nearest 100KHz, and at * the same time convert to KHz */ alp_khz = (alp_hz + 50000) / 100000 * 100; } else alp_khz = 0; return alp_khz; }
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) { uint mdiodata, i = 0; uint pcie_serdes_spinwait = 200; mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | (blk << 4)); bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); pr28829_delay(); /* retry till the transaction is complete */ while (i < pcie_serdes_spinwait) { if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & MDIOCTL_ACCESS_DONE) break; udelay(1000); i++; } if (i >= pcie_serdes_spinwait) return false; return true; }
void __init arch_init_irq(void) { #ifdef CONFIG_BCM47XX_BCMA if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31); /* * the kernel reads the timer irq from some register and thinks * it's #5, but we offset it by 2 and route to #7 */ cp0_compare_irq = 7; } #endif mips_cpu_irq_init(); if (cpu_has_vint) { pr_info("Setting up vectored interrupts\n"); set_vi_handler(2, bcm47xx_hw2_irqdispatch); set_vi_handler(3, bcm47xx_hw3_irqdispatch); set_vi_handler(4, bcm47xx_hw4_irqdispatch); set_vi_handler(5, bcm47xx_hw5_irqdispatch); set_vi_handler(6, bcm47xx_hw6_irqdispatch); set_vi_handler(7, bcm47xx_hw7_irqdispatch); } }
u32 si_pmu_measure_alpclk(struct si_pub *sih) { struct bcma_device *core; u32 alp_khz; if (ai_get_pmurev(sih) < 10) return 0; /* */ core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) { u32 ilp_ctr, alp_hz; /* */ bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT); /* */ udelay(1000); /* */ ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) & PMU_XTALFREQ_REG_ILPCTR_MASK; /* */ bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0); /* */ alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4; /* */ alp_khz = (alp_hz + 50000) / 100000 * 100; } else alp_khz = 0; return alp_khz; }
static uint pcie_writereg(struct bcma_device *core, uint addrtype, uint offset, uint val) { switch (addrtype) { case PCIE_CONFIGREGS: bcma_write32(core, PCIEREGOFFS(configaddr), offset); bcma_write32(core, PCIEREGOFFS(configdata), val); break; case PCIE_PCIEREGS: bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); bcma_write32(core, PCIEREGOFFS(pcieinddata), val); break; default: break; } return 0; }
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */ static int bcma_mdio_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value) { struct bcma_device *core; u16 phy_access_addr; u16 phy_ctl_addr; u32 tmp; if (bgmac->bcma.core->id.id == BCMA_CORE_4706_MAC_GBIT) { core = bgmac->bcma.core->bus->drv_gmac_cmn.core; phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS; phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL; } else { core = bgmac->bcma.core; phy_access_addr = BGMAC_PHY_ACCESS; phy_ctl_addr = BGMAC_PHY_CNTL; } tmp = bcma_read32(core, phy_ctl_addr); tmp &= ~BGMAC_PC_EPA_MASK; tmp |= phyaddr; bcma_write32(core, phy_ctl_addr, tmp); bcma_write32(bgmac->bcma.core, BGMAC_INT_STATUS, BGMAC_IS_MDIO); if (bcma_read32(bgmac->bcma.core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO) dev_warn(&core->dev, "Error setting MDIO int\n"); tmp = BGMAC_PA_START; tmp |= BGMAC_PA_WRITE; tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT; tmp |= reg << BGMAC_PA_REG_SHIFT; tmp |= value; bcma_write32(core, phy_access_addr, tmp); if (!bcma_mdio_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) { dev_err(&core->dev, "Writing to PHY %d register 0x%X failed\n", phyaddr, reg); return -ETIMEDOUT; } return 0; }
/* ***** Register Access API */ static uint pcie_readreg(struct bcma_device *core, uint addrtype, uint offset) { uint retval = 0xFFFFFFFF; switch (addrtype) { case PCIE_CONFIGREGS: bcma_write32(core, PCIEREGOFFS(configaddr), offset); (void)bcma_read32(core, PCIEREGOFFS(configaddr)); retval = bcma_read32(core, PCIEREGOFFS(configdata)); break; case PCIE_PCIEREGS: bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr)); retval = bcma_read32(core, PCIEREGOFFS(pcieinddata)); break; } return retval; }
static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) { u32 val; /* * Delay after PHY initialized to ensure HC is ready to be configured */ usleep_range(1000, 2000); /* Set packet buffer OUT threshold */ val = bcma_read32(dev, 0x94); val &= 0xffff; val |= 0x80 << 16; bcma_write32(dev, 0x94, val); /* Enable break memory transfer */ val = bcma_read32(dev, 0x9c); val |= 1; bcma_write32(dev, 0x9c, val); }
void __init arch_init_irq(void) { #ifdef CONFIG_BCM47XX_BCMA if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31); /* * the kernel reads the timer irq from some register and thinks * it's #5, but we offset it by 2 and route to #7 */ cp0_compare_irq = 7; } #endif mips_cpu_irq_init(); }
static void bcma_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value) { bcma_write32(bgmac->bcma.core, offset, value); }
void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid) { u32 tmp = 0; struct bcma_device *core; /* */ core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); switch (ai_get_chip_id(sih)) { case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: if (spuravoid == 1) { bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL0); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x11500010); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL1); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x000C0C06); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL2); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x0F600a08); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL3); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x00000000); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL4); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x2001E920); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL5); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x88888815); } else { bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL0); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x11100010); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL1); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x000c0c06); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL2); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x03000a08); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL3); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x00000000); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL4); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x200005c0); bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr), PMU1_PLL0_PLLCTL5); bcma_write32(core, CHIPCREGOFFS(pllcontrol_data), 0x88888815); } tmp = 1 << 10; break; default: /* */ return; } bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp); }
/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ static void bcma_hcd_init_chip_mips(struct bcma_device *dev) { u32 tmp; /* * USB 2.0 special considerations: * * 1. Since the core supports both OHCI and EHCI functions, it must * only be reset once. * * 2. In addition to the standard SI reset sequence, the Host Control * Register must be programmed to bring the USB core and various * phy components out of reset. */ if (!bcma_core_is_enabled(dev)) { bcma_core_enable(dev, 0); mdelay(10); if (dev->id.rev >= 5) { /* Enable Misc PLL */ tmp = bcma_read32(dev, 0x1e0); tmp |= 0x100; bcma_write32(dev, 0x1e0, tmp); if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100)) printk(KERN_EMERG "Failed to enable misc PPL!\n"); /* Take out of resets */ bcma_write32(dev, 0x200, 0x4ff); udelay(25); bcma_write32(dev, 0x200, 0x6ff); udelay(25); /* Make sure digital and AFE are locked in USB PHY */ bcma_write32(dev, 0x524, 0x6b); udelay(50); tmp = bcma_read32(dev, 0x524); udelay(50); bcma_write32(dev, 0x524, 0xab); udelay(50); tmp = bcma_read32(dev, 0x524); udelay(50); bcma_write32(dev, 0x524, 0x2b); udelay(50); tmp = bcma_read32(dev, 0x524); udelay(50); bcma_write32(dev, 0x524, 0x10ab); udelay(50); tmp = bcma_read32(dev, 0x524); if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) { tmp = bcma_read32(dev, 0x528); printk(KERN_EMERG "USB20H mdio_rddata 0x%08x\n", tmp); } bcma_write32(dev, 0x528, 0x80000000); tmp = bcma_read32(dev, 0x314); udelay(265); bcma_write32(dev, 0x200, 0x7ff); udelay(10); /* Take USB and HSIC out of non-driving modes */ bcma_write32(dev, 0x510, 0); } else { bcma_write32(dev, 0x200, 0x7ff); udelay(1); } bcma_hcd_4716wa(dev); } }
static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset, u32 value) { bcma_write32(b53spi->core, offset, value); }
static void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value) { bcma_write32(dev->bdev, offset, value); }