/* Copyright 2013-2016 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <skiboot.h>
#include <opal-msg.h>
#include <pci-cfg.h>
#include <pci.h>
#include <pci-slot.h>

/* Debugging options */
#define PCI_SLOT_PREFIX	"PCI-SLOT-%016llx "
#define PCI_SLOT_DBG(s, fmt, a...)		 \
	prlog(PR_DEBUG, PCI_SLOT_PREFIX fmt, (s)->id, ##a)

static void pci_slot_prepare_link_change(struct pci_slot *slot, bool up)
{
	struct phb *phb = slot->phb;
	struct pci_device *pd = slot->pd;
	uint32_t aercap, mask;

	/*
	 * Mask the link down and receiver error before the link becomes
	 * down. Otherwise, unmask the errors when the link is up.
	 */
	if (pci_has_cap(pd, PCIECAP_ID_AER, true)) {
		aercap = pci_cap(pd, PCIECAP_ID_AER, true);

		/* Mask link surprise down event. The event is always
		 * masked when the associated PCI slot supports PCI
		 * surprise hotplug. We needn't toggle it when the link
		 * bounces caused by reset and just keep it always masked.
		 */
		if (!pd->slot || !pd->slot->surprise_pluggable) {
			pci_cfg_read32(phb, pd->bdfn,
				       aercap + PCIECAP_AER_UE_MASK, &mask);
			if (up)
				mask &= ~PCIECAP_AER_UE_MASK_SURPRISE_DOWN;
			else
				mask |= PCIECAP_AER_UE_MASK_SURPRISE_DOWN;
			pci_cfg_write32(phb, pd->bdfn,
					aercap + PCIECAP_AER_UE_MASK, mask);
		}

		/* Receiver error */
		pci_cfg_read32(phb, pd->bdfn, aercap + PCIECAP_AER_CE_MASK,
			       &mask);
		if (up)
			mask &= ~PCIECAP_AER_CE_RECVR_ERR;
		else
			mask |= PCIECAP_AER_CE_RECVR_ERR;
		pci_cfg_write32(phb, pd->bdfn, aercap + PCIECAP_AER_CE_MASK,
				mask);
	}

	/*
	 * We're coming back from reset. We need restore bus ranges
	 * and reinitialize the affected bridges and devices.
	 */
	if (up) {
		pci_restore_bridge_buses(phb, pd);
		if (phb->ops->device_init)
			pci_walk_dev(phb, pd, phb->ops->device_init, NULL);
	}
}

static int64_t pci_slot_sm_poll(struct pci_slot *slot)
{
	uint64_t now = mftb();
	int64_t ret;

	/* Return remaining timeout if we're still waiting */
	if (slot->delay_tgt_tb &&
	    tb_compare(now, slot->delay_tgt_tb) == TB_ABEFOREB)
		return slot->delay_tgt_tb - now;

	slot->delay_tgt_tb = 0;
	switch (slot->state & PCI_SLOT_STATE_MASK) {
	case PCI_SLOT_STATE_LINK:
		ret = slot->ops.poll_link(slot);
		break;
	case PCI_SLOT_STATE_HRESET:
		ret = slot->ops.hreset(slot);
		break;
	case PCI_SLOT_STATE_FRESET:
		ret = slot->ops.freset(slot);
		break;
	case PCI_SLOT_STATE_CRESET:
		ret = slot->ops.creset(slot);
		break;
	default:
		prlog(PR_ERR, PCI_SLOT_PREFIX
		      "Invalid state %08x\n", slot->id, slot->state);
		pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
		return OPAL_HARDWARE;
	}

	return ret;
}

void pci_slot_add_dt_properties(struct pci_slot *slot,
				struct dt_node *np)
{
	/* Bail without device node */
	if (!np)
		return;

	dt_add_property_cells(np, "ibm,reset-by-firmware", 1);
	dt_add_property_cells(np, "ibm,slot-pluggable", slot->pluggable);
	dt_add_property_cells(np, "ibm,slot-surprise-pluggable",
			      slot->surprise_pluggable);
	if (pci_slot_has_flags(slot, PCI_SLOT_FLAG_BROKEN_PDC))
		dt_add_property_cells(np, "ibm,slot-broken-pdc", 1);

	dt_add_property_cells(np, "ibm,slot-power-ctl", slot->power_ctl);
	dt_add_property_cells(np, "ibm,slot-power-led-ctlled",
			      slot->power_led_ctl);
	dt_add_property_cells(np, "ibm,slot-attn-led", slot->attn_led_ctl);
	dt_add_property_cells(np, "ibm,slot-connector-type",
			      slot->connector_type);
	dt_add_property_cells(np, "ibm,slot-card-desc", slot->card_desc);
	dt_add_property_cells(np, "ibm,slot-card-mech", slot->card_mech);
	dt_add_property_cells(np, "ibm,slot-wired-lanes", slot->wired_lanes);

	if (slot->ops.add_properties)
		slot->ops.add_properties(slot, np);
}

struct pci_slot *pci_slot_alloc(struct phb *phb,
				struct pci_device *pd)
{
	struct pci_slot *slot = NULL;

	/*
	 * The function can be used to allocate either PHB slot or normal
	 * one. For both cases, the @phb should be always valid.
	 */
	if (!phb)
		return NULL;

	/*
	 * When @pd is NULL, we're going to create a PHB slot. Otherwise,
	 * a normal slot will be created. Check if the specified slot
	 * already exists or not.
	 */
	slot = pd ? pd->slot : phb->slot;
	if (slot) {
		prlog(PR_ERR, PCI_SLOT_PREFIX "Already exists\n", slot->id);
		return slot;
	}

	/* Allocate memory chunk */
	slot = zalloc(sizeof(struct pci_slot));
	if (!slot) {
		prlog(PR_ERR, "%s: Out of memory\n", __func__);
		return NULL;
	}

	/*
	 * The polling function sholdn't be overridden by individual
	 * platforms
	 */
	slot->phb = phb;
	slot->pd = pd;
	pci_slot_set_state(slot, PCI_SLOT_STATE_NORMAL);
	slot->power_state = PCI_SLOT_POWER_ON;
	slot->ops.poll = pci_slot_sm_poll;
	slot->ops.prepare_link_change = pci_slot_prepare_link_change;
	if (!pd) {
		slot->id = PCI_PHB_SLOT_ID(phb);
		phb->slot = slot;
	} else {
		slot->id = PCI_SLOT_ID(phb, pd->bdfn);
		pd->slot = slot;
	}

	return slot;
}

struct pci_slot *pci_slot_find(uint64_t id)
{
	struct phb *phb;
	struct pci_device *pd;
	struct pci_slot *slot;
	uint64_t index;
	uint16_t bdfn;

	index = PCI_SLOT_PHB_INDEX(id);
	phb = pci_get_phb(index);

	/* PHB slot */
	if (!(id & PCI_SLOT_ID_PREFIX)) {
		slot = phb ? phb->slot : NULL;
		return slot;
	}

	/* Normal PCI slot */
	bdfn = PCI_SLOT_BDFN(id);
	pd = phb ? pci_find_dev(phb, bdfn) : NULL;
	slot = pd ? pd->slot : NULL;
	return slot;
}
