Skip to content

Commit

Permalink
net: qcom/emac: Encapsulate sgmii ops under one structure
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hemanth Puranik authored and David S. Miller committed May 16, 2018
1 parent cfb3e08 commit 9e6881d
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 71 deletions.
5 changes: 2 additions & 3 deletions drivers/net/ethernet/qualcomm/emac/emac-mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
128 changes: 77 additions & 51 deletions drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;

/* Disable interrupts */
writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
synchronize_irq(sgmii->irq);
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,
};

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)
{
Expand All @@ -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);
Expand All @@ -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;
}
}
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand All @@ -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;

Expand Down
32 changes: 20 additions & 12 deletions drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 4 additions & 5 deletions drivers/net/ethernet/qualcomm/emac/emac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}

Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 9e6881d

Please sign in to comment.