From patchwork Tue Jun 21 06:19:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 638491 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rYcyH4CQPz9t0N for ; Tue, 21 Jun 2016 16:19:35 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3rYcyH2yvyzDqRd for ; Tue, 21 Jun 2016 16:19:35 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3rYcy92gNTzDq5c for ; Tue, 21 Jun 2016 16:19:29 +1000 (AEST) Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u5L6JPwI028114 for ; Tue, 21 Jun 2016 02:19:26 -0400 Received: from e23smtp06.au.ibm.com (e23smtp06.au.ibm.com [202.81.31.148]) by mx0b-001b2d01.pphosted.com with ESMTP id 23n2ekdy7a-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 21 Jun 2016 02:19:26 -0400 Received: from localhost by e23smtp06.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 21 Jun 2016 16:19:17 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp06.au.ibm.com (202.81.31.212) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 21 Jun 2016 16:19:14 +1000 X-IBM-Helo: d23dlp03.au.ibm.com X-IBM-MailFrom: gwshan@linux.vnet.ibm.com X-IBM-RcptTo: skiboot@lists.ozlabs.org Received: from d23relay07.au.ibm.com (d23relay07.au.ibm.com [9.190.26.37]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id 47F4B3578056 for ; Tue, 21 Jun 2016 16:19:14 +1000 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay07.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u5L6JElI60555296 for ; Tue, 21 Jun 2016 16:19:14 +1000 Received: from d23av04.au.ibm.com (localhost [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u5L6JDwv015598 for ; Tue, 21 Jun 2016 16:19:13 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u5L6JDE3015577; Tue, 21 Jun 2016 16:19:13 +1000 Received: from bran.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) by ozlabs.au.ibm.com (Postfix) with ESMTP id DE762A0254; Tue, 21 Jun 2016 16:19:12 +1000 (AEST) Received: from gwshan (shangw.ozlabs.ibm.com [10.61.2.199]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id BDCD4E3B30; Tue, 21 Jun 2016 16:19:12 +1000 (AEST) Received: by gwshan (Postfix, from userid 1000) id 7ECED942CAA; Tue, 21 Jun 2016 16:19:12 +1000 (AEST) From: Gavin Shan To: skiboot@lists.ozlabs.org Date: Tue, 21 Jun 2016 16:19:11 +1000 X-Mailer: git-send-email 2.1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16062106-0040-0000-0000-000001B79F31 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16062106-0041-0000-0000-000009ED525B Message-Id: <1466489951-13273-1-git-send-email-gwshan@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-06-21_04:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1606210076 Subject: [Skiboot] [PATCH] platforms/ibm-fsp: Reuse PCI slot mechanism for fixup X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Currently, we have separately I2C stubs used for PCI slot power management and fixup. It's reasonable to merge them to one so that the code looks unified. Also, this introduces a table tracking PCI slot fixup info which is very easy to be extended in future. Signed-off-by: Gavin Shan --- Tested on P83 (Tuleta) only --- platforms/ibm-fsp/firenze-pci.c | 228 +++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 121 deletions(-) diff --git a/platforms/ibm-fsp/firenze-pci.c b/platforms/ibm-fsp/firenze-pci.c index 4416f1f..aa9a231 100644 --- a/platforms/ibm-fsp/firenze-pci.c +++ b/platforms/ibm-fsp/firenze-pci.c @@ -98,6 +98,8 @@ struct firenze_pci_slot_info { uint8_t channel; uint8_t power_status; uint8_t buddy; + uint8_t fixup; + uint8_t fixup_num; }; struct firenze_pci_inv { @@ -124,21 +126,30 @@ struct firenze_pci_inv_data { */ static struct firenze_pci_inv_data *firenze_inv_data; static uint32_t firenze_inv_cnt; +static uint8_t firenze_pci_slot_fixup_tbl[] = { + 0x5e, 0xfa, /* C6 / C7 */ + 0x5a, 0xff, + 0x5b, 0xff, + 0x5e, 0xfb, /* C5 */ + 0x5b, 0xff, + 0x5e, 0xfb, /* C3 */ + 0x5b, 0xff +}; static struct firenze_pci_slot_info firenze_pci_slots[] = { - { 0x0B, "C7", 1, 1, 0, 1, 0, 0x35, 1, 0xAA, 0 }, - { 0x11, "C14", 0, 1, 0, 0, 0, 0x00, 0, 0xAA, 1 }, - { 0x0F, "C11", 1, 1, 0, 1, 0, 0x32, 1, 0xAA, 2 }, - { 0x10, "C12", 1, 1, 0, 1, 0, 0x39, 0, 0xAA, 3 }, - { 0x0A, "C6", 1, 1, 0, 1, 0, 0x35, 0, 0xAA, 0 }, - { 0x12, "C15", 0, 1, 0, 0, 0, 0x00, 0, 0xAA, 5 }, - { 0x01, "USB", 0, 0, 0, 0, 0, 0x00, 0, 0xAA, 6 }, - { 0x0C, "C8", 1, 1, 0, 1, 0, 0x36, 0, 0xAA, 7 }, - { 0x0D, "C9", 1, 1, 0, 1, 0, 0x36, 1, 0xAA, 7 }, - { 0x0E, "C10", 1, 1, 0, 1, 0, 0x32, 0, 0xAA, 2 }, - { 0x09, "C5", 1, 1, 0x10, 1, 0, 0x39, 1, 0xAA, 10 }, - { 0x08, "C4", 1, 1, 0x10, 1, 0, 0x39, 0, 0xAA, 10 }, - { 0x07, "C3", 1, 1, 0x10, 1, 0, 0x3A, 1, 0xAA, 12 }, - { 0x06, "C2", 1, 1, 0x10, 1, 0, 0x3A, 0, 0xAA, 12 } + { 0x0B, "C7", 1, 1, 0, 1, 0, 0x35, 1, 0xAA, 0, 0, 3 }, + { 0x11, "C14", 0, 1, 0, 0, 0, 0x00, 0, 0xAA, 1, 0, 0 }, + { 0x0F, "C11", 1, 1, 0, 1, 0, 0x32, 1, 0xAA, 2, 0, 0 }, + { 0x10, "C12", 1, 1, 0, 1, 0, 0x39, 0, 0xAA, 3, 0, 0 }, + { 0x0A, "C6", 1, 1, 0, 1, 0, 0x35, 0, 0xAA, 0, 0, 3 }, + { 0x12, "C15", 0, 1, 0, 0, 0, 0x00, 0, 0xAA, 5, 0, 0 }, + { 0x01, "USB", 0, 0, 0, 0, 0, 0x00, 0, 0xAA, 6, 0, 0 }, + { 0x0C, "C8", 1, 1, 0, 1, 0, 0x36, 0, 0xAA, 7, 0, 0 }, + { 0x0D, "C9", 1, 1, 0, 1, 0, 0x36, 1, 0xAA, 7, 0, 0 }, + { 0x0E, "C10", 1, 1, 0, 1, 0, 0x32, 0, 0xAA, 2, 0, 0 }, + { 0x09, "C5", 1, 1, 0x10, 1, 0, 0x39, 1, 0xAA, 10, 3, 2 }, + { 0x08, "C4", 1, 1, 0x10, 1, 0, 0x39, 0, 0xAA, 10, 0, 0 }, + { 0x07, "C3", 1, 1, 0x10, 1, 0, 0x3A, 1, 0xAA, 12, 5, 2 }, + { 0x06, "C2", 1, 1, 0x10, 1, 0, 0x3A, 0, 0xAA, 12, 0, 0 } }; static void firenze_pci_add_inventory(struct phb *phb, @@ -742,6 +753,85 @@ static struct i2c_bus *firenze_pci_find_i2c_bus(uint8_t chip, return NULL; } +static int64_t firenze_pci_slot_fixup_one(struct pci_slot *slot, + struct firenze_pci_slot_info *info, + uint8_t *fixup, bool write) +{ + struct firenze_pci_slot *plat_slot = slot->data; + struct i2c_request *req = plat_slot->req; + int32_t retries = FIRENZE_PCI_SLOT_RETRIES; + uint8_t rval; + int64_t rc = OPAL_SUCCESS; + + req->offset = *fixup; + if (write) { + req->op = SMBUS_WRITE; + *(uint8_t *)(req->rw_buf) = *(fixup + 1); + } else { + req->op = SMBUS_READ; + *(uint8_t *)(req->rw_buf) = 0; + } + pci_slot_set_state(slot, FIRENZE_PCI_SLOT_FRESET_WAIT_RSP); + i2c_set_req_timeout(req, FIRENZE_PCI_I2C_TIMEOUT); + i2c_queue_req(plat_slot->req); + + while (retries-- > 0) { + check_timers(false); + if (slot->state == FIRENZE_PCI_SLOT_FRESET_DELAY) + break; + + time_wait_ms(FIRENZE_PCI_SLOT_DELAY); + } + + if (slot->state != FIRENZE_PCI_SLOT_FRESET_DELAY) { + rc = OPAL_BUSY; + prlog(PR_ERR, "Timeout %s PCI slot [%s] - (%02x, %02x)\n", + write ? "writing" : "reading", info->label, + *fixup, *(fixup + 1)); + goto out; + } + + if (!write) { + rval = *(uint8_t *)(req->rw_buf); + if (rval != *(fixup + 1)) { + rc = OPAL_INTERNAL_ERROR; + prlog(PR_ERR, "Error fixing PCI slot [%s] - (%02x, %02x, %02x)\n", + info->label, *fixup, *(fixup + 1), rval); + } + } + +out: + pci_slot_set_state(slot, FIRENZE_PCI_SLOT_NORMAL); + return rc; +} + +static void firenze_pci_slot_fixup(struct pci_slot *slot, + struct firenze_pci_slot_info *info) +{ + const uint32_t *p; + uint64_t id; + uint8_t *fixup, num, i; + int64_t rc; + + p = dt_prop_get_def(dt_root, "ibm,vpd-lx-info", NULL); + id = p ? (((uint64_t)p[1] << 32) | p[2]) : 0ul; + if (id != LX_VPD_2S4U_BACKPLANE && + id != LX_VPD_1S4U_BACKPLANE) + return; + + fixup = &firenze_pci_slot_fixup_tbl[info->fixup * 2]; + num = info->fixup_num; + for (i = 0; i < num; i++, fixup += 2) { + rc = firenze_pci_slot_fixup_one(slot, info, fixup, true); + if (rc) + return; + + rc = firenze_pci_slot_fixup_one(slot, info, fixup, false); + if (rc) + return; + } +} + static void firenze_pci_slot_init(struct pci_slot *slot) { struct lxvpd_pci_slot *s = slot->data; @@ -775,11 +865,13 @@ static void firenze_pci_slot_init(struct pci_slot *slot) if (plat_slot->req) { plat_slot->req->dev_addr = info->slave_addr; plat_slot->req->offset_bytes = 1; - plat_slot->req->offset = 0x69; plat_slot->req->rw_buf = plat_slot->i2c_rw_buf; plat_slot->req->rw_len = 1; plat_slot->req->completion = firenze_i2c_req_done; plat_slot->req->user_data = slot; + firenze_pci_slot_fixup(slot, info); + + plat_slot->req->offset = 0x69; switch (info->channel) { case 0: plat_slot->power_status = &firenze_pci_slots[buddy].power_status; @@ -864,109 +956,6 @@ void firenze_pci_setup_phb(struct phb *phb, unsigned int index) } } -static void firenze_pci_i2c_complete(int rc, struct i2c_request *req) -{ - *(int *)req->user_data = rc; -} - -static void firenze_pci_do_i2c_byte(uint8_t chip, uint8_t eng, uint8_t port, - uint8_t addr, uint8_t reg, uint8_t data) -{ - struct i2c_bus *bus; - struct i2c_request *req; - uint8_t verif; - int rc; - - bus = firenze_pci_find_i2c_bus(chip, eng, port); - if (!bus) { - prerror("FIRENZE: Failed to find i2c (%d/%d/%d)\n", chip, eng, port); - return; - } - req = i2c_alloc_req(bus); - if (!req) { - prerror("FIRENZE: Failed to allocate i2c request\n"); - return; - } - req->op = SMBUS_WRITE; - req->dev_addr = addr >> 1; - req->offset_bytes = 1; - req->offset = reg; - req->rw_buf = &data; - req->rw_len = 1; - req->completion = firenze_pci_i2c_complete; - req->user_data = &rc; - rc = 1; - i2c_queue_req(req); - while(rc == 1) { - time_wait_us(10); - } - if (rc != 0) { - prerror("FIRENZE: I2C error %d writing byte\n", rc); - return; - } - req->op = SMBUS_READ; - req->dev_addr = addr >> 1; - req->offset_bytes = 1; - req->offset = reg; - req->rw_buf = &verif; - req->rw_len = 1; - req->completion = firenze_pci_i2c_complete; - req->user_data = &rc; - rc = 1; - i2c_queue_req(req); - while(rc == 1) { - time_wait_us(10); - } - if (rc != 0) { - prerror("FIRENZE: I2C error %d reading byte\n", rc); - return; - } - if (verif != data) { - prerror("FIRENZE: I2C miscompare want %02x got %02x\n", data, verif); - } -} - -static void firenze_pci_slot_fixup(struct pci_slot *slot) -{ - uint64_t id; - const uint32_t *p; - struct lxvpd_pci_slot *s; - - p = dt_prop_get_def(dt_root, "ibm,vpd-lx-info", NULL); - if (!p) - return; - - /* FIXME: support fixup with generic way */ - id = ((uint64_t)p[1] << 32) | p[2]; - - if (id != LX_VPD_2S4U_BACKPLANE && - id != LX_VPD_1S4U_BACKPLANE) - return; - - s = slot->data; - if (!s || !s->pluggable) - return; - - /* Note: We apply the settings twice for C6/C7 but that shouldn't - * be a problem - */ - if (!strncmp(s->label, "C6 ", 2) || - !strncmp(s->label, "C7 ", 2)) { - printf("FIRENZE: Fixing power on %s...\n", s->label); - firenze_pci_do_i2c_byte(0, 1, 0, 0x6a, 0x5e, 0xfa); - firenze_pci_do_i2c_byte(0, 1, 0, 0x6a, 0x5a, 0xff); - firenze_pci_do_i2c_byte(0, 1, 0, 0x6a, 0x5b, 0xff); - } else if (!strncmp(s->label, "C5 ", 2)) { - printf("FIRENZE: Fixing power on %s...\n", s->label); - firenze_pci_do_i2c_byte(0, 1, 0, 0x72, 0x5e, 0xfb); - firenze_pci_do_i2c_byte(0, 1, 0, 0x72, 0x5b, 0xff); - } else if (!strncmp(s->label, "C3 ", 2)) { - printf("FIRENZE: Fixing power on %s...\n", s->label); - firenze_pci_do_i2c_byte(0, 1, 0, 0x74, 0x5e, 0xfb); - firenze_pci_do_i2c_byte(0, 1, 0, 0x74, 0x5b, 0xff); - } -} - void firenze_pci_get_slot_info(struct phb *phb, struct pci_device *pd) { struct pci_slot *slot; @@ -996,7 +985,4 @@ void firenze_pci_get_slot_info(struct phb *phb, struct pci_device *pd) lxvpd_extract_info(slot, s); firenze_pci_slot_init(slot); } - - /* Fixup the slot's power status */ - firenze_pci_slot_fixup(slot); }