^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Marvell 88SE94xx hardware specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2007 Red Hat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2008 Marvell. <kewei@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "mv_sas.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "mv_94xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "mv_chips.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct mvs_phy *phy = &mvi->phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u32 phy_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) reg = mvs_read_port_vsr_data(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) phy_status = ((reg & 0x3f0000) >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) switch (phy_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) phy->phy_type |= PORT_TYPE_SAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) case 0x1d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) phy->phy_type |= PORT_TYPE_SATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void set_phy_tuning(struct mvs_info *mvi, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct phy_tuning phy_tuning)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 tmp, setting_0 = 0, setting_1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* Remap information for B0 chip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * R0Ch -> R118h[15:0] (Adapted DFE F3 - F5 coefficient)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * R0Dh -> R118h[31:16] (Generation 1 Setting 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * R0Eh -> R11Ch[15:0] (Generation 1 Setting 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * R0Fh -> R11Ch[31:16] (Generation 2 Setting 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * R10h -> R120h[15:0] (Generation 2 Setting 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * R11h -> R120h[31:16] (Generation 3 Setting 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * R12h -> R124h[15:0] (Generation 3 Setting 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * R13h -> R124h[31:16] (Generation 4 Setting 0 (Reserved))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* A0 has a different set of registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (mvi->pdev->revision == VANIR_A0_REV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* loop 3 times, set Gen 1, Gen 2, Gen 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) switch (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) setting_0 = GENERATION_1_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) setting_1 = GENERATION_1_2_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) setting_0 = GENERATION_1_2_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) setting_1 = GENERATION_2_3_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) setting_0 = GENERATION_2_3_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) setting_1 = GENERATION_3_4_SETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Transmitter Emphasis Enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Transmitter Emphasis Amplitude
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Transmitter Amplitude
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) mvs_write_port_vsr_addr(mvi, phy_id, setting_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) tmp &= ~(0xFBE << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) tmp |= (((phy_tuning.trans_emp_en << 11) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) (phy_tuning.trans_emp_amp << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) (phy_tuning.trans_amp << 1)) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) mvs_write_port_vsr_data(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* Set Transmitter Amplitude Adjust */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mvs_write_port_vsr_addr(mvi, phy_id, setting_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) tmp &= ~(0xC000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) tmp |= (phy_tuning.trans_amp_adj << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) mvs_write_port_vsr_data(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct ffe_control ffe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Don't run this if A0/B0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if ((mvi->pdev->revision == VANIR_A0_REV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) || (mvi->pdev->revision == VANIR_B0_REV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* FFE Resistor and Capacitor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* R10Ch DFE Resolution Control/Squelch and FFE Setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * FFE_FORCE [7]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * FFE_RES_SEL [6:4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * FFE_CAP_SEL [3:0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_FFE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) tmp &= ~0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Read from HBA_Info_Page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) tmp |= ((0x1 << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) (ffe.ffe_rss_sel << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) (ffe.ffe_cap_sel << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mvs_write_port_vsr_data(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* R064h PHY Mode Register 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * DFE_DIS 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) tmp &= ~0x40001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Hard coding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* No defines in HBA_Info_Page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) tmp |= (0 << 18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) mvs_write_port_vsr_data(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* R110h DFE F0-F1 Coefficient Control/DFE Update Control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * DFE_UPDATE_EN [11:6]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * DFE_FX_FORCE [5:0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_DFE_UPDATE_CRTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) tmp &= ~0xFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* Hard coding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* No defines in HBA_Info_Page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) tmp |= ((0x3F << 6) | (0x0 << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) mvs_write_port_vsr_data(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* R1A0h Interface and Digital Reference Clock Control/Reserved_50h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * FFE_TRAIN_EN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) mvs_write_port_vsr_addr(mvi, phy_id, VSR_REF_CLOCK_CRTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) tmp &= ~0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Hard coding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* No defines in HBA_Info_Page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) tmp |= (0 << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) mvs_write_port_vsr_data(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*Notice: this function must be called when phy is disabled*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) union reg_phy_cfg phy_cfg, phy_cfg_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) phy_cfg_tmp.v = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) phy_cfg.v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) phy_cfg.u.disable_phy = phy_cfg_tmp.u.disable_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) phy_cfg.u.sas_support = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) phy_cfg.u.sata_support = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) phy_cfg.u.sata_host_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case 0x0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* support 1.5 Gbps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) phy_cfg.u.speed_support = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) phy_cfg.u.snw_3_support = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) phy_cfg.u.tx_lnk_parity = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) phy_cfg.u.tx_spt_phs_lnk_rate = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case 0x1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* support 1.5, 3.0 Gbps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) phy_cfg.u.speed_support = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) phy_cfg.u.tx_spt_phs_lnk_rate = 0x3c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) phy_cfg.u.tx_lgcl_lnk_rate = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) case 0x2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* support 1.5, 3.0, 6.0 Gbps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) phy_cfg.u.speed_support = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) phy_cfg.u.snw_3_support = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) phy_cfg.u.tx_lnk_parity = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) phy_cfg.u.tx_spt_phs_lnk_rate = 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) phy_cfg.u.tx_lgcl_lnk_rate = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) mvs_write_port_vsr_data(mvi, phy_id, phy_cfg.v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void mvs_94xx_config_reg_from_hba(struct mvs_info *mvi, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) temp = (u32)(*(u32 *)&mvi->hba_info_param.phy_tuning[phy_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (temp == 0xFFFFFFFFL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) mvi->hba_info_param.phy_tuning[phy_id].trans_emp_amp = 0x6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) mvi->hba_info_param.phy_tuning[phy_id].trans_amp = 0x1A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mvi->hba_info_param.phy_tuning[phy_id].trans_amp_adj = 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) temp = (u8)(*(u8 *)&mvi->hba_info_param.ffe_ctl[phy_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (temp == 0xFFL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) switch (mvi->pdev->revision) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case VANIR_A0_REV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case VANIR_B0_REV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case VANIR_C0_REV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) case VANIR_C1_REV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) case VANIR_C2_REV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) mvi->hba_info_param.ffe_ctl[phy_id].ffe_rss_sel = 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mvi->hba_info_param.ffe_ctl[phy_id].ffe_cap_sel = 0xC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) temp = (u8)(*(u8 *)&mvi->hba_info_param.phy_rate[phy_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (temp == 0xFFL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*set default phy_rate = 6Gbps*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mvi->hba_info_param.phy_rate[phy_id] = 0x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) set_phy_tuning(mvi, phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) mvi->hba_info_param.phy_tuning[phy_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) set_phy_ffe_tuning(mvi, phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) mvi->hba_info_param.ffe_ctl[phy_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) set_phy_rate(mvi, phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mvi->hba_info_param.phy_rate[phy_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static void mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tmp = mr32(MVS_PCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) tmp |= 1 << (phy_id + PCS_EN_PORT_XMT_SHIFT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) mw32(MVS_PCS, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 delay = 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (hard == MVS_PHY_TUNE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mvs_write_port_cfg_addr(mvi, phy_id, PHYR_SATA_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) tmp = mvs_read_port_cfg_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mvs_write_port_cfg_data(mvi, phy_id, tmp|0x20000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mvs_write_port_cfg_data(mvi, phy_id, tmp|0x100000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) tmp = mvs_read_port_irq_stat(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) tmp &= ~PHYEV_RDY_CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mvs_write_port_irq_stat(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (hard) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) tmp = mvs_read_phy_ctl(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) tmp |= PHY_RST_HARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mvs_write_phy_ctl(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) tmp = mvs_read_phy_ctl(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) delay--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) } while ((tmp & PHY_RST_HARD) && delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mv_dprintk("phy hard reset failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) tmp = mvs_read_phy_ctl(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tmp |= PHY_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) mvs_write_phy_ctl(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void mvs_94xx_phy_disable(struct mvs_info *mvi, u32 phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) mvs_write_port_vsr_data(mvi, phy_id, tmp | 0x00800000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u8 revision = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) revision = mvi->pdev->revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (revision == VANIR_A0_REV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (revision == VANIR_B0_REV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) mvs_write_port_vsr_addr(mvi, phy_id, CMD_APP_MEM_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mvs_write_port_vsr_data(mvi, phy_id, 0x08001006);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) mvs_write_port_vsr_addr(mvi, phy_id, CMD_HOST_RD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) mvs_write_port_vsr_data(mvi, phy_id, 0x0000705f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) tmp = mvs_read_port_vsr_data(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) tmp |= bit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void mvs_94xx_sgpio_init(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) tmp = mr32(MVS_HST_CHIP_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) tmp |= 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) mw32(MVS_HST_CHIP_CONFIG, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) mw32(MVS_SGPIO_CTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) MVS_SGPIO_CTRL_SDOUT_AUTO << MVS_SGPIO_CTRL_SDOUT_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) mw32(MVS_SGPIO_CFG1 + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 8 << MVS_SGPIO_CFG1_LOWA_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 8 << MVS_SGPIO_CFG1_HIA_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 4 << MVS_SGPIO_CFG1_LOWB_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 4 << MVS_SGPIO_CFG1_HIB_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 2 << MVS_SGPIO_CFG1_MAXACTON_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 1 << MVS_SGPIO_CFG1_FORCEACTOFF_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) mw32(MVS_SGPIO_CFG2 + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) (300000 / 100) << MVS_SGPIO_CFG2_CLK_SHIFT | /* 100kHz clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 66 << MVS_SGPIO_CFG2_BLINK_SHIFT /* (66 * 0,121 Hz?)*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) mw32(MVS_SGPIO_CFG0 + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) MVS_SGPIO_CFG0_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MVS_SGPIO_CFG0_BLINKA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MVS_SGPIO_CFG0_BLINKB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* 3*4 data bits / PDU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) (12 - 1) << MVS_SGPIO_CFG0_AUT_BITLEN_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) DEFAULT_SGPIO_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) mw32(MVS_SGPIO_DSRC + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ((mvi->id * 4) + 3) << (8 * 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ((mvi->id * 4) + 2) << (8 * 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ((mvi->id * 4) + 1) << (8 * 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ((mvi->id * 4) + 0) << (8 * 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int mvs_94xx_init(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) u32 tmp, cctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) u8 revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) revision = mvi->pdev->revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) mvs_show_pcie_usage(mvi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (mvi->flags & MVF_FLAG_SOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) tmp = mr32(MVS_PHY_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) tmp &= ~PCTL_PWR_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) tmp |= PCTL_PHY_DSBL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) mw32(MVS_PHY_CTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* Init Chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* make sure RST is set; HBA_RST /should/ have done that for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) cctl = mr32(MVS_CTL) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (cctl & CCTL_RST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) cctl &= ~CCTL_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) mw32_f(MVS_CTL, cctl | CCTL_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (mvi->flags & MVF_FLAG_SOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) tmp = mr32(MVS_PHY_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) tmp &= ~PCTL_PWR_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) tmp |= PCTL_COM_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) tmp &= ~PCTL_PHY_DSBL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tmp |= PCTL_LINK_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mw32(MVS_PHY_CTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) tmp &= ~PCTL_LINK_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) mw32(MVS_PHY_CTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* disable Multiplexing, enable phy implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) mw32(MVS_PORTS_IMP, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (revision == VANIR_A0_REV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mw32(MVS_PA_VSR_ADDR, CMD_CMWK_OOB_DET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) mw32(MVS_PA_VSR_PORT, 0x00018080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (revision == VANIR_A0_REV || revision == VANIR_B0_REV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* set 6G/3G/1.5G, multiplexing, without SSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) mw32(MVS_PA_VSR_PORT, 0x0084d4fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* set 6G/3G/1.5G, multiplexing, with and without SSC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) mw32(MVS_PA_VSR_PORT, 0x0084fffe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (revision == VANIR_B0_REV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) mw32(MVS_PA_VSR_ADDR, CMD_APP_MEM_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) mw32(MVS_PA_VSR_PORT, 0x08001006);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) mw32(MVS_PA_VSR_ADDR, CMD_HOST_RD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) mw32(MVS_PA_VSR_PORT, 0x0000705f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* reset control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) mw32(MVS_PCS, 0); /* MVS_PCS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mw32(MVS_STP_REG_SET_0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mw32(MVS_STP_REG_SET_1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* init phys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) mvs_phy_hacks(mvi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* disable non data frame retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) tmp = mvs_cr32(mvi, CMD_SAS_CTL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if ((revision == VANIR_A0_REV) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) (revision == VANIR_B0_REV) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) (revision == VANIR_C0_REV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) tmp &= ~0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) tmp |= 0x007f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) mvs_cw32(mvi, CMD_SAS_CTL1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* set LED blink when IO*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) mw32(MVS_PA_VSR_ADDR, VSR_PHY_ACT_LED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) tmp = mr32(MVS_PA_VSR_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) tmp &= 0xFFFF00FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) tmp |= 0x00003300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) mw32(MVS_PA_VSR_PORT, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) mw32(MVS_CMD_LIST_LO, mvi->slot_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) mw32(MVS_CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) mw32(MVS_RX_FIS_LO, mvi->rx_fis_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) mw32(MVS_RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) mw32(MVS_TX_LO, mvi->tx_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mw32(MVS_TX_HI, (mvi->tx_dma >> 16) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) mw32(MVS_RX_CFG, MVS_RX_RING_SZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) mw32(MVS_RX_LO, mvi->rx_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) mw32(MVS_RX_HI, (mvi->rx_dma >> 16) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) for (i = 0; i < mvi->chip->n_phy; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) mvs_94xx_phy_disable(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* set phy local SAS address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) cpu_to_le64(mvi->phy[i].dev_sas_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mvs_94xx_enable_xmt(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mvs_94xx_config_reg_from_hba(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mvs_94xx_phy_enable(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) mvs_94xx_phy_reset(mvi, i, PHY_RST_HARD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mvs_94xx_detect_porttype(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (mvi->flags & MVF_FLAG_SOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* set select registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) writel(0x0E008000, regs + 0x000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) writel(0x59000008, regs + 0x004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) writel(0x20, regs + 0x008);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) writel(0x20, regs + 0x00c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) writel(0x20, regs + 0x010);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) writel(0x20, regs + 0x014);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) writel(0x20, regs + 0x018);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) writel(0x20, regs + 0x01c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) for (i = 0; i < mvi->chip->n_phy; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* clear phy int status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) tmp = mvs_read_port_irq_stat(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) tmp &= ~PHYEV_SIG_FIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mvs_write_port_irq_stat(mvi, i, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* set phy int mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) PHYEV_ID_DONE | PHYEV_DCDR_ERR | PHYEV_CRC_ERR ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mvs_write_port_irq_mask(mvi, i, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) mvs_update_phyinfo(mvi, i, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* little endian for open address and command table, etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) cctl = mr32(MVS_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) cctl |= CCTL_ENDIAN_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) cctl &= ~CCTL_ENDIAN_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) cctl |= CCTL_ENDIAN_RSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) mw32_f(MVS_CTL, cctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* reset CMD queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) tmp = mr32(MVS_PCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) tmp |= PCS_CMD_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) tmp &= ~PCS_SELF_CLEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) mw32(MVS_PCS, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * the max count is 0x1ff, while our max slot is 0x200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * it will make count 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (MVS_CHIP_SLOT_SZ > 0x1ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) mw32(MVS_INT_COAL, 0x1ff | COAL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ | COAL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* default interrupt coalescing time is 128us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) tmp = 0x10000 | interrupt_coalescing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) mw32(MVS_INT_COAL_TMOUT, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* ladies and gentlemen, start your engines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) mw32(MVS_TX_CFG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) mw32(MVS_TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) mw32(MVS_RX_CFG, MVS_RX_RING_SZ | RX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* enable CMD/CMPL_Q/RESP mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mw32(MVS_PCS, PCS_SATA_RETRY_2 | PCS_FIS_RX_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) PCS_CMD_EN | PCS_CMD_STOP_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* enable completion queue interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) CINT_DMA_PCIE | CINT_NON_SPEC_NCQ_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) tmp |= CINT_PHY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mw32(MVS_INT_MASK, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) tmp = mvs_cr32(mvi, CMD_LINK_TIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) tmp |= 0xFFFF0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) mvs_cw32(mvi, CMD_LINK_TIMER, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* tune STP performance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) tmp = 0x003F003F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) mvs_cw32(mvi, CMD_PL_TIMER, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /* This can improve expander large block size seq write performance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) tmp = mvs_cr32(mvi, CMD_PORT_LAYER_TIMER1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) tmp |= 0xFFFF007F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) mvs_cw32(mvi, CMD_PORT_LAYER_TIMER1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* change the connection open-close behavior (bit 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * set bit8 to 1 for performance tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) tmp = mvs_cr32(mvi, CMD_SL_MODE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) tmp |= 0x00000300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* set bit0 to 0 to enable retry for no_dest reject case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) tmp &= 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) mvs_cw32(mvi, CMD_SL_MODE0, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* Enable SRS interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mw32(MVS_INT_MASK_SRS_0, 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) mvs_94xx_sgpio_init(mvi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static int mvs_94xx_ioremap(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (!mvs_ioremap(mvi, 2, -1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) mvi->regs_ex = mvi->regs + 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mvi->regs += 0x20000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (mvi->id == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mvi->regs += 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static void mvs_94xx_iounmap(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (mvi->regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) mvi->regs -= 0x20000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (mvi->id == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) mvi->regs -= 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mvs_iounmap(mvi->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static void mvs_94xx_interrupt_enable(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) void __iomem *regs = mvi->regs_ex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) tmp = mr32(MVS_GBL_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) tmp |= (MVS_IRQ_SAS_A | MVS_IRQ_SAS_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) mw32(MVS_GBL_INT_STAT, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) writel(tmp, regs + 0x0C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) writel(tmp, regs + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) writel(tmp, regs + 0x14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) writel(tmp, regs + 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) mw32(MVS_GBL_CTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static void mvs_94xx_interrupt_disable(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) void __iomem *regs = mvi->regs_ex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) tmp = mr32(MVS_GBL_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) tmp &= ~(MVS_IRQ_SAS_A | MVS_IRQ_SAS_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) mw32(MVS_GBL_INT_STAT, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) writel(tmp, regs + 0x0C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) writel(tmp, regs + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) writel(tmp, regs + 0x14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) writel(tmp, regs + 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) mw32(MVS_GBL_CTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static u32 mvs_94xx_isr_status(struct mvs_info *mvi, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) void __iomem *regs = mvi->regs_ex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) u32 stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (!(mvi->flags & MVF_FLAG_SOC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) stat = mr32(MVS_GBL_INT_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!(stat & (MVS_IRQ_SAS_A | MVS_IRQ_SAS_B)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static irqreturn_t mvs_94xx_isr(struct mvs_info *mvi, int irq, u32 stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (((stat & MVS_IRQ_SAS_A) && mvi->id == 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ((stat & MVS_IRQ_SAS_B) && mvi->id == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) mw32_f(MVS_INT_STAT, CINT_DONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) spin_lock(&mvi->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) mvs_int_full(mvi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) spin_unlock(&mvi->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (tmp & 1 << (slot_idx % 32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) mv_printk("command active %08X, slot [%x].\n", tmp, slot_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 1 << (slot_idx % 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) tmp = mvs_cr32(mvi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) MVS_COMMAND_ACTIVE + (slot_idx >> 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) } while (tmp & 1 << (slot_idx % 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (clear_all) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) tmp = mr32(MVS_INT_STAT_SRS_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) mv_dprintk("check SRS 0 %08X.\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) mw32(MVS_INT_STAT_SRS_0, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) tmp = mr32(MVS_INT_STAT_SRS_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) mv_dprintk("check SRS 1 %08X.\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) mw32(MVS_INT_STAT_SRS_1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (reg_set > 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) tmp = mr32(MVS_INT_STAT_SRS_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) tmp = mr32(MVS_INT_STAT_SRS_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (tmp & (1 << (reg_set % 32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) mv_dprintk("register set 0x%x was stopped.\n", reg_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (reg_set > 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) mw32(MVS_INT_STAT_SRS_1, 1 << (reg_set % 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) u32 tfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) mvs_94xx_clear_srs_irq(mvi, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) tmp = mr32(MVS_INT_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) mw32(MVS_INT_STAT, tmp | CINT_CI_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) tmp = mr32(MVS_PCS) | 0xFF00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) mw32(MVS_PCS, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) u32 err_0, err_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct mvs_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) err_0 = mr32(MVS_NON_NCQ_ERR_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) err_1 = mr32(MVS_NON_NCQ_ERR_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) mv_dprintk("non specific ncq error err_0:%x,err_1:%x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) err_0, err_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (err_0 & bit(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) device = mvs_find_dev_by_reg_set(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) mvs_release_task(mvi, device->sas_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (err_1 & bit(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) device = mvs_find_dev_by_reg_set(mvi, i+32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) mvs_release_task(mvi, device->sas_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) mw32(MVS_NON_NCQ_ERR_0, err_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) mw32(MVS_NON_NCQ_ERR_1, err_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) u8 reg_set = *tfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (*tfs == MVS_ID_NOT_MAPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) mvi->sata_reg_set &= ~bit(reg_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (reg_set < 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) w_reg_set_enable(reg_set, (u32)mvi->sata_reg_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) w_reg_set_enable(reg_set, (u32)(mvi->sata_reg_set >> 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) *tfs = MVS_ID_NOT_MAPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static u8 mvs_94xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (*tfs != MVS_ID_NOT_MAPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) i = mv_ffc64(mvi->sata_reg_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (i >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) mvi->sata_reg_set |= bit(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) w_reg_set_enable(i, (u32)(mvi->sata_reg_set >> 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) *tfs = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) } else if (i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) mvi->sata_reg_set |= bit(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) w_reg_set_enable(i, (u32)mvi->sata_reg_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) *tfs = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return MVS_ID_NOT_MAPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct mvs_prd *buf_prd = prd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct mvs_prd_imt im_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) *(u32 *)&im_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) for_each_sg(scatter, sg, nr, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) im_len.len = sg_dma_len(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) buf_prd++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static int mvs_94xx_oob_done(struct mvs_info *mvi, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) u32 phy_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) phy_st = mvs_read_phy_ctl(mvi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (phy_st & PHY_READY_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct sas_identify_frame *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) u32 id_frame[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) for (i = 0; i < 7; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mvs_write_port_cfg_addr(mvi, port_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) CONFIG_ID_FRAME0 + i * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) memcpy(id, id_frame, 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct sas_identify_frame *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) u32 id_frame[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) for (i = 0; i < 7; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) mvs_write_port_cfg_addr(mvi, port_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) CONFIG_ATT_ID_FRAME0 + i * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) mv_dprintk("94xx phy %d atta frame %d %x.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) memcpy(id, id_frame, 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static u32 mvs_94xx_make_dev_info(struct sas_identify_frame *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) u32 att_dev_info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) att_dev_info |= id->dev_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (id->stp_iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) att_dev_info |= PORT_DEV_STP_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (id->smp_iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) att_dev_info |= PORT_DEV_SMP_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (id->ssp_iport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) att_dev_info |= PORT_DEV_SSP_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (id->stp_tport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) att_dev_info |= PORT_DEV_STP_TRGT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (id->smp_tport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) att_dev_info |= PORT_DEV_SMP_TRGT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (id->ssp_tport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) att_dev_info |= PORT_DEV_SSP_TRGT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) att_dev_info |= (u32)id->phy_id<<24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return att_dev_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static u32 mvs_94xx_make_att_info(struct sas_identify_frame *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return mvs_94xx_make_dev_info(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct sas_identify_frame *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct mvs_phy *phy = &mvi->phy[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct asd_sas_phy *sas_phy = &phy->sas_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) mv_dprintk("get all reg link rate is 0x%x\n", phy->phy_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) sas_phy->linkrate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) sas_phy->linkrate += 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) mv_dprintk("get link rate is %d\n", sas_phy->linkrate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) phy->maximum_linkrate = SAS_LINK_RATE_6_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) mvs_94xx_get_dev_identify_frame(mvi, i, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) phy->dev_info = mvs_94xx_make_dev_info(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (phy->phy_type & PORT_TYPE_SAS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) mvs_94xx_get_att_identify_frame(mvi, i, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) phy->att_dev_info = mvs_94xx_make_att_info(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) phy->att_dev_sas_addr = *(u64 *)id->sas_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) phy->att_dev_info = PORT_DEV_STP_TRGT | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* enable spin up bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) mvs_write_port_cfg_addr(mvi, i, PHYR_PHY_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) mvs_write_port_cfg_data(mvi, i, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct sas_phy_linkrates *rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) u32 lrmax = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) tmp = mvs_read_phy_ctl(mvi, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (lrmax) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) tmp &= ~(0x3 << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) tmp |= lrmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) mvs_write_phy_ctl(mvi, phy_id, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) mvs_94xx_phy_reset(mvi, phy_id, PHY_RST_HARD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) tmp = mr32(MVS_STP_REG_SET_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) mw32(MVS_STP_REG_SET_0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) mw32(MVS_STP_REG_SET_0, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) tmp = mr32(MVS_STP_REG_SET_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) mw32(MVS_STP_REG_SET_1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) mw32(MVS_STP_REG_SET_1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static u32 mvs_94xx_spi_read_data(struct mvs_info *mvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return mr32(SPI_RD_DATA_REG_94XX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) static void mvs_94xx_spi_write_data(struct mvs_info *mvi, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) mw32(SPI_RD_DATA_REG_94XX, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static int mvs_94xx_spi_buildcmd(struct mvs_info *mvi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) u32 *dwCmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) u8 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) u8 read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) u8 length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) u32 addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) u32 dwTmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dwTmp = ((u32)cmd << 8) | ((u32)length << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dwTmp |= SPI_CTRL_READ_94XX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (addr != MV_MAX_U32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) mw32(SPI_ADDR_REG_94XX, (addr & 0x0003FFFFL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) dwTmp |= SPI_ADDR_VLD_94XX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) *dwCmd = dwTmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) mw32(SPI_CTRL_REG_94XX, cmd | SPI_CTRL_SpiStart_94XX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) u32 i, dwTmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) for (i = 0; i < timeout; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) dwTmp = mr32(SPI_CTRL_REG_94XX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (!(dwTmp & SPI_CTRL_SpiStart_94XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) int buf_len, int from, void *prd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct mvs_prd *buf_prd = prd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) dma_addr_t buf_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct mvs_prd_imt im_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) *(u32 *)&im_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) buf_prd += from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) #define PRD_CHAINED_ENTRY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if ((mvi->pdev->revision == VANIR_A0_REV) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) (mvi->pdev->revision == VANIR_B0_REV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) buf_dma = (phy_mask <= 0x08) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) mvi->bulk_buffer_dma : mvi->bulk_buffer_dma1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) for (i = from; i < MAX_SG_ENTRY; i++, ++buf_prd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (i == MAX_SG_ENTRY - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) buf_prd->addr = cpu_to_le64(virt_to_phys(buf_prd - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) im_len.len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) im_len.misc_ctl = PRD_CHAINED_ENTRY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) buf_prd->addr = cpu_to_le64(buf_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) im_len.len = buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) buf_prd->im_len = cpu_to_le32(*(u32 *)&im_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static void mvs_94xx_tune_interrupt(struct mvs_info *mvi, u32 time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) void __iomem *regs = mvi->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) u32 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * the max count is 0x1ff, while our max slot is 0x200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * it will make count 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (time == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) mw32(MVS_INT_COAL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) mw32(MVS_INT_COAL_TMOUT, 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (MVS_CHIP_SLOT_SZ > 0x1ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) tmp = 0x10000 | time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) mw32(MVS_INT_COAL_TMOUT, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) u8 reg_type, u8 reg_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) u8 reg_count, u8 *write_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) switch (reg_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case SAS_GPIO_REG_TX_GP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (reg_index == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (reg_count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (reg_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* maximum supported bits = hosts * 4 drives * 3 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) for (i = 0; i < mvs_prv->n_host * 4 * 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* select host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct mvs_info *mvi = mvs_prv->mvi[i/(4*3)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int drive = (i/3) & (4-1); /* drive number on host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) int driveshift = drive * 8; /* bit offset of drive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) u32 block = ioread32be(regs + MVS_SGPIO_DCTRL +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) MVS_SGPIO_HOST_OFFSET * mvi->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * if bit is set then create a mask with the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * bit of the drive set in the mask ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) u32 bit = get_unaligned_be32(write_data) & (1 << i) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 1 << driveshift : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * ... and then shift it to the right position based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * on the led type (activity/id/fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) switch (i%3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) case 0: /* activity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) block &= ~((0x7 << MVS_SGPIO_DCTRL_ACT_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) << driveshift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /* hardwire activity bit to SOF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) block |= LED_BLINKA_SOF << (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) MVS_SGPIO_DCTRL_ACT_SHIFT +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) driveshift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) case 1: /* id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) block &= ~((0x3 << MVS_SGPIO_DCTRL_LOC_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) << driveshift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) block |= bit << MVS_SGPIO_DCTRL_LOC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) case 2: /* fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) block &= ~((0x7 << MVS_SGPIO_DCTRL_ERR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) << driveshift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) block |= bit << MVS_SGPIO_DCTRL_ERR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) iowrite32be(block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) regs + MVS_SGPIO_DCTRL +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) MVS_SGPIO_HOST_OFFSET * mvi->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) return reg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) case SAS_GPIO_REG_TX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (reg_index + reg_count > mvs_prv->n_host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) for (i = 0; i < reg_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) struct mvs_info *mvi = mvs_prv->mvi[i+reg_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) void __iomem *regs = mvi->regs_ex - 0x10200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) ((u32 *) write_data)[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return reg_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) const struct mvs_dispatch mvs_94xx_dispatch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) "mv94xx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) mvs_94xx_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) mvs_94xx_ioremap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) mvs_94xx_iounmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) mvs_94xx_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) mvs_94xx_isr_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) mvs_94xx_interrupt_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) mvs_94xx_interrupt_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) mvs_read_phy_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) mvs_write_phy_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) mvs_read_port_cfg_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) mvs_write_port_cfg_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) mvs_write_port_cfg_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) mvs_read_port_vsr_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) mvs_write_port_vsr_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) mvs_write_port_vsr_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) mvs_read_port_irq_stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) mvs_write_port_irq_stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) mvs_read_port_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) mvs_write_port_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) mvs_94xx_command_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) mvs_94xx_clear_srs_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) mvs_94xx_issue_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) mvs_start_delivery,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) mvs_rx_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) mvs_int_full,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) mvs_94xx_assign_reg_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) mvs_94xx_free_reg_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) mvs_get_prd_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) mvs_get_prd_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) mvs_94xx_make_prd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) mvs_94xx_detect_porttype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mvs_94xx_oob_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) mvs_94xx_fix_phy_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) mvs_94xx_phy_set_link_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) mvs_hw_max_link_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) mvs_94xx_phy_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) mvs_94xx_phy_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) mvs_94xx_phy_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) mvs_94xx_clear_active_cmds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) mvs_94xx_spi_read_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) mvs_94xx_spi_write_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) mvs_94xx_spi_buildcmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) mvs_94xx_spi_issuecmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) mvs_94xx_spi_waitdataready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) mvs_94xx_fix_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) mvs_94xx_tune_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) mvs_94xx_non_spec_ncq_error,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) mvs_94xx_gpio_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)