Skip to content

Commit

Permalink
Merge branch 'update-2.1.1.1' into mergeback
Browse files Browse the repository at this point in the history
Complex merge fixups

Signed-off-by: Benjamin Herrenschmidt <[email protected]>
  • Loading branch information
ozbenh committed Jul 1, 2015
2 parents 6c458a0 + 200df96 commit 6be837c
Showing 1 changed file with 144 additions and 5 deletions.
149 changes: 144 additions & 5 deletions platforms/ibm-fsp/firenze.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <pci.h>
#include <pci-cfg.h>
#include <chip.h>
#include <i2c.h>
#include <timebase.h>
#include <hostservices.h>

#include "ibm-fsp.h"
Expand Down Expand Up @@ -48,6 +50,7 @@ struct fsp_pcie_inventory {
static struct fsp_pcie_inventory *fsp_pcie_inv;
static unsigned int fsp_pcie_inv_alloc_count;
#define FSP_PCIE_INV_ALLOC_CHUNK 4
static uint64_t lx_vpd_id;

struct lock fsp_pcie_inv_lock = LOCK_UNLOCKED;

Expand Down Expand Up @@ -110,6 +113,44 @@ static struct dt_node *dt_create_i2c_device(struct dt_node *bus, uint8_t addr,
return dev;
}

static struct i2c_bus *firenze_pci_find_i2c_bus(uint8_t chip, uint8_t eng, uint8_t port)
{
struct dt_node *np, *child;
uint32_t reg;

/* Iterate I2C masters */
dt_for_each_compatible(dt_root, np, "ibm,power8-i2cm") {
if (!np->parent ||
!dt_node_is_compatible(np->parent, "ibm,power8-xscom"))
continue;

/* Check chip index */
reg = dt_prop_get_u32(np->parent, "ibm,chip-id");
if (reg != chip)
continue;

/* Check I2C master index */
reg = dt_prop_get_u32(np, "chip-engine#");
if (reg != eng)
continue;

/* Iterate I2C buses */
dt_for_each_child(np, child) {
if (!dt_node_is_compatible(child, "ibm,power8-i2c-port"))
continue;

/* Check I2C port index */
reg = dt_prop_get_u32(child, "reg");
if (reg != port)
continue;

reg = dt_prop_get_u32(child, "ibm,opal-id");
return i2c_find_bus_by_id(reg);
}
}
return NULL;
}

static void firenze_dt_fixup_i2cm(void)
{
struct dt_node *master, *bus, *dev;
Expand Down Expand Up @@ -272,6 +313,102 @@ static void firenze_send_pci_inventory(void)
fsp_pcie_inv = NULL;
}

static void firenze_i2c_complete(int rc, struct i2c_request *req)
{
*(int *)req->user_data = rc;
}

static void firenze_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_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_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_fixup_pcie_slot_power(struct pci_device * pd)
{
const char *label = pd->slot_info->label;

if (!pd->slot_info->pluggable)
return;

if (lx_vpd_id != LX_VPD_2S4U_BACKPLANE &&
lx_vpd_id != LX_VPD_1S4U_BACKPLANE)
return;

printf("FIRENZE: Checking slot %s for power fixup\n", label);

/* Note: We apply the settings twice for C6/C7 but that shouldn't
* be a problem
*/
if (!strncmp(label, "C6 ", 3) || !strncmp(label, "C7 ", 3)) {
printf("FIRENZE: Fixing power on %s...\n", label);
firenze_do_i2c_byte(0, 1, 0, 0x6a, 0x5e, 0xfa);
firenze_do_i2c_byte(0, 1, 0, 0x6a, 0x5a, 0xff);
firenze_do_i2c_byte(0, 1, 0, 0x6a, 0x5b, 0xff);
}
if (!strncmp(label, "C5 ", 3)) {
printf("FIRENZE: Fixing power on %s...\n", label);
firenze_do_i2c_byte(0, 1, 0, 0x72, 0x5e, 0xfb);
firenze_do_i2c_byte(0, 1, 0, 0x72, 0x5b, 0xff);
}
if (!strncmp(label, "C3 ", 3)) {
printf("FIRENZE: Fixing power on %s...\n", label);
firenze_do_i2c_byte(0, 1, 0, 0x74, 0x5e, 0xfb);
firenze_do_i2c_byte(0, 1, 0, 0x74, 0x5b, 0xff);
}
}

static void firenze_add_pcidev_to_fsp_inventory(struct phb *phb,
struct pci_device *pd)
{
Expand Down Expand Up @@ -353,17 +490,19 @@ static void firenze_get_slot_info(struct phb *phb, struct pci_device * pd)
* - Slot entry says pluggable
* - Aren't an upstream switch that has slot info
*/
if (!pd || !pd->parent)
return;
if (pd->bdfn & 7)
if (!pd)
return;
if (pd->dev_type == PCIE_TYPE_ROOT_PORT ||
pd->dev_type == PCIE_TYPE_SWITCH_DNPORT)
pd->dev_type == PCIE_TYPE_SWITCH_DNPORT) {
firenze_fixup_pcie_slot_power(pd);
return;
}
if (pd->bdfn & 7)
return;
if (pd->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
pd->slot_info)
return;
if (!pd->parent->slot_info)
if (!pd->parent || !pd->parent->slot_info)
return;
if (!pd->parent->slot_info->pluggable)
return;
Expand Down

0 comments on commit 6be837c

Please sign in to comment.