18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Broadcom specific AMBA 38c2ecf20Sopenharmony_ci * ChipCommon B Unit driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2014, Hauke Mehrtens <hauke@hauke-m.de> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "bcma_private.h" 118c2ecf20Sopenharmony_ci#include <linux/export.h> 128c2ecf20Sopenharmony_ci#include <linux/bcma/bcma.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask, 158c2ecf20Sopenharmony_ci u32 value, int timeout) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci unsigned long deadline = jiffies + timeout; 188c2ecf20Sopenharmony_ci u32 val; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci do { 218c2ecf20Sopenharmony_ci val = readl(addr); 228c2ecf20Sopenharmony_ci if ((val & mask) == value) 238c2ecf20Sopenharmony_ci return true; 248c2ecf20Sopenharmony_ci cpu_relax(); 258c2ecf20Sopenharmony_ci udelay(10); 268c2ecf20Sopenharmony_ci } while (!time_after_eq(jiffies, deadline)); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci bcma_err(bus, "Timeout waiting for register %p\n", addr); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci return false; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_civoid bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct bcma_bus *bus = ccb->core->bus; 368c2ecf20Sopenharmony_ci void __iomem *mii = ccb->mii; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci writel(offset, mii + BCMA_CCB_MII_MNG_CTL); 398c2ecf20Sopenharmony_ci bcma_wait_reg(bus, mii + BCMA_CCB_MII_MNG_CTL, 0x0100, 0x0000, 100); 408c2ecf20Sopenharmony_ci writel(value, mii + BCMA_CCB_MII_MNG_CMD_DATA); 418c2ecf20Sopenharmony_ci bcma_wait_reg(bus, mii + BCMA_CCB_MII_MNG_CTL, 0x0100, 0x0000, 100); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bcma_chipco_b_mii_write); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciint bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci if (ccb->setup_done) 488c2ecf20Sopenharmony_ci return 0; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ccb->setup_done = 1; 518c2ecf20Sopenharmony_ci ccb->mii = ioremap(ccb->core->addr_s[1], BCMA_CORE_SIZE); 528c2ecf20Sopenharmony_ci if (!ccb->mii) 538c2ecf20Sopenharmony_ci return -ENOMEM; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_civoid bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci if (ccb->mii) 618c2ecf20Sopenharmony_ci iounmap(ccb->mii); 628c2ecf20Sopenharmony_ci} 63