162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Marvell 88SE64xx/88SE94xx register IO interface 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2007 Red Hat, Inc. 662306a36Sopenharmony_ci * Copyright 2008 Marvell. <kewei@marvell.com> 762306a36Sopenharmony_ci * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com> 862306a36Sopenharmony_ci*/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef _MV_CHIPS_H_ 1262306a36Sopenharmony_ci#define _MV_CHIPS_H_ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define mr32(reg) readl(regs + reg) 1562306a36Sopenharmony_ci#define mw32(reg, val) writel((val), regs + reg) 1662306a36Sopenharmony_ci#define mw32_f(reg, val) do { \ 1762306a36Sopenharmony_ci mw32(reg, val); \ 1862306a36Sopenharmony_ci mr32(reg); \ 1962306a36Sopenharmony_ci } while (0) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define iow32(reg, val) outl(val, (unsigned long)(regs + reg)) 2262306a36Sopenharmony_ci#define ior32(reg) inl((unsigned long)(regs + reg)) 2362306a36Sopenharmony_ci#define iow16(reg, val) outw((unsigned long)(val, regs + reg)) 2462306a36Sopenharmony_ci#define ior16(reg) inw((unsigned long)(regs + reg)) 2562306a36Sopenharmony_ci#define iow8(reg, val) outb((unsigned long)(val, regs + reg)) 2662306a36Sopenharmony_ci#define ior8(reg) inb((unsigned long)(regs + reg)) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic inline u32 mvs_cr32(struct mvs_info *mvi, u32 addr) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 3162306a36Sopenharmony_ci mw32(MVS_CMD_ADDR, addr); 3262306a36Sopenharmony_ci return mr32(MVS_CMD_DATA); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic inline void mvs_cw32(struct mvs_info *mvi, u32 addr, u32 val) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 3862306a36Sopenharmony_ci mw32(MVS_CMD_ADDR, addr); 3962306a36Sopenharmony_ci mw32(MVS_CMD_DATA, val); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic inline u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 4562306a36Sopenharmony_ci return (port < 4) ? mr32(MVS_P0_SER_CTLSTAT + port * 4) : 4662306a36Sopenharmony_ci mr32(MVS_P4_SER_CTLSTAT + (port - 4) * 4); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic inline void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 5262306a36Sopenharmony_ci if (port < 4) 5362306a36Sopenharmony_ci mw32(MVS_P0_SER_CTLSTAT + port * 4, val); 5462306a36Sopenharmony_ci else 5562306a36Sopenharmony_ci mw32(MVS_P4_SER_CTLSTAT + (port - 4) * 4, val); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic inline u32 mvs_read_port(struct mvs_info *mvi, u32 off, 5962306a36Sopenharmony_ci u32 off2, u32 port) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci void __iomem *regs = mvi->regs + off; 6262306a36Sopenharmony_ci void __iomem *regs2 = mvi->regs + off2; 6362306a36Sopenharmony_ci return (port < 4) ? readl(regs + port * 8) : 6462306a36Sopenharmony_ci readl(regs2 + (port - 4) * 8); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic inline void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2, 6862306a36Sopenharmony_ci u32 port, u32 val) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci void __iomem *regs = mvi->regs + off; 7162306a36Sopenharmony_ci void __iomem *regs2 = mvi->regs + off2; 7262306a36Sopenharmony_ci if (port < 4) 7362306a36Sopenharmony_ci writel(val, regs + port * 8); 7462306a36Sopenharmony_ci else 7562306a36Sopenharmony_ci writel(val, regs2 + (port - 4) * 8); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic inline u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci return mvs_read_port(mvi, MVS_P0_CFG_DATA, 8162306a36Sopenharmony_ci MVS_P4_CFG_DATA, port); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline void mvs_write_port_cfg_data(struct mvs_info *mvi, 8562306a36Sopenharmony_ci u32 port, u32 val) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci mvs_write_port(mvi, MVS_P0_CFG_DATA, 8862306a36Sopenharmony_ci MVS_P4_CFG_DATA, port, val); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic inline void mvs_write_port_cfg_addr(struct mvs_info *mvi, 9262306a36Sopenharmony_ci u32 port, u32 addr) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci mvs_write_port(mvi, MVS_P0_CFG_ADDR, 9562306a36Sopenharmony_ci MVS_P4_CFG_ADDR, port, addr); 9662306a36Sopenharmony_ci mdelay(10); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return mvs_read_port(mvi, MVS_P0_VSR_DATA, 10262306a36Sopenharmony_ci MVS_P4_VSR_DATA, port); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic inline void mvs_write_port_vsr_data(struct mvs_info *mvi, 10662306a36Sopenharmony_ci u32 port, u32 val) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci mvs_write_port(mvi, MVS_P0_VSR_DATA, 10962306a36Sopenharmony_ci MVS_P4_VSR_DATA, port, val); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic inline void mvs_write_port_vsr_addr(struct mvs_info *mvi, 11362306a36Sopenharmony_ci u32 port, u32 addr) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci mvs_write_port(mvi, MVS_P0_VSR_ADDR, 11662306a36Sopenharmony_ci MVS_P4_VSR_ADDR, port, addr); 11762306a36Sopenharmony_ci mdelay(10); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic inline u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return mvs_read_port(mvi, MVS_P0_INT_STAT, 12362306a36Sopenharmony_ci MVS_P4_INT_STAT, port); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline void mvs_write_port_irq_stat(struct mvs_info *mvi, 12762306a36Sopenharmony_ci u32 port, u32 val) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci mvs_write_port(mvi, MVS_P0_INT_STAT, 13062306a36Sopenharmony_ci MVS_P4_INT_STAT, port, val); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic inline u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci return mvs_read_port(mvi, MVS_P0_INT_MASK, 13662306a36Sopenharmony_ci MVS_P4_INT_MASK, port); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic inline void mvs_write_port_irq_mask(struct mvs_info *mvi, 14162306a36Sopenharmony_ci u32 port, u32 val) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci mvs_write_port(mvi, MVS_P0_INT_MASK, 14462306a36Sopenharmony_ci MVS_P4_INT_MASK, port, val); 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic inline void mvs_phy_hacks(struct mvs_info *mvi) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci u32 tmp; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci tmp = mvs_cr32(mvi, CMD_PHY_TIMER); 15262306a36Sopenharmony_ci tmp &= ~(1 << 9); 15362306a36Sopenharmony_ci tmp |= (1 << 10); 15462306a36Sopenharmony_ci mvs_cw32(mvi, CMD_PHY_TIMER, tmp); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* enable retry 127 times */ 15762306a36Sopenharmony_ci mvs_cw32(mvi, CMD_SAS_CTL1, 0x7f7f); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* extend open frame timeout to max */ 16062306a36Sopenharmony_ci tmp = mvs_cr32(mvi, CMD_SAS_CTL0); 16162306a36Sopenharmony_ci tmp &= ~0xffff; 16262306a36Sopenharmony_ci tmp |= 0x3fff; 16362306a36Sopenharmony_ci mvs_cw32(mvi, CMD_SAS_CTL0, tmp); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci mvs_cw32(mvi, CMD_WD_TIMER, 0x7a0000); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /* not to halt for different port op during wideport link change */ 16862306a36Sopenharmony_ci mvs_cw32(mvi, CMD_APP_ERR_CONFIG, 0xffefbf7d); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic inline void mvs_int_sata(struct mvs_info *mvi) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci u32 tmp; 17462306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 17562306a36Sopenharmony_ci tmp = mr32(MVS_INT_STAT_SRS_0); 17662306a36Sopenharmony_ci if (tmp) 17762306a36Sopenharmony_ci mw32(MVS_INT_STAT_SRS_0, tmp); 17862306a36Sopenharmony_ci MVS_CHIP_DISP->clear_active_cmds(mvi); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic inline void mvs_int_full(struct mvs_info *mvi) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 18462306a36Sopenharmony_ci u32 tmp, stat; 18562306a36Sopenharmony_ci int i; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci stat = mr32(MVS_INT_STAT); 18862306a36Sopenharmony_ci mvs_int_rx(mvi, false); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci for (i = 0; i < mvi->chip->n_phy; i++) { 19162306a36Sopenharmony_ci tmp = (stat >> i) & (CINT_PORT | CINT_PORT_STOPPED); 19262306a36Sopenharmony_ci if (tmp) 19362306a36Sopenharmony_ci mvs_int_port(mvi, i, tmp); 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (stat & CINT_NON_SPEC_NCQ_ERROR) 19762306a36Sopenharmony_ci MVS_CHIP_DISP->non_spec_ncq_error(mvi); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (stat & CINT_SRS) 20062306a36Sopenharmony_ci mvs_int_sata(mvi); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci mw32(MVS_INT_STAT, stat); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic inline void mvs_start_delivery(struct mvs_info *mvi, u32 tx) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 20862306a36Sopenharmony_ci mw32(MVS_TX_PROD_IDX, tx); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic inline u32 mvs_rx_update(struct mvs_info *mvi) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci void __iomem *regs = mvi->regs; 21462306a36Sopenharmony_ci return mr32(MVS_RX_CONS_IDX); 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic inline u32 mvs_get_prd_size(void) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci return sizeof(struct mvs_prd); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic inline u32 mvs_get_prd_count(void) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci return MAX_SG_ENTRY; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic inline void mvs_show_pcie_usage(struct mvs_info *mvi) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci u16 link_stat, link_spd; 23062306a36Sopenharmony_ci const char *spd[] = { 23162306a36Sopenharmony_ci "UnKnown", 23262306a36Sopenharmony_ci "2.5", 23362306a36Sopenharmony_ci "5.0", 23462306a36Sopenharmony_ci }; 23562306a36Sopenharmony_ci if (mvi->flags & MVF_FLAG_SOC || mvi->id > 0) 23662306a36Sopenharmony_ci return; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci pci_read_config_word(mvi->pdev, PCR_LINK_STAT, &link_stat); 23962306a36Sopenharmony_ci link_spd = (link_stat & PLS_LINK_SPD) >> PLS_LINK_SPD_OFFS; 24062306a36Sopenharmony_ci if (link_spd >= 3) 24162306a36Sopenharmony_ci link_spd = 0; 24262306a36Sopenharmony_ci dev_printk(KERN_INFO, mvi->dev, 24362306a36Sopenharmony_ci "mvsas: PCI-E x%u, Bandwidth Usage: %s Gbps\n", 24462306a36Sopenharmony_ci (link_stat & PLS_NEG_LINK_WD) >> PLS_NEG_LINK_WD_OFFS, 24562306a36Sopenharmony_ci spd[link_spd]); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic inline u32 mvs_hw_max_link_rate(void) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci return MAX_LINK_RATE; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci#endif /* _MV_CHIPS_H_ */ 25462306a36Sopenharmony_ci 255