15ef51809SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 25ef51809SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 35ef51809SAlfredo Cardigliano */ 45ef51809SAlfredo Cardigliano 55ef51809SAlfredo Cardigliano #include <rte_malloc.h> 65ef51809SAlfredo Cardigliano 75ef51809SAlfredo Cardigliano #include "ionic_dev.h" 85ef51809SAlfredo Cardigliano #include "ionic.h" 95ef51809SAlfredo Cardigliano 105ef51809SAlfredo Cardigliano int 115ef51809SAlfredo Cardigliano ionic_dev_setup(struct ionic_adapter *adapter) 125ef51809SAlfredo Cardigliano { 135ef51809SAlfredo Cardigliano struct ionic_dev_bar *bar = adapter->bars; 145ef51809SAlfredo Cardigliano unsigned int num_bars = adapter->num_bars; 155ef51809SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 165ef51809SAlfredo Cardigliano uint32_t sig; 175ef51809SAlfredo Cardigliano u_char *bar0_base; 185ef51809SAlfredo Cardigliano 195ef51809SAlfredo Cardigliano /* BAR0: dev_cmd and interrupts */ 205ef51809SAlfredo Cardigliano if (num_bars < 1) { 215ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "No bars found, aborting"); 225ef51809SAlfredo Cardigliano return -EFAULT; 235ef51809SAlfredo Cardigliano } 245ef51809SAlfredo Cardigliano 255ef51809SAlfredo Cardigliano if (bar->len < IONIC_BAR0_SIZE) { 265ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, 275ef51809SAlfredo Cardigliano "Resource bar size %lu too small, aborting", 285ef51809SAlfredo Cardigliano bar->len); 295ef51809SAlfredo Cardigliano return -EFAULT; 305ef51809SAlfredo Cardigliano } 315ef51809SAlfredo Cardigliano 325ef51809SAlfredo Cardigliano bar0_base = bar->vaddr; 335ef51809SAlfredo Cardigliano idev->dev_info = (union ionic_dev_info_regs *) 345ef51809SAlfredo Cardigliano &bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET]; 355ef51809SAlfredo Cardigliano idev->dev_cmd = (union ionic_dev_cmd_regs *) 365ef51809SAlfredo Cardigliano &bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET]; 375ef51809SAlfredo Cardigliano idev->intr_status = (struct ionic_intr_status *) 385ef51809SAlfredo Cardigliano &bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET]; 395ef51809SAlfredo Cardigliano idev->intr_ctrl = (struct ionic_intr *) 405ef51809SAlfredo Cardigliano &bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET]; 415ef51809SAlfredo Cardigliano 425ef51809SAlfredo Cardigliano sig = ioread32(&idev->dev_info->signature); 435ef51809SAlfredo Cardigliano if (sig != IONIC_DEV_INFO_SIGNATURE) { 445ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Incompatible firmware signature %" PRIx32 "", 455ef51809SAlfredo Cardigliano sig); 465ef51809SAlfredo Cardigliano return -EFAULT; 475ef51809SAlfredo Cardigliano } 485ef51809SAlfredo Cardigliano 495ef51809SAlfredo Cardigliano /* BAR1: doorbells */ 505ef51809SAlfredo Cardigliano bar++; 515ef51809SAlfredo Cardigliano if (num_bars < 2) { 525ef51809SAlfredo Cardigliano IONIC_PRINT(ERR, "Doorbell bar missing, aborting"); 535ef51809SAlfredo Cardigliano return -EFAULT; 545ef51809SAlfredo Cardigliano } 555ef51809SAlfredo Cardigliano 565ef51809SAlfredo Cardigliano idev->db_pages = bar->vaddr; 575ef51809SAlfredo Cardigliano idev->phy_db_pages = bar->bus_addr; 585ef51809SAlfredo Cardigliano 595ef51809SAlfredo Cardigliano return 0; 605ef51809SAlfredo Cardigliano } 615ef51809SAlfredo Cardigliano 625ef51809SAlfredo Cardigliano /* Devcmd Interface */ 635ef51809SAlfredo Cardigliano 645ef51809SAlfredo Cardigliano uint8_t 655ef51809SAlfredo Cardigliano ionic_dev_cmd_status(struct ionic_dev *idev) 665ef51809SAlfredo Cardigliano { 675ef51809SAlfredo Cardigliano return ioread8(&idev->dev_cmd->comp.comp.status); 685ef51809SAlfredo Cardigliano } 695ef51809SAlfredo Cardigliano 705ef51809SAlfredo Cardigliano bool 715ef51809SAlfredo Cardigliano ionic_dev_cmd_done(struct ionic_dev *idev) 725ef51809SAlfredo Cardigliano { 735ef51809SAlfredo Cardigliano return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE; 745ef51809SAlfredo Cardigliano } 755ef51809SAlfredo Cardigliano 765ef51809SAlfredo Cardigliano void 775ef51809SAlfredo Cardigliano ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem) 785ef51809SAlfredo Cardigliano { 795ef51809SAlfredo Cardigliano union ionic_dev_cmd_comp *comp = mem; 805ef51809SAlfredo Cardigliano unsigned int i; 815ef51809SAlfredo Cardigliano uint32_t comp_size = sizeof(comp->words) / 825ef51809SAlfredo Cardigliano sizeof(comp->words[0]); 835ef51809SAlfredo Cardigliano 845ef51809SAlfredo Cardigliano for (i = 0; i < comp_size; i++) 855ef51809SAlfredo Cardigliano comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]); 865ef51809SAlfredo Cardigliano } 875ef51809SAlfredo Cardigliano 885ef51809SAlfredo Cardigliano void 895ef51809SAlfredo Cardigliano ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd) 905ef51809SAlfredo Cardigliano { 915ef51809SAlfredo Cardigliano unsigned int i; 925ef51809SAlfredo Cardigliano uint32_t cmd_size = sizeof(cmd->words) / 935ef51809SAlfredo Cardigliano sizeof(cmd->words[0]); 945ef51809SAlfredo Cardigliano 955ef51809SAlfredo Cardigliano for (i = 0; i < cmd_size; i++) 965ef51809SAlfredo Cardigliano iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]); 975ef51809SAlfredo Cardigliano 985ef51809SAlfredo Cardigliano iowrite32(0, &idev->dev_cmd->done); 995ef51809SAlfredo Cardigliano iowrite32(1, &idev->dev_cmd->doorbell); 1005ef51809SAlfredo Cardigliano } 1015ef51809SAlfredo Cardigliano 1025ef51809SAlfredo Cardigliano /* Device commands */ 1035ef51809SAlfredo Cardigliano 1045ef51809SAlfredo Cardigliano void 1055ef51809SAlfredo Cardigliano ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver) 1065ef51809SAlfredo Cardigliano { 1075ef51809SAlfredo Cardigliano union ionic_dev_cmd cmd = { 1085ef51809SAlfredo Cardigliano .identify.opcode = IONIC_CMD_IDENTIFY, 1095ef51809SAlfredo Cardigliano .identify.ver = ver, 1105ef51809SAlfredo Cardigliano }; 1115ef51809SAlfredo Cardigliano 1125ef51809SAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 1135ef51809SAlfredo Cardigliano } 1145ef51809SAlfredo Cardigliano 1155ef51809SAlfredo Cardigliano void 1165ef51809SAlfredo Cardigliano ionic_dev_cmd_init(struct ionic_dev *idev) 1175ef51809SAlfredo Cardigliano { 1185ef51809SAlfredo Cardigliano union ionic_dev_cmd cmd = { 1195ef51809SAlfredo Cardigliano .init.opcode = IONIC_CMD_INIT, 1205ef51809SAlfredo Cardigliano .init.type = 0, 1215ef51809SAlfredo Cardigliano }; 1225ef51809SAlfredo Cardigliano 1235ef51809SAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 1245ef51809SAlfredo Cardigliano } 1255ef51809SAlfredo Cardigliano 1265ef51809SAlfredo Cardigliano void 1275ef51809SAlfredo Cardigliano ionic_dev_cmd_reset(struct ionic_dev *idev) 1285ef51809SAlfredo Cardigliano { 1295ef51809SAlfredo Cardigliano union ionic_dev_cmd cmd = { 1305ef51809SAlfredo Cardigliano .reset.opcode = IONIC_CMD_RESET, 1315ef51809SAlfredo Cardigliano }; 1325ef51809SAlfredo Cardigliano 1335ef51809SAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 1345ef51809SAlfredo Cardigliano } 135*23bf4ddbSAlfredo Cardigliano 136*23bf4ddbSAlfredo Cardigliano /* Port commands */ 137*23bf4ddbSAlfredo Cardigliano 138*23bf4ddbSAlfredo Cardigliano void 139*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_identify(struct ionic_dev *idev) 140*23bf4ddbSAlfredo Cardigliano { 141*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 142*23bf4ddbSAlfredo Cardigliano .port_init.opcode = IONIC_CMD_PORT_IDENTIFY, 143*23bf4ddbSAlfredo Cardigliano .port_init.index = 0, 144*23bf4ddbSAlfredo Cardigliano }; 145*23bf4ddbSAlfredo Cardigliano 146*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 147*23bf4ddbSAlfredo Cardigliano } 148*23bf4ddbSAlfredo Cardigliano 149*23bf4ddbSAlfredo Cardigliano void 150*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_init(struct ionic_dev *idev) 151*23bf4ddbSAlfredo Cardigliano { 152*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 153*23bf4ddbSAlfredo Cardigliano .port_init.opcode = IONIC_CMD_PORT_INIT, 154*23bf4ddbSAlfredo Cardigliano .port_init.index = 0, 155*23bf4ddbSAlfredo Cardigliano .port_init.info_pa = idev->port_info_pa, 156*23bf4ddbSAlfredo Cardigliano }; 157*23bf4ddbSAlfredo Cardigliano 158*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 159*23bf4ddbSAlfredo Cardigliano } 160*23bf4ddbSAlfredo Cardigliano 161*23bf4ddbSAlfredo Cardigliano void 162*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_reset(struct ionic_dev *idev) 163*23bf4ddbSAlfredo Cardigliano { 164*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 165*23bf4ddbSAlfredo Cardigliano .port_reset.opcode = IONIC_CMD_PORT_RESET, 166*23bf4ddbSAlfredo Cardigliano .port_reset.index = 0, 167*23bf4ddbSAlfredo Cardigliano }; 168*23bf4ddbSAlfredo Cardigliano 169*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 170*23bf4ddbSAlfredo Cardigliano } 171*23bf4ddbSAlfredo Cardigliano 172*23bf4ddbSAlfredo Cardigliano void 173*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state) 174*23bf4ddbSAlfredo Cardigliano { 175*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 176*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 177*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 178*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_STATE, 179*23bf4ddbSAlfredo Cardigliano .port_setattr.state = state, 180*23bf4ddbSAlfredo Cardigliano }; 181*23bf4ddbSAlfredo Cardigliano 182*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 183*23bf4ddbSAlfredo Cardigliano } 184*23bf4ddbSAlfredo Cardigliano 185*23bf4ddbSAlfredo Cardigliano void 186*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed) 187*23bf4ddbSAlfredo Cardigliano { 188*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 189*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 190*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 191*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_SPEED, 192*23bf4ddbSAlfredo Cardigliano .port_setattr.speed = speed, 193*23bf4ddbSAlfredo Cardigliano }; 194*23bf4ddbSAlfredo Cardigliano 195*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 196*23bf4ddbSAlfredo Cardigliano } 197*23bf4ddbSAlfredo Cardigliano 198*23bf4ddbSAlfredo Cardigliano void 199*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu) 200*23bf4ddbSAlfredo Cardigliano { 201*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 202*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 203*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 204*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_MTU, 205*23bf4ddbSAlfredo Cardigliano .port_setattr.mtu = mtu, 206*23bf4ddbSAlfredo Cardigliano }; 207*23bf4ddbSAlfredo Cardigliano 208*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 209*23bf4ddbSAlfredo Cardigliano } 210*23bf4ddbSAlfredo Cardigliano 211*23bf4ddbSAlfredo Cardigliano void 212*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable) 213*23bf4ddbSAlfredo Cardigliano { 214*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 215*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 216*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 217*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_AUTONEG, 218*23bf4ddbSAlfredo Cardigliano .port_setattr.an_enable = an_enable, 219*23bf4ddbSAlfredo Cardigliano }; 220*23bf4ddbSAlfredo Cardigliano 221*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 222*23bf4ddbSAlfredo Cardigliano } 223*23bf4ddbSAlfredo Cardigliano 224*23bf4ddbSAlfredo Cardigliano void 225*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type) 226*23bf4ddbSAlfredo Cardigliano { 227*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 228*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 229*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 230*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_FEC, 231*23bf4ddbSAlfredo Cardigliano .port_setattr.fec_type = fec_type, 232*23bf4ddbSAlfredo Cardigliano }; 233*23bf4ddbSAlfredo Cardigliano 234*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 235*23bf4ddbSAlfredo Cardigliano } 236*23bf4ddbSAlfredo Cardigliano 237*23bf4ddbSAlfredo Cardigliano void 238*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type) 239*23bf4ddbSAlfredo Cardigliano { 240*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 241*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 242*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 243*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_PAUSE, 244*23bf4ddbSAlfredo Cardigliano .port_setattr.pause_type = pause_type, 245*23bf4ddbSAlfredo Cardigliano }; 246*23bf4ddbSAlfredo Cardigliano 247*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 248*23bf4ddbSAlfredo Cardigliano } 249*23bf4ddbSAlfredo Cardigliano 250*23bf4ddbSAlfredo Cardigliano void 251*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode) 252*23bf4ddbSAlfredo Cardigliano { 253*23bf4ddbSAlfredo Cardigliano union ionic_dev_cmd cmd = { 254*23bf4ddbSAlfredo Cardigliano .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 255*23bf4ddbSAlfredo Cardigliano .port_setattr.index = 0, 256*23bf4ddbSAlfredo Cardigliano .port_setattr.attr = IONIC_PORT_ATTR_LOOPBACK, 257*23bf4ddbSAlfredo Cardigliano .port_setattr.loopback_mode = loopback_mode, 258*23bf4ddbSAlfredo Cardigliano }; 259*23bf4ddbSAlfredo Cardigliano 260*23bf4ddbSAlfredo Cardigliano ionic_dev_cmd_go(idev, &cmd); 261*23bf4ddbSAlfredo Cardigliano } 262