mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-26 05:50:53 +07:00
net: qcom/emac: Encapsulate sgmii ops under one structure
This patch introduces ops structure for sgmii, This by ensures that we do not need dummy functions in case of emulation platforms. Signed-off-by: Hemanth Puranik <hpuranik@codeaurora.org> Acked-by: Timur Tabi <timur@codeaurora.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cfb3e08968
commit
9e6881d366
@ -920,14 +920,13 @@ static void emac_mac_rx_descs_refill(struct emac_adapter *adpt,
|
||||
static void emac_adjust_link(struct net_device *netdev)
|
||||
{
|
||||
struct emac_adapter *adpt = netdev_priv(netdev);
|
||||
struct emac_sgmii *sgmii = &adpt->phy;
|
||||
struct phy_device *phydev = netdev->phydev;
|
||||
|
||||
if (phydev->link) {
|
||||
emac_mac_start(adpt);
|
||||
sgmii->link_up(adpt);
|
||||
emac_sgmii_link_change(adpt, true);
|
||||
} else {
|
||||
sgmii->link_down(adpt);
|
||||
emac_sgmii_link_change(adpt, false);
|
||||
emac_mac_stop(adpt);
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,46 @@
|
||||
|
||||
#define SERDES_START_WAIT_TIMES 100
|
||||
|
||||
int emac_sgmii_init(struct emac_adapter *adpt)
|
||||
{
|
||||
if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->init))
|
||||
return 0;
|
||||
|
||||
return adpt->phy.sgmii_ops->init(adpt);
|
||||
}
|
||||
|
||||
int emac_sgmii_open(struct emac_adapter *adpt)
|
||||
{
|
||||
if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->open))
|
||||
return 0;
|
||||
|
||||
return adpt->phy.sgmii_ops->open(adpt);
|
||||
}
|
||||
|
||||
void emac_sgmii_close(struct emac_adapter *adpt)
|
||||
{
|
||||
if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->close))
|
||||
return;
|
||||
|
||||
adpt->phy.sgmii_ops->close(adpt);
|
||||
}
|
||||
|
||||
int emac_sgmii_link_change(struct emac_adapter *adpt, bool link_state)
|
||||
{
|
||||
if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->link_change))
|
||||
return 0;
|
||||
|
||||
return adpt->phy.sgmii_ops->link_change(adpt, link_state);
|
||||
}
|
||||
|
||||
void emac_sgmii_reset(struct emac_adapter *adpt)
|
||||
{
|
||||
if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->reset))
|
||||
return;
|
||||
|
||||
adpt->phy.sgmii_ops->reset(adpt);
|
||||
}
|
||||
|
||||
/* Initialize the SGMII link between the internal and external PHYs. */
|
||||
static void emac_sgmii_link_init(struct emac_adapter *adpt)
|
||||
{
|
||||
@ -163,21 +203,21 @@ static void emac_sgmii_reset_prepare(struct emac_adapter *adpt)
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
void emac_sgmii_reset(struct emac_adapter *adpt)
|
||||
static void emac_sgmii_common_reset(struct emac_adapter *adpt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
emac_sgmii_reset_prepare(adpt);
|
||||
emac_sgmii_link_init(adpt);
|
||||
|
||||
ret = adpt->phy.initialize(adpt);
|
||||
ret = emac_sgmii_init(adpt);
|
||||
if (ret)
|
||||
netdev_err(adpt->netdev,
|
||||
"could not reinitialize internal PHY (error=%i)\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
static int emac_sgmii_open(struct emac_adapter *adpt)
|
||||
static int emac_sgmii_common_open(struct emac_adapter *adpt)
|
||||
{
|
||||
struct emac_sgmii *sgmii = &adpt->phy;
|
||||
int ret;
|
||||
@ -201,43 +241,53 @@ static int emac_sgmii_open(struct emac_adapter *adpt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emac_sgmii_close(struct emac_adapter *adpt)
|
||||
static void emac_sgmii_common_close(struct emac_adapter *adpt)
|
||||
{
|
||||
struct emac_sgmii *sgmii = &adpt->phy;
|
||||
|
||||
/* Make sure interrupts are disabled */
|
||||
writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
|
||||
free_irq(sgmii->irq, adpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The error interrupts are only valid after the link is up */
|
||||
static int emac_sgmii_link_up(struct emac_adapter *adpt)
|
||||
static int emac_sgmii_common_link_change(struct emac_adapter *adpt, bool linkup)
|
||||
{
|
||||
struct emac_sgmii *sgmii = &adpt->phy;
|
||||
int ret;
|
||||
|
||||
/* Clear and enable interrupts */
|
||||
ret = emac_sgmii_irq_clear(adpt, 0xff);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (linkup) {
|
||||
/* Clear and enable interrupts */
|
||||
ret = emac_sgmii_irq_clear(adpt, 0xff);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(SGMII_ISR_MASK, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
|
||||
writel(SGMII_ISR_MASK,
|
||||
sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
|
||||
} else {
|
||||
/* Disable interrupts */
|
||||
writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
|
||||
synchronize_irq(sgmii->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emac_sgmii_link_down(struct emac_adapter *adpt)
|
||||
{
|
||||
struct emac_sgmii *sgmii = &adpt->phy;
|
||||
static struct sgmii_ops qdf2432_ops = {
|
||||
.init = emac_sgmii_init_qdf2432,
|
||||
.open = emac_sgmii_common_open,
|
||||
.close = emac_sgmii_common_close,
|
||||
.link_change = emac_sgmii_common_link_change,
|
||||
.reset = emac_sgmii_common_reset,
|
||||
};
|
||||
|
||||
/* Disable interrupts */
|
||||
writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
|
||||
synchronize_irq(sgmii->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static struct sgmii_ops qdf2400_ops = {
|
||||
.init = emac_sgmii_init_qdf2400,
|
||||
.open = emac_sgmii_common_open,
|
||||
.close = emac_sgmii_common_close,
|
||||
.link_change = emac_sgmii_common_link_change,
|
||||
.reset = emac_sgmii_common_reset,
|
||||
};
|
||||
|
||||
static int emac_sgmii_acpi_match(struct device *dev, void *data)
|
||||
{
|
||||
@ -249,7 +299,7 @@ static int emac_sgmii_acpi_match(struct device *dev, void *data)
|
||||
{}
|
||||
};
|
||||
const struct acpi_device_id *id = acpi_match_device(match_table, dev);
|
||||
emac_sgmii_function *initialize = data;
|
||||
struct sgmii_ops **ops = data;
|
||||
|
||||
if (id) {
|
||||
acpi_handle handle = ACPI_HANDLE(dev);
|
||||
@ -270,10 +320,10 @@ static int emac_sgmii_acpi_match(struct device *dev, void *data)
|
||||
|
||||
switch (hrv) {
|
||||
case 1:
|
||||
*initialize = emac_sgmii_init_qdf2432;
|
||||
*ops = &qdf2432_ops;
|
||||
return 1;
|
||||
case 2:
|
||||
*initialize = emac_sgmii_init_qdf2400;
|
||||
*ops = &qdf2400_ops;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -294,14 +344,6 @@ static const struct of_device_id emac_sgmii_dt_match[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
/* Dummy function for systems without an internal PHY. This avoids having
|
||||
* to check for NULL pointers before calling the functions.
|
||||
*/
|
||||
static int emac_sgmii_dummy(struct emac_adapter *adpt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
|
||||
{
|
||||
struct platform_device *sgmii_pdev = NULL;
|
||||
@ -312,22 +354,11 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
|
||||
if (has_acpi_companion(&pdev->dev)) {
|
||||
struct device *dev;
|
||||
|
||||
dev = device_find_child(&pdev->dev, &phy->initialize,
|
||||
dev = device_find_child(&pdev->dev, &phy->sgmii_ops,
|
||||
emac_sgmii_acpi_match);
|
||||
|
||||
if (!dev) {
|
||||
dev_warn(&pdev->dev, "cannot find internal phy node\n");
|
||||
/* There is typically no internal PHY on emulation
|
||||
* systems, so if we can't find the node, assume
|
||||
* we are on an emulation system and stub-out
|
||||
* support for the internal PHY. These systems only
|
||||
* use ACPI.
|
||||
*/
|
||||
phy->open = emac_sgmii_dummy;
|
||||
phy->close = emac_sgmii_dummy;
|
||||
phy->link_up = emac_sgmii_dummy;
|
||||
phy->link_down = emac_sgmii_dummy;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -355,14 +386,9 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
|
||||
goto error_put_device;
|
||||
}
|
||||
|
||||
phy->initialize = (emac_sgmii_function)match->data;
|
||||
phy->sgmii_ops->init = match->data;
|
||||
}
|
||||
|
||||
phy->open = emac_sgmii_open;
|
||||
phy->close = emac_sgmii_close;
|
||||
phy->link_up = emac_sgmii_link_up;
|
||||
phy->link_down = emac_sgmii_link_down;
|
||||
|
||||
/* Base address is the first address */
|
||||
res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
@ -386,7 +412,7 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
|
||||
}
|
||||
}
|
||||
|
||||
ret = phy->initialize(adpt);
|
||||
ret = emac_sgmii_init(adpt);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
|
@ -16,36 +16,44 @@
|
||||
struct emac_adapter;
|
||||
struct platform_device;
|
||||
|
||||
typedef int (*emac_sgmii_function)(struct emac_adapter *adpt);
|
||||
/** emac_sgmii - internal emac phy
|
||||
* @init initialization function
|
||||
* @open called when the driver is opened
|
||||
* @close called when the driver is closed
|
||||
* @link_change called when the link state changes
|
||||
*/
|
||||
struct sgmii_ops {
|
||||
int (*init)(struct emac_adapter *adpt);
|
||||
int (*open)(struct emac_adapter *adpt);
|
||||
void (*close)(struct emac_adapter *adpt);
|
||||
int (*link_change)(struct emac_adapter *adpt, bool link_state);
|
||||
void (*reset)(struct emac_adapter *adpt);
|
||||
};
|
||||
|
||||
/** emac_sgmii - internal emac phy
|
||||
* @base base address
|
||||
* @digital per-lane digital block
|
||||
* @irq the interrupt number
|
||||
* @decode_error_count reference count of consecutive decode errors
|
||||
* @initialize initialization function
|
||||
* @open called when the driver is opened
|
||||
* @close called when the driver is closed
|
||||
* @link_up called when the link comes up
|
||||
* @link_down called when the link comes down
|
||||
* @sgmii_ops sgmii ops
|
||||
*/
|
||||
struct emac_sgmii {
|
||||
void __iomem *base;
|
||||
void __iomem *digital;
|
||||
unsigned int irq;
|
||||
atomic_t decode_error_count;
|
||||
emac_sgmii_function initialize;
|
||||
emac_sgmii_function open;
|
||||
emac_sgmii_function close;
|
||||
emac_sgmii_function link_up;
|
||||
emac_sgmii_function link_down;
|
||||
struct sgmii_ops *sgmii_ops;
|
||||
};
|
||||
|
||||
int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt);
|
||||
void emac_sgmii_reset(struct emac_adapter *adpt);
|
||||
|
||||
int emac_sgmii_init_fsm9900(struct emac_adapter *adpt);
|
||||
int emac_sgmii_init_qdf2432(struct emac_adapter *adpt);
|
||||
int emac_sgmii_init_qdf2400(struct emac_adapter *adpt);
|
||||
|
||||
int emac_sgmii_init(struct emac_adapter *adpt);
|
||||
int emac_sgmii_open(struct emac_adapter *adpt);
|
||||
void emac_sgmii_close(struct emac_adapter *adpt);
|
||||
int emac_sgmii_link_change(struct emac_adapter *adpt, bool link_state);
|
||||
void emac_sgmii_reset(struct emac_adapter *adpt);
|
||||
#endif
|
||||
|
@ -253,7 +253,7 @@ static int emac_open(struct net_device *netdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = adpt->phy.open(adpt);
|
||||
ret = emac_sgmii_open(adpt);
|
||||
if (ret) {
|
||||
emac_mac_rx_tx_rings_free_all(adpt);
|
||||
free_irq(irq->irq, irq);
|
||||
@ -264,7 +264,7 @@ static int emac_open(struct net_device *netdev)
|
||||
if (ret) {
|
||||
emac_mac_rx_tx_rings_free_all(adpt);
|
||||
free_irq(irq->irq, irq);
|
||||
adpt->phy.close(adpt);
|
||||
emac_sgmii_close(adpt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ static int emac_close(struct net_device *netdev)
|
||||
|
||||
mutex_lock(&adpt->reset_lock);
|
||||
|
||||
adpt->phy.close(adpt);
|
||||
emac_sgmii_close(adpt);
|
||||
emac_mac_down(adpt);
|
||||
emac_mac_rx_tx_rings_free_all(adpt);
|
||||
|
||||
@ -761,11 +761,10 @@ static void emac_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *netdev = dev_get_drvdata(&pdev->dev);
|
||||
struct emac_adapter *adpt = netdev_priv(netdev);
|
||||
struct emac_sgmii *sgmii = &adpt->phy;
|
||||
|
||||
if (netdev->flags & IFF_UP) {
|
||||
/* Closing the SGMII turns off its interrupts */
|
||||
sgmii->close(adpt);
|
||||
emac_sgmii_close(adpt);
|
||||
|
||||
/* Resetting the MAC turns off all DMA and its interrupts */
|
||||
emac_mac_reset(adpt);
|
||||
|
Loading…
Reference in New Issue
Block a user