Commit 7779f268 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-asp22-optimizations'

Justin Chen says:

====================
Support for ASP 2.2 and optimizations

ASP 2.2 adds some power savings during low power modes.

Also make various improvements when entering low power modes and
reduce MDIO traffic by hooking up interrupts.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fc809e1e cc7f105e
...@@ -15,6 +15,10 @@ description: Broadcom Ethernet controller first introduced with 72165 ...@@ -15,6 +15,10 @@ description: Broadcom Ethernet controller first introduced with 72165
properties: properties:
compatible: compatible:
oneOf: oneOf:
- items:
- enum:
- brcm,bcm74165b0-asp
- const: brcm,asp-v2.2
- items: - items:
- enum: - enum:
- brcm,bcm74165-asp - brcm,bcm74165-asp
......
...@@ -24,6 +24,7 @@ properties: ...@@ -24,6 +24,7 @@ properties:
- brcm,genet-mdio-v5 - brcm,genet-mdio-v5
- brcm,asp-v2.0-mdio - brcm,asp-v2.0-mdio
- brcm,asp-v2.1-mdio - brcm,asp-v2.1-mdio
- brcm,asp-v2.2-mdio
- brcm,unimac-mdio - brcm,unimac-mdio
reg: reg:
......
...@@ -31,6 +31,20 @@ static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask) ...@@ -31,6 +31,20 @@ static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask)
priv->irq_mask |= mask; priv->irq_mask |= mask;
} }
void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en)
{
struct bcmasp_priv *priv = intf->parent;
/* Only supported with internal phys */
if (!intf->internal_phy)
return;
if (en)
_intr2_mask_clear(priv, ASP_INTR2_PHY_EVENT(intf->channel));
else
_intr2_mask_set(priv, ASP_INTR2_PHY_EVENT(intf->channel));
}
void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en) void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en)
{ {
struct bcmasp_priv *priv = intf->parent; struct bcmasp_priv *priv = intf->parent;
...@@ -79,6 +93,9 @@ static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status) ...@@ -79,6 +93,9 @@ static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status)
__napi_schedule_irqoff(&intf->tx_napi); __napi_schedule_irqoff(&intf->tx_napi);
} }
} }
if (status & ASP_INTR2_PHY_EVENT(intf->channel))
phy_mac_interrupt(intf->ndev->phydev);
} }
static irqreturn_t bcmasp_isr(int irq, void *data) static irqreturn_t bcmasp_isr(int irq, void *data)
...@@ -972,7 +989,26 @@ static void bcmasp_core_init(struct bcmasp_priv *priv) ...@@ -972,7 +989,26 @@ static void bcmasp_core_init(struct bcmasp_priv *priv)
ASP_INTR2_CLEAR); ASP_INTR2_CLEAR);
} }
static void bcmasp_core_clock_select(struct bcmasp_priv *priv, bool slow) static void bcmasp_core_clock_select_many(struct bcmasp_priv *priv, bool slow)
{
u32 reg;
reg = ctrl2_core_rl(priv, ASP_CTRL2_CORE_CLOCK_SELECT);
if (slow)
reg &= ~ASP_CTRL2_CORE_CLOCK_SELECT_MAIN;
else
reg |= ASP_CTRL2_CORE_CLOCK_SELECT_MAIN;
ctrl2_core_wl(priv, reg, ASP_CTRL2_CORE_CLOCK_SELECT);
reg = ctrl2_core_rl(priv, ASP_CTRL2_CPU_CLOCK_SELECT);
if (slow)
reg &= ~ASP_CTRL2_CPU_CLOCK_SELECT_MAIN;
else
reg |= ASP_CTRL2_CPU_CLOCK_SELECT_MAIN;
ctrl2_core_wl(priv, reg, ASP_CTRL2_CPU_CLOCK_SELECT);
}
static void bcmasp_core_clock_select_one(struct bcmasp_priv *priv, bool slow)
{ {
u32 reg; u32 reg;
...@@ -1166,6 +1202,24 @@ static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv) ...@@ -1166,6 +1202,24 @@ static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv)
} }
} }
static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en)
{
u32 reg, phy_lpi_overwrite;
reg = rx_edpkt_core_rl(intf->parent, ASP_EDPKT_SPARE_REG);
phy_lpi_overwrite = intf->internal_phy ? ASP_EDPKT_SPARE_REG_EPHY_LPI :
ASP_EDPKT_SPARE_REG_GPHY_LPI;
if (en)
reg |= phy_lpi_overwrite;
else
reg &= ~phy_lpi_overwrite;
rx_edpkt_core_wl(intf->parent, reg, ASP_EDPKT_SPARE_REG);
usleep_range(50, 100);
}
static struct bcmasp_hw_info v20_hw_info = { static struct bcmasp_hw_info v20_hw_info = {
.rx_ctrl_flush = ASP_RX_CTRL_FLUSH, .rx_ctrl_flush = ASP_RX_CTRL_FLUSH,
.umac2fb = UMAC2FB_OFFSET, .umac2fb = UMAC2FB_OFFSET,
...@@ -1178,6 +1232,7 @@ static const struct bcmasp_plat_data v20_plat_data = { ...@@ -1178,6 +1232,7 @@ static const struct bcmasp_plat_data v20_plat_data = {
.init_wol = bcmasp_init_wol_per_intf, .init_wol = bcmasp_init_wol_per_intf,
.enable_wol = bcmasp_enable_wol_per_intf, .enable_wol = bcmasp_enable_wol_per_intf,
.destroy_wol = bcmasp_wol_irq_destroy_per_intf, .destroy_wol = bcmasp_wol_irq_destroy_per_intf,
.core_clock_select = bcmasp_core_clock_select_one,
.hw_info = &v20_hw_info, .hw_info = &v20_hw_info,
}; };
...@@ -1194,17 +1249,39 @@ static const struct bcmasp_plat_data v21_plat_data = { ...@@ -1194,17 +1249,39 @@ static const struct bcmasp_plat_data v21_plat_data = {
.init_wol = bcmasp_init_wol_shared, .init_wol = bcmasp_init_wol_shared,
.enable_wol = bcmasp_enable_wol_shared, .enable_wol = bcmasp_enable_wol_shared,
.destroy_wol = bcmasp_wol_irq_destroy_shared, .destroy_wol = bcmasp_wol_irq_destroy_shared,
.core_clock_select = bcmasp_core_clock_select_one,
.hw_info = &v21_hw_info,
};
static const struct bcmasp_plat_data v22_plat_data = {
.init_wol = bcmasp_init_wol_shared,
.enable_wol = bcmasp_enable_wol_shared,
.destroy_wol = bcmasp_wol_irq_destroy_shared,
.core_clock_select = bcmasp_core_clock_select_many,
.hw_info = &v21_hw_info, .hw_info = &v21_hw_info,
.eee_fixup = bcmasp_eee_fixup,
}; };
static void bcmasp_set_pdata(struct bcmasp_priv *priv, const struct bcmasp_plat_data *pdata)
{
priv->init_wol = pdata->init_wol;
priv->enable_wol = pdata->enable_wol;
priv->destroy_wol = pdata->destroy_wol;
priv->core_clock_select = pdata->core_clock_select;
priv->eee_fixup = pdata->eee_fixup;
priv->hw_info = pdata->hw_info;
}
static const struct of_device_id bcmasp_of_match[] = { static const struct of_device_id bcmasp_of_match[] = {
{ .compatible = "brcm,asp-v2.0", .data = &v20_plat_data }, { .compatible = "brcm,asp-v2.0", .data = &v20_plat_data },
{ .compatible = "brcm,asp-v2.1", .data = &v21_plat_data }, { .compatible = "brcm,asp-v2.1", .data = &v21_plat_data },
{ .compatible = "brcm,asp-v2.2", .data = &v22_plat_data },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, bcmasp_of_match); MODULE_DEVICE_TABLE(of, bcmasp_of_match);
static const struct of_device_id bcmasp_mdio_of_match[] = { static const struct of_device_id bcmasp_mdio_of_match[] = {
{ .compatible = "brcm,asp-v2.2-mdio", },
{ .compatible = "brcm,asp-v2.1-mdio", }, { .compatible = "brcm,asp-v2.1-mdio", },
{ .compatible = "brcm,asp-v2.0-mdio", }, { .compatible = "brcm,asp-v2.0-mdio", },
{ /* sentinel */ }, { /* sentinel */ },
...@@ -1265,16 +1342,13 @@ static int bcmasp_probe(struct platform_device *pdev) ...@@ -1265,16 +1342,13 @@ static int bcmasp_probe(struct platform_device *pdev)
if (!pdata) if (!pdata)
return dev_err_probe(dev, -EINVAL, "unable to find platform data\n"); return dev_err_probe(dev, -EINVAL, "unable to find platform data\n");
priv->init_wol = pdata->init_wol; bcmasp_set_pdata(priv, pdata);
priv->enable_wol = pdata->enable_wol;
priv->destroy_wol = pdata->destroy_wol;
priv->hw_info = pdata->hw_info;
/* Enable all clocks to ensure successful probing */ /* Enable all clocks to ensure successful probing */
bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
/* Switch to the main clock */ /* Switch to the main clock */
bcmasp_core_clock_select(priv, false); priv->core_clock_select(priv, false);
bcmasp_intr2_mask_set_all(priv); bcmasp_intr2_mask_set_all(priv);
bcmasp_intr2_clear_all(priv); bcmasp_intr2_clear_all(priv);
...@@ -1381,7 +1455,7 @@ static int __maybe_unused bcmasp_suspend(struct device *d) ...@@ -1381,7 +1455,7 @@ static int __maybe_unused bcmasp_suspend(struct device *d)
*/ */
bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE); bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE);
bcmasp_core_clock_select(priv, true); priv->core_clock_select(priv, true);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
...@@ -1399,7 +1473,7 @@ static int __maybe_unused bcmasp_resume(struct device *d) ...@@ -1399,7 +1473,7 @@ static int __maybe_unused bcmasp_resume(struct device *d)
return ret; return ret;
/* Switch to the main clock domain */ /* Switch to the main clock domain */
bcmasp_core_clock_select(priv, false); priv->core_clock_select(priv, false);
/* Re-enable all clocks for re-initialization */ /* Re-enable all clocks for re-initialization */
bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0); bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#define ASP_INTR2_TX_DESC(intr) BIT((intr) + 14) #define ASP_INTR2_TX_DESC(intr) BIT((intr) + 14)
#define ASP_INTR2_UMC0_WAKE BIT(22) #define ASP_INTR2_UMC0_WAKE BIT(22)
#define ASP_INTR2_UMC1_WAKE BIT(28) #define ASP_INTR2_UMC1_WAKE BIT(28)
#define ASP_INTR2_PHY_EVENT(intr) ((intr) ? BIT(30) | BIT(31) : \
BIT(24) | BIT(25))
#define ASP_WAKEUP_INTR2_OFFSET 0x1200 #define ASP_WAKEUP_INTR2_OFFSET 0x1200
#define ASP_WAKEUP_INTR2_STATUS 0x0 #define ASP_WAKEUP_INTR2_STATUS 0x0
...@@ -33,6 +35,12 @@ ...@@ -33,6 +35,12 @@
#define ASP_WAKEUP_INTR2_FILT_1 BIT(3) #define ASP_WAKEUP_INTR2_FILT_1 BIT(3)
#define ASP_WAKEUP_INTR2_FW BIT(4) #define ASP_WAKEUP_INTR2_FW BIT(4)
#define ASP_CTRL2_OFFSET 0x2000
#define ASP_CTRL2_CORE_CLOCK_SELECT 0x0
#define ASP_CTRL2_CORE_CLOCK_SELECT_MAIN BIT(0)
#define ASP_CTRL2_CPU_CLOCK_SELECT 0x4
#define ASP_CTRL2_CPU_CLOCK_SELECT_MAIN BIT(0)
#define ASP_TX_ANALYTICS_OFFSET 0x4c000 #define ASP_TX_ANALYTICS_OFFSET 0x4c000
#define ASP_TX_ANALYTICS_CTRL 0x0 #define ASP_TX_ANALYTICS_CTRL 0x0
...@@ -134,8 +142,11 @@ enum asp_rx_net_filter_block { ...@@ -134,8 +142,11 @@ enum asp_rx_net_filter_block {
#define ASP_EDPKT_RX_PKT_CNT 0x138 #define ASP_EDPKT_RX_PKT_CNT 0x138
#define ASP_EDPKT_HDR_EXTR_CNT 0x13c #define ASP_EDPKT_HDR_EXTR_CNT 0x13c
#define ASP_EDPKT_HDR_OUT_CNT 0x140 #define ASP_EDPKT_HDR_OUT_CNT 0x140
#define ASP_EDPKT_SPARE_REG 0x174
#define ASP_EDPKT_SPARE_REG_EPHY_LPI BIT(4)
#define ASP_EDPKT_SPARE_REG_GPHY_LPI BIT(3)
#define ASP_CTRL 0x101000 #define ASP_CTRL_OFFSET 0x101000
#define ASP_CTRL_ASP_SW_INIT 0x04 #define ASP_CTRL_ASP_SW_INIT 0x04
#define ASP_CTRL_ASP_SW_INIT_ACPUSS_CORE BIT(0) #define ASP_CTRL_ASP_SW_INIT_ACPUSS_CORE BIT(0)
#define ASP_CTRL_ASP_SW_INIT_ASP_TX BIT(1) #define ASP_CTRL_ASP_SW_INIT_ASP_TX BIT(1)
...@@ -306,6 +317,7 @@ struct bcmasp_intf { ...@@ -306,6 +317,7 @@ struct bcmasp_intf {
struct bcmasp_desc *rx_edpkt_cpu; struct bcmasp_desc *rx_edpkt_cpu;
dma_addr_t rx_edpkt_dma_addr; dma_addr_t rx_edpkt_dma_addr;
dma_addr_t rx_edpkt_dma_read; dma_addr_t rx_edpkt_dma_read;
dma_addr_t rx_edpkt_dma_valid;
/* RX buffer prefetcher ring*/ /* RX buffer prefetcher ring*/
void *rx_ring_cpu; void *rx_ring_cpu;
...@@ -372,6 +384,8 @@ struct bcmasp_plat_data { ...@@ -372,6 +384,8 @@ struct bcmasp_plat_data {
void (*init_wol)(struct bcmasp_priv *priv); void (*init_wol)(struct bcmasp_priv *priv);
void (*enable_wol)(struct bcmasp_intf *intf, bool en); void (*enable_wol)(struct bcmasp_intf *intf, bool en);
void (*destroy_wol)(struct bcmasp_priv *priv); void (*destroy_wol)(struct bcmasp_priv *priv);
void (*core_clock_select)(struct bcmasp_priv *priv, bool slow);
void (*eee_fixup)(struct bcmasp_intf *priv, bool en);
struct bcmasp_hw_info *hw_info; struct bcmasp_hw_info *hw_info;
}; };
...@@ -390,6 +404,8 @@ struct bcmasp_priv { ...@@ -390,6 +404,8 @@ struct bcmasp_priv {
void (*init_wol)(struct bcmasp_priv *priv); void (*init_wol)(struct bcmasp_priv *priv);
void (*enable_wol)(struct bcmasp_intf *intf, bool en); void (*enable_wol)(struct bcmasp_intf *intf, bool en);
void (*destroy_wol)(struct bcmasp_priv *priv); void (*destroy_wol)(struct bcmasp_priv *priv);
void (*core_clock_select)(struct bcmasp_priv *priv, bool slow);
void (*eee_fixup)(struct bcmasp_intf *intf, bool en);
void __iomem *base; void __iomem *base;
struct bcmasp_hw_info *hw_info; struct bcmasp_hw_info *hw_info;
...@@ -530,7 +546,8 @@ BCMASP_CORE_IO_MACRO(rx_analytics, ASP_RX_ANALYTICS_OFFSET); ...@@ -530,7 +546,8 @@ BCMASP_CORE_IO_MACRO(rx_analytics, ASP_RX_ANALYTICS_OFFSET);
BCMASP_CORE_IO_MACRO(rx_ctrl, ASP_RX_CTRL_OFFSET); BCMASP_CORE_IO_MACRO(rx_ctrl, ASP_RX_CTRL_OFFSET);
BCMASP_CORE_IO_MACRO(rx_filter, ASP_RX_FILTER_OFFSET); BCMASP_CORE_IO_MACRO(rx_filter, ASP_RX_FILTER_OFFSET);
BCMASP_CORE_IO_MACRO(rx_edpkt, ASP_EDPKT_OFFSET); BCMASP_CORE_IO_MACRO(rx_edpkt, ASP_EDPKT_OFFSET);
BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL); BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL_OFFSET);
BCMASP_CORE_IO_MACRO(ctrl2, ASP_CTRL2_OFFSET);
struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv, struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv,
struct device_node *ndev_dn, int i); struct device_node *ndev_dn, int i);
...@@ -541,6 +558,8 @@ void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en); ...@@ -541,6 +558,8 @@ void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en);
void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en); void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en);
void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en);
void bcmasp_flush_rx_port(struct bcmasp_intf *intf); void bcmasp_flush_rx_port(struct bcmasp_intf *intf);
extern const struct ethtool_ops bcmasp_ethtool_ops; extern const struct ethtool_ops bcmasp_ethtool_ops;
......
...@@ -382,6 +382,7 @@ static void bcmasp_netif_start(struct net_device *dev) ...@@ -382,6 +382,7 @@ static void bcmasp_netif_start(struct net_device *dev)
bcmasp_enable_rx_irq(intf, 1); bcmasp_enable_rx_irq(intf, 1);
bcmasp_enable_tx_irq(intf, 1); bcmasp_enable_tx_irq(intf, 1);
bcmasp_enable_phy_irq(intf, 1);
phy_start(dev->phydev); phy_start(dev->phydev);
} }
...@@ -674,40 +675,78 @@ static void bcmasp_adj_link(struct net_device *dev) ...@@ -674,40 +675,78 @@ static void bcmasp_adj_link(struct net_device *dev)
phy_print_status(phydev); phy_print_status(phydev);
} }
static int bcmasp_init_rx(struct bcmasp_intf *intf) static int bcmasp_alloc_buffers(struct bcmasp_intf *intf)
{ {
struct device *kdev = &intf->parent->pdev->dev; struct device *kdev = &intf->parent->pdev->dev;
struct page *buffer_pg; struct page *buffer_pg;
dma_addr_t dma;
void *p;
u32 reg;
int ret;
/* Alloc RX */
intf->rx_buf_order = get_order(RING_BUFFER_SIZE); intf->rx_buf_order = get_order(RING_BUFFER_SIZE);
buffer_pg = alloc_pages(GFP_KERNEL, intf->rx_buf_order); buffer_pg = alloc_pages(GFP_KERNEL, intf->rx_buf_order);
if (!buffer_pg) if (!buffer_pg)
return -ENOMEM; return -ENOMEM;
dma = dma_map_page(kdev, buffer_pg, 0, RING_BUFFER_SIZE,
DMA_FROM_DEVICE);
if (dma_mapping_error(kdev, dma)) {
__free_pages(buffer_pg, intf->rx_buf_order);
return -ENOMEM;
}
intf->rx_ring_cpu = page_to_virt(buffer_pg); intf->rx_ring_cpu = page_to_virt(buffer_pg);
intf->rx_ring_dma = dma; intf->rx_ring_dma = dma_map_page(kdev, buffer_pg, 0, RING_BUFFER_SIZE,
intf->rx_ring_dma_valid = intf->rx_ring_dma + RING_BUFFER_SIZE - 1; DMA_FROM_DEVICE);
if (dma_mapping_error(kdev, intf->rx_ring_dma))
goto free_rx_buffer;
intf->rx_edpkt_cpu = dma_alloc_coherent(kdev, DESC_RING_SIZE,
&intf->rx_edpkt_dma_addr, GFP_KERNEL);
if (!intf->rx_edpkt_cpu)
goto free_rx_buffer_dma;
/* Alloc TX */
intf->tx_spb_cpu = dma_alloc_coherent(kdev, DESC_RING_SIZE,
&intf->tx_spb_dma_addr, GFP_KERNEL);
if (!intf->tx_spb_cpu)
goto free_rx_edpkt_dma;
p = dma_alloc_coherent(kdev, DESC_RING_SIZE, &intf->rx_edpkt_dma_addr, intf->tx_cbs = kcalloc(DESC_RING_COUNT, sizeof(struct bcmasp_tx_cb),
GFP_KERNEL); GFP_KERNEL);
if (!p) { if (!intf->tx_cbs)
ret = -ENOMEM; goto free_tx_spb_dma;
goto free_rx_ring;
}
intf->rx_edpkt_cpu = p;
netif_napi_add(intf->ndev, &intf->rx_napi, bcmasp_rx_poll); return 0;
free_tx_spb_dma:
dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
intf->tx_spb_dma_addr);
free_rx_edpkt_dma:
dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu,
intf->rx_edpkt_dma_addr);
free_rx_buffer_dma:
dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
DMA_FROM_DEVICE);
free_rx_buffer:
__free_pages(buffer_pg, intf->rx_buf_order);
return -ENOMEM;
}
static void bcmasp_reclaim_free_buffers(struct bcmasp_intf *intf)
{
struct device *kdev = &intf->parent->pdev->dev;
/* RX buffers */
dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu,
intf->rx_edpkt_dma_addr);
dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
DMA_FROM_DEVICE);
__free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order);
/* TX buffers */
dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
intf->tx_spb_dma_addr);
kfree(intf->tx_cbs);
}
static void bcmasp_init_rx(struct bcmasp_intf *intf)
{
/* Restart from index 0 */
intf->rx_ring_dma_valid = intf->rx_ring_dma + RING_BUFFER_SIZE - 1;
intf->rx_edpkt_dma_valid = intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1);
intf->rx_edpkt_dma_read = intf->rx_edpkt_dma_addr; intf->rx_edpkt_dma_read = intf->rx_edpkt_dma_addr;
intf->rx_edpkt_index = 0; intf->rx_edpkt_index = 0;
...@@ -733,64 +772,23 @@ static int bcmasp_init_rx(struct bcmasp_intf *intf) ...@@ -733,64 +772,23 @@ static int bcmasp_init_rx(struct bcmasp_intf *intf)
rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_WRITE); rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_WRITE);
rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_READ); rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_READ);
rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_BASE); rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_BASE);
rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1), rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_valid, RX_EDPKT_DMA_END);
RX_EDPKT_DMA_END); rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_valid, RX_EDPKT_DMA_VALID);
rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1),
RX_EDPKT_DMA_VALID);
reg = UMAC2FB_CFG_DEFAULT_EN |
((intf->channel + 11) << UMAC2FB_CFG_CHID_SHIFT);
reg |= (0xd << UMAC2FB_CFG_OK_SEND_SHIFT);
umac2fb_wl(intf, reg, UMAC2FB_CFG);
return 0;
free_rx_ring:
dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
DMA_FROM_DEVICE);
__free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order);
return ret; umac2fb_wl(intf, UMAC2FB_CFG_DEFAULT_EN | ((intf->channel + 11) <<
UMAC2FB_CFG_CHID_SHIFT) | (0xd << UMAC2FB_CFG_OK_SEND_SHIFT),
UMAC2FB_CFG);
} }
static void bcmasp_reclaim_free_all_rx(struct bcmasp_intf *intf)
{
struct device *kdev = &intf->parent->pdev->dev;
dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu, static void bcmasp_init_tx(struct bcmasp_intf *intf)
intf->rx_edpkt_dma_addr);
dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
DMA_FROM_DEVICE);
__free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order);
}
static int bcmasp_init_tx(struct bcmasp_intf *intf)
{ {
struct device *kdev = &intf->parent->pdev->dev; /* Restart from index 0 */
void *p;
int ret;
p = dma_alloc_coherent(kdev, DESC_RING_SIZE, &intf->tx_spb_dma_addr,
GFP_KERNEL);
if (!p)
return -ENOMEM;
intf->tx_spb_cpu = p;
intf->tx_spb_dma_valid = intf->tx_spb_dma_addr + DESC_RING_SIZE - 1; intf->tx_spb_dma_valid = intf->tx_spb_dma_addr + DESC_RING_SIZE - 1;
intf->tx_spb_dma_read = intf->tx_spb_dma_addr; intf->tx_spb_dma_read = intf->tx_spb_dma_addr;
intf->tx_cbs = kcalloc(DESC_RING_COUNT, sizeof(struct bcmasp_tx_cb),
GFP_KERNEL);
if (!intf->tx_cbs) {
ret = -ENOMEM;
goto free_tx_spb;
}
intf->tx_spb_index = 0; intf->tx_spb_index = 0;
intf->tx_spb_clean_index = 0; intf->tx_spb_clean_index = 0;
netif_napi_add_tx(intf->ndev, &intf->tx_napi, bcmasp_tx_poll);
/* Make sure channels are disabled */ /* Make sure channels are disabled */
tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE); tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE);
tx_epkt_core_wl(intf, 0x0, TX_EPKT_C_CFG_MISC); tx_epkt_core_wl(intf, 0x0, TX_EPKT_C_CFG_MISC);
...@@ -806,26 +804,6 @@ static int bcmasp_init_tx(struct bcmasp_intf *intf) ...@@ -806,26 +804,6 @@ static int bcmasp_init_tx(struct bcmasp_intf *intf)
tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_BASE); tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_BASE);
tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_END); tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_END);
tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_VALID); tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_VALID);
return 0;
free_tx_spb:
dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
intf->tx_spb_dma_addr);
return ret;
}
static void bcmasp_reclaim_free_all_tx(struct bcmasp_intf *intf)
{
struct device *kdev = &intf->parent->pdev->dev;
/* Free descriptors */
dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
intf->tx_spb_dma_addr);
/* Free cbs */
kfree(intf->tx_cbs);
} }
static void bcmasp_ephy_enable_set(struct bcmasp_intf *intf, bool enable) static void bcmasp_ephy_enable_set(struct bcmasp_intf *intf, bool enable)
...@@ -913,12 +891,10 @@ static void bcmasp_netif_deinit(struct net_device *dev) ...@@ -913,12 +891,10 @@ static void bcmasp_netif_deinit(struct net_device *dev)
/* Disable interrupts */ /* Disable interrupts */
bcmasp_enable_tx_irq(intf, 0); bcmasp_enable_tx_irq(intf, 0);
bcmasp_enable_rx_irq(intf, 0); bcmasp_enable_rx_irq(intf, 0);
bcmasp_enable_phy_irq(intf, 0);
netif_napi_del(&intf->tx_napi); netif_napi_del(&intf->tx_napi);
bcmasp_reclaim_free_all_tx(intf);
netif_napi_del(&intf->rx_napi); netif_napi_del(&intf->rx_napi);
bcmasp_reclaim_free_all_rx(intf);
} }
static int bcmasp_stop(struct net_device *dev) static int bcmasp_stop(struct net_device *dev)
...@@ -932,6 +908,8 @@ static int bcmasp_stop(struct net_device *dev) ...@@ -932,6 +908,8 @@ static int bcmasp_stop(struct net_device *dev)
bcmasp_netif_deinit(dev); bcmasp_netif_deinit(dev);
bcmasp_reclaim_free_buffers(intf);
phy_disconnect(dev->phydev); phy_disconnect(dev->phydev);
/* Disable internal EPHY or external PHY */ /* Disable internal EPHY or external PHY */
...@@ -1052,6 +1030,9 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) ...@@ -1052,6 +1030,9 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
goto err_phy_disable; goto err_phy_disable;
} }
if (intf->internal_phy)
dev->phydev->irq = PHY_MAC_INTERRUPT;
/* Indicate that the MAC is responsible for PHY PM */ /* Indicate that the MAC is responsible for PHY PM */
phydev->mac_managed_pm = true; phydev->mac_managed_pm = true;
} else if (!intf->wolopts) { } else if (!intf->wolopts) {
...@@ -1073,17 +1054,12 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) ...@@ -1073,17 +1054,12 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
intf->old_link = -1; intf->old_link = -1;
intf->old_pause = -1; intf->old_pause = -1;
ret = bcmasp_init_tx(intf); bcmasp_init_tx(intf);
if (ret) netif_napi_add_tx(intf->ndev, &intf->tx_napi, bcmasp_tx_poll);
goto err_phy_disconnect;
/* Turn on asp */
bcmasp_enable_tx(intf, 1); bcmasp_enable_tx(intf, 1);
ret = bcmasp_init_rx(intf); bcmasp_init_rx(intf);
if (ret) netif_napi_add(intf->ndev, &intf->rx_napi, bcmasp_rx_poll);
goto err_reclaim_tx;
bcmasp_enable_rx(intf, 1); bcmasp_enable_rx(intf, 1);
/* Turn on UniMAC TX/RX */ /* Turn on UniMAC TX/RX */
...@@ -1097,12 +1073,6 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect) ...@@ -1097,12 +1073,6 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
return 0; return 0;
err_reclaim_tx:
netif_napi_del(&intf->tx_napi);
bcmasp_reclaim_free_all_tx(intf);
err_phy_disconnect:
if (phydev)
phy_disconnect(phydev);
err_phy_disable: err_phy_disable:
if (intf->internal_phy) if (intf->internal_phy)
bcmasp_ephy_enable_set(intf, false); bcmasp_ephy_enable_set(intf, false);
...@@ -1118,13 +1088,24 @@ static int bcmasp_open(struct net_device *dev) ...@@ -1118,13 +1088,24 @@ static int bcmasp_open(struct net_device *dev)
netif_dbg(intf, ifup, dev, "bcmasp open\n"); netif_dbg(intf, ifup, dev, "bcmasp open\n");
ret = clk_prepare_enable(intf->parent->clk); ret = bcmasp_alloc_buffers(intf);
if (ret) if (ret)
return ret; return ret;
ret = bcmasp_netif_init(dev, true); ret = clk_prepare_enable(intf->parent->clk);
if (ret) if (ret)
goto err_free_mem;
ret = bcmasp_netif_init(dev, true);
if (ret) {
clk_disable_unprepare(intf->parent->clk); clk_disable_unprepare(intf->parent->clk);
goto err_free_mem;
}
return ret;
err_free_mem:
bcmasp_reclaim_free_buffers(intf);
return ret; return ret;
} }
...@@ -1333,6 +1314,9 @@ static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf) ...@@ -1333,6 +1314,9 @@ static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf)
ASP_WAKEUP_INTR2_MASK_CLEAR); ASP_WAKEUP_INTR2_MASK_CLEAR);
} }
if (intf->eee.eee_enabled && intf->parent->eee_fixup)
intf->parent->eee_fixup(intf, true);
netif_dbg(intf, wol, ndev, "entered WOL mode\n"); netif_dbg(intf, wol, ndev, "entered WOL mode\n");
} }
...@@ -1381,6 +1365,9 @@ static void bcmasp_resume_from_wol(struct bcmasp_intf *intf) ...@@ -1381,6 +1365,9 @@ static void bcmasp_resume_from_wol(struct bcmasp_intf *intf)
{ {
u32 reg; u32 reg;
if (intf->eee.eee_enabled && intf->parent->eee_fixup)
intf->parent->eee_fixup(intf, false);
reg = umac_rl(intf, UMC_MPD_CTRL); reg = umac_rl(intf, UMC_MPD_CTRL);
reg &= ~UMC_MPD_CTRL_MPD_EN; reg &= ~UMC_MPD_CTRL_MPD_EN;
umac_wl(intf, reg, UMC_MPD_CTRL); umac_wl(intf, reg, UMC_MPD_CTRL);
......
...@@ -334,6 +334,7 @@ static SIMPLE_DEV_PM_OPS(unimac_mdio_pm_ops, ...@@ -334,6 +334,7 @@ static SIMPLE_DEV_PM_OPS(unimac_mdio_pm_ops,
NULL, unimac_mdio_resume); NULL, unimac_mdio_resume);
static const struct of_device_id unimac_mdio_ids[] = { static const struct of_device_id unimac_mdio_ids[] = {
{ .compatible = "brcm,asp-v2.2-mdio", },
{ .compatible = "brcm,asp-v2.1-mdio", }, { .compatible = "brcm,asp-v2.1-mdio", },
{ .compatible = "brcm,asp-v2.0-mdio", }, { .compatible = "brcm,asp-v2.0-mdio", },
{ .compatible = "brcm,genet-mdio-v5", }, { .compatible = "brcm,genet-mdio-v5", },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment