Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions Documentation/devicetree/bindings/pci/toshiba,tc9563.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/pci/toshiba,tc9563.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Toshiba TC9563 PCIe switch

maintainers:
- Krishna chaitanya chundru <[email protected]>

description: |
Toshiba TC9563 PCIe switch has one upstream and three downstream ports.
The 3rd downstream port has integrated endpoint device of Ethernet MAC.
Other two downstream ports are supposed to connect to external device.

The TC9563 PCIe switch can be configured through I2C interface before
PCIe link is established to change FTS, ASPM related entry delays,
tx amplitude etc for better power efficiency and functionality.

properties:
compatible:
enum:
- pci1179,0623

reg:
maxItems: 1

reset-gpios:
maxItems: 1
description:
GPIO controlling the RESX# pin.

vdd18-supply: true

vdd09-supply: true

vddc-supply: true

vddio1-supply: true

vddio2-supply: true

vddio18-supply: true

i2c-parent:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
A phandle to the parent I2C node and the slave address of the device
used to do configure tc9563 to change FTS, tx amplitude etc.
items:
- description: Phandle to the I2C controller node
- description: I2C slave address

patternProperties:
"^pcie@[1-3],0$":
description:
child nodes describing the internal downstream ports
the tc9563 switch.
type: object
allOf:
- $ref: "#/$defs/tc9563-node"
- $ref: /schemas/pci/pci-pci-bridge.yaml#
unevaluatedProperties: false

$defs:
tc9563-node:
type: object

properties:
toshiba,tx-amplitude-microvolt:
description:
Change Tx Margin setting for low power consumption.

toshiba,no-dfe-support:
type: boolean
description:
Disable DFE (Decision Feedback Equalizer), which mitigates
intersymbol interference and some reflections caused by impedance mismatches.

required:
- reset-gpios
- vdd18-supply
- vdd09-supply
- vddc-supply
- vddio1-supply
- vddio2-supply
- vddio18-supply
- i2c-parent

allOf:
- $ref: "#/$defs/tc9563-node"
- $ref: /schemas/pci/pci-bus-common.yaml#

unevaluatedProperties: false

examples:
- |
#include <dt-bindings/gpio/gpio.h>

pcie {
#address-cells = <3>;
#size-cells = <2>;

pcie@0 {
device_type = "pci";
reg = <0x0 0x0 0x0 0x0 0x0>;

#address-cells = <3>;
#size-cells = <2>;
ranges;
bus-range = <0x01 0xff>;

pcie@0,0 {
compatible = "pci1179,0623";

reg = <0x10000 0x0 0x0 0x0 0x0>;
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
ranges;
bus-range = <0x02 0xff>;

i2c-parent = <&qup_i2c 0x77>;

vdd18-supply = <&vdd>;
vdd09-supply = <&vdd>;
vddc-supply = <&vdd>;
vddio1-supply = <&vdd>;
vddio2-supply = <&vdd>;
vddio18-supply = <&vdd>;

reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;

pcie@1,0 {
compatible = "pciclass,0604";
reg = <0x20800 0x0 0x0 0x0 0x0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges;
bus-range = <0x03 0xff>;

toshiba,no-dfe-support;
};

pcie@2,0 {
compatible = "pciclass,0604";
reg = <0x21000 0x0 0x0 0x0 0x0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges;
bus-range = <0x04 0xff>;
};

pcie@3,0 {
compatible = "pciclass,0604";
reg = <0x21800 0x0 0x0 0x0 0x0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
ranges;
bus-range = <0x05 0xff>;

toshiba,tx-amplitude-microvolt = <10>;

ethernet@0,0 {
reg = <0x50000 0x0 0x0 0x0 0x0>;
};

ethernet@0,1 {
reg = <0x50100 0x0 0x0 0x0 0x0>;
};
};
};
};
};
18 changes: 18 additions & 0 deletions drivers/pci/controller/dwc/pcie-designware-host.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,10 +727,28 @@ void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn,
}
EXPORT_SYMBOL_GPL(dw_pcie_own_conf_map_bus);

static int dw_pcie_op_start_link(struct pci_bus *bus)
{
struct dw_pcie_rp *pp = bus->sysdata;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);

return dw_pcie_host_start_link(pci);
}

static void dw_pcie_op_stop_link(struct pci_bus *bus)
{
struct dw_pcie_rp *pp = bus->sysdata;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);

dw_pcie_host_stop_link(pci);
}

static struct pci_ops dw_pcie_ops = {
.map_bus = dw_pcie_own_conf_map_bus,
.read = pci_generic_config_read,
.write = pci_generic_config_write,
.start_link = dw_pcie_op_start_link,
.stop_link = dw_pcie_op_stop_link,
};

static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
Expand Down
16 changes: 16 additions & 0 deletions drivers/pci/controller/dwc/pcie-designware.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ struct dw_pcie_ops {
enum dw_pcie_ltssm (*get_ltssm)(struct dw_pcie *pcie);
int (*start_link)(struct dw_pcie *pcie);
void (*stop_link)(struct dw_pcie *pcie);
int (*host_start_link)(struct dw_pcie *pcie);
void (*host_stop_link)(struct dw_pcie *pcie);
};

struct debugfs_info {
Expand Down Expand Up @@ -743,6 +745,20 @@ static inline void dw_pcie_stop_link(struct dw_pcie *pci)
pci->ops->stop_link(pci);
}

static inline int dw_pcie_host_start_link(struct dw_pcie *pci)
{
if (pci->ops && pci->ops->host_start_link)
return pci->ops->host_start_link(pci);

return 0;
}

static inline void dw_pcie_host_stop_link(struct dw_pcie *pci)
{
if (pci->ops && pci->ops->host_stop_link)
pci->ops->host_stop_link(pci);
}

static inline enum dw_pcie_ltssm dw_pcie_get_ltssm(struct dw_pcie *pci)
{
u32 val;
Expand Down
35 changes: 35 additions & 0 deletions drivers/pci/controller/dwc/pcie-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ struct qcom_pcie_ops {
void (*host_post_init)(struct qcom_pcie *pcie);
void (*deinit)(struct qcom_pcie *pcie);
void (*ltssm_enable)(struct qcom_pcie *pcie);
void (*ltssm_disable)(struct qcom_pcie *pcie);
int (*config_sid)(struct qcom_pcie *pcie);
};

Expand Down Expand Up @@ -618,6 +619,37 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
return 0;
}

static int qcom_pcie_host_start_link(struct dw_pcie *pci)
{
struct qcom_pcie *pcie = to_qcom_pcie(pci);

qcom_ep_reset_deassert(pcie);

if (pcie->cfg->ops->ltssm_enable)
pcie->cfg->ops->ltssm_enable(pcie);

return 0;
}

static void qcom_pcie_host_stop_link(struct dw_pcie *pci)
{
struct qcom_pcie *pcie = to_qcom_pcie(pci);

qcom_ep_reset_assert(pcie);

if (pcie->cfg->ops->ltssm_disable)
pcie->cfg->ops->ltssm_disable(pcie);
}

static void qcom_pcie_2_3_2_ltssm_disable(struct qcom_pcie *pcie)
{
u32 val;

val = readl(pcie->parf + PARF_LTSSM);
val &= ~LTSSM_EN;
writel(val, pcie->parf + PARF_LTSSM);
}

static void qcom_pcie_2_3_2_ltssm_enable(struct qcom_pcie *pcie)
{
u32 val;
Expand Down Expand Up @@ -1362,6 +1394,7 @@ static const struct qcom_pcie_ops ops_1_9_0 = {
.host_post_init = qcom_pcie_host_post_init_2_7_0,
.deinit = qcom_pcie_deinit_2_7_0,
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
.ltssm_disable = qcom_pcie_2_3_2_ltssm_disable,
.config_sid = qcom_pcie_config_sid_1_9_0,
};

Expand Down Expand Up @@ -1429,6 +1462,8 @@ static const struct qcom_pcie_cfg cfg_sc8280xp = {
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = qcom_pcie_link_up,
.start_link = qcom_pcie_start_link,
.host_start_link = qcom_pcie_host_start_link,
.host_stop_link = qcom_pcie_host_stop_link,
};

static int qcom_pcie_icc_init(struct qcom_pcie *pcie)
Expand Down
7 changes: 4 additions & 3 deletions drivers/pci/hotplug/pciehp_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ void pciehp_handle_disable_request(struct controller *ctrl)

void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
{
int present, link_active;
bool link_active;
int present;

/*
* If the slot is on and presence or link has changed, turn it off.
Expand Down Expand Up @@ -260,8 +261,8 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
/* Turn the slot on if it's occupied or link is up */
mutex_lock(&ctrl->state_lock);
present = pciehp_card_present(ctrl);
link_active = pciehp_check_link_active(ctrl);
if (present <= 0 && link_active <= 0) {
link_active = pcie_link_is_active(ctrl->pcie->port);
if (present <= 0 && !link_active) {
if (ctrl->state == BLINKINGON_STATE) {
ctrl->state = OFF_STATE;
cancel_delayed_work(&ctrl->button_work);
Expand Down
31 changes: 2 additions & 29 deletions drivers/pci/hotplug/pciehp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,33 +221,6 @@ static void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask)
pcie_do_write_cmd(ctrl, cmd, mask, false);
}

/**
* pciehp_check_link_active() - Is the link active
* @ctrl: PCIe hotplug controller
*
* Check whether the downstream link is currently active. Note it is
* possible that the card is removed immediately after this so the
* caller may need to take it into account.
*
* If the hotplug controller itself is not available anymore returns
* %-ENODEV.
*/
int pciehp_check_link_active(struct controller *ctrl)
{
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 lnk_status;
int ret;

ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))
return -ENODEV;

ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);

return ret;
}

static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
{
u32 l;
Expand Down Expand Up @@ -467,7 +440,7 @@ int pciehp_card_present_or_link_active(struct controller *ctrl)
if (ret)
return ret;

return pciehp_check_link_active(ctrl);
return pcie_link_is_active(ctrl_dev(ctrl));
}

int pciehp_query_power_fault(struct controller *ctrl)
Expand Down Expand Up @@ -921,7 +894,7 @@ int pciehp_slot_reset(struct pcie_device *dev)
pcie_capability_write_word(dev->port, PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_DLLSC);

if (!pciehp_check_link_active(ctrl))
if (!pcie_link_is_active(ctrl_dev(ctrl)))
pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC);

return 0;
Expand Down
Loading