Commit e8f3f705 authored by David S. Miller's avatar David S. Miller

Merge branch 'netcp-K2G-SoC-support'

Murali Karicheri says:

====================
Add support for netcp driver on K2G SoC

K2G SoC is another variant of Keystone family of SoCs. This patch
series add support for NetCP driver on this SoC. The QMSS found on
K2G SoC is a cut down version of the QMSS found on other keystone
devices with less number of queues, internal link ram etc. The patch
series has 2 patch sets that goes into the drivers/soc and the
rest has to be applied to net sub system. Please review and merge
if this looks good.

K2G TRM is located at http://www.ti.com/lit/ug/spruhy8g/spruhy8g.pdf
Thanks

The boot logs on K2G ICE board (tftp boot over Ethernet and from mmc)
https://pastebin.ubuntu.com/p/yvZ6drFhkW/

The boot logs on K2G GP board (tftp boot over Ethernet and from mmc)
https://pastebin.ubuntu.com/p/QTr6K7s4Zp/

Also regressed boot on K2HK and K2L EVMs as we have modified GBE
version detection logic (K2E uses same version of NetCP as in K2L.
So regression on one of them is needed).

Boot log on K2L and K2HK EVMs are at
https://pastebin.ubuntu.com/p/N9DBdPjbvR/

This series applies to net-next master branch.

Change history:
  v4 - ready for merge to net-next
       Folded the series "Add promiscous mode support in k2g network driver"
       into this.
       Fixed a typo in 5/11 (sgmii to rgmii) based on TI internal comment
       Reworked 4/11 and title changed to reflect additional changes to
       exclude sgmii configuration code for 2U cpsw. Use IS_SS_ID_2U()
       macro for customization.
       Added Reviewed-by from Rob Herring against 1/13
  v3 - Addressed comments from Andrew Lunn and Grygorii Strashko
       against v2.
  v2 - Addressed following comments on initial version
       - split patch 3/5 to multiple patches from Andrew Lunn
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0565de29 8585661b
...@@ -17,7 +17,8 @@ pool management. ...@@ -17,7 +17,8 @@ pool management.
Required properties: Required properties:
- compatible : Must be "ti,keystone-navigator-qmss"; - compatible : Must be "ti,keystone-navigator-qmss".
: Must be "ti,66ak2g-navss-qm" for QMSS on K2G SoC.
- clocks : phandle to the reference clock for this device. - clocks : phandle to the reference clock for this device.
- queue-range : <start number> total range of queue numbers for the device. - queue-range : <start number> total range of queue numbers for the device.
- linkram0 : <address size> for internal link ram, where size is the total - linkram0 : <address size> for internal link ram, where size is the total
...@@ -39,6 +40,12 @@ Required properties: ...@@ -39,6 +40,12 @@ Required properties:
- Descriptor memory setup region. - Descriptor memory setup region.
- Queue Management/Queue Proxy region for queue Push. - Queue Management/Queue Proxy region for queue Push.
- Queue Management/Queue Proxy region for queue Pop. - Queue Management/Queue Proxy region for queue Pop.
For QMSS on K2G SoC, following QM reg indexes are used in that order
- Queue Peek region.
- Queue configuration region.
- Queue Management/Queue Proxy region for queue Push/Pop.
- queue-pools : child node classifying the queue ranges into pools. - queue-pools : child node classifying the queue ranges into pools.
Queue ranges are grouped into 3 type of pools: Queue ranges are grouped into 3 type of pools:
- qpend : pool of qpend(interruptible) queues - qpend : pool of qpend(interruptible) queues
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#define SGMII_LINK_MAC_MAC_FORCED 2 #define SGMII_LINK_MAC_MAC_FORCED 2
#define SGMII_LINK_MAC_FIBER 3 #define SGMII_LINK_MAC_FIBER 3
#define SGMII_LINK_MAC_PHY_NO_MDIO 4 #define SGMII_LINK_MAC_PHY_NO_MDIO 4
#define RGMII_LINK_MAC_PHY 5
#define RGMII_LINK_MAC_PHY_NO_MDIO 7
#define XGMII_LINK_MAC_PHY 10 #define XGMII_LINK_MAC_PHY 10
#define XGMII_LINK_MAC_MAC_FORCED 11 #define XGMII_LINK_MAC_MAC_FORCED 11
...@@ -212,6 +214,7 @@ struct netcp_module { ...@@ -212,6 +214,7 @@ struct netcp_module {
int (*add_vid)(void *intf_priv, int vid); int (*add_vid)(void *intf_priv, int vid);
int (*del_vid)(void *intf_priv, int vid); int (*del_vid)(void *intf_priv, int vid);
int (*ioctl)(void *intf_priv, struct ifreq *req, int cmd); int (*ioctl)(void *intf_priv, struct ifreq *req, int cmd);
int (*set_rx_mode)(void *intf_priv, bool promisc);
/* used internally */ /* used internally */
struct list_head module_list; struct list_head module_list;
......
...@@ -1509,6 +1509,24 @@ static void netcp_addr_sweep_add(struct netcp_intf *netcp) ...@@ -1509,6 +1509,24 @@ static void netcp_addr_sweep_add(struct netcp_intf *netcp)
} }
} }
static int netcp_set_promiscuous(struct netcp_intf *netcp, bool promisc)
{
struct netcp_intf_modpriv *priv;
struct netcp_module *module;
int error;
for_each_module(netcp, priv) {
module = priv->netcp_module;
if (!module->set_rx_mode)
continue;
error = module->set_rx_mode(priv->module_priv, promisc);
if (error)
return error;
}
return 0;
}
static void netcp_set_rx_mode(struct net_device *ndev) static void netcp_set_rx_mode(struct net_device *ndev)
{ {
struct netcp_intf *netcp = netdev_priv(ndev); struct netcp_intf *netcp = netdev_priv(ndev);
...@@ -1538,6 +1556,7 @@ static void netcp_set_rx_mode(struct net_device *ndev) ...@@ -1538,6 +1556,7 @@ static void netcp_set_rx_mode(struct net_device *ndev)
/* finally sweep and callout into modules */ /* finally sweep and callout into modules */
netcp_addr_sweep_del(netcp); netcp_addr_sweep_del(netcp);
netcp_addr_sweep_add(netcp); netcp_addr_sweep_add(netcp);
netcp_set_promiscuous(netcp, promisc);
spin_unlock(&netcp->lock); spin_unlock(&netcp->lock);
} }
...@@ -2155,8 +2174,13 @@ static int netcp_probe(struct platform_device *pdev) ...@@ -2155,8 +2174,13 @@ static int netcp_probe(struct platform_device *pdev)
struct device_node *child, *interfaces; struct device_node *child, *interfaces;
struct netcp_device *netcp_device; struct netcp_device *netcp_device;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct netcp_module *module;
int ret; int ret;
if (!knav_dma_device_ready() ||
!knav_qmss_device_ready())
return -EPROBE_DEFER;
if (!node) { if (!node) {
dev_err(dev, "could not find device info\n"); dev_err(dev, "could not find device info\n");
return -ENODEV; return -ENODEV;
...@@ -2203,6 +2227,14 @@ static int netcp_probe(struct platform_device *pdev) ...@@ -2203,6 +2227,14 @@ static int netcp_probe(struct platform_device *pdev)
/* Add the device instance to the list */ /* Add the device instance to the list */
list_add_tail(&netcp_device->device_list, &netcp_devices); list_add_tail(&netcp_device->device_list, &netcp_devices);
/* Probe & attach any modules already registered */
mutex_lock(&netcp_modules_lock);
for_each_netcp_module(module) {
ret = netcp_module_probe(netcp_device, module);
if (ret < 0)
dev_err(dev, "module(%s) probe failed\n", module->name);
}
mutex_unlock(&netcp_modules_lock);
return 0; return 0;
probe_quit_interface: probe_quit_interface:
......
This diff is collapsed.
...@@ -134,6 +134,13 @@ struct knav_dma_chan { ...@@ -134,6 +134,13 @@ struct knav_dma_chan {
static struct knav_dma_pool_device *kdev; static struct knav_dma_pool_device *kdev;
static bool device_ready;
bool knav_dma_device_ready(void)
{
return device_ready;
}
EXPORT_SYMBOL_GPL(knav_dma_device_ready);
static bool check_config(struct knav_dma_chan *chan, struct knav_dma_cfg *cfg) static bool check_config(struct knav_dma_chan *chan, struct knav_dma_cfg *cfg)
{ {
if (!memcmp(&chan->cfg, cfg, sizeof(*cfg))) if (!memcmp(&chan->cfg, cfg, sizeof(*cfg)))
...@@ -773,6 +780,7 @@ static int knav_dma_probe(struct platform_device *pdev) ...@@ -773,6 +780,7 @@ static int knav_dma_probe(struct platform_device *pdev)
debugfs_create_file("knav_dma", S_IFREG | S_IRUGO, NULL, NULL, debugfs_create_file("knav_dma", S_IFREG | S_IRUGO, NULL, NULL,
&knav_dma_debug_ops); &knav_dma_debug_ops);
device_ready = true;
return ret; return ret;
} }
......
...@@ -292,6 +292,11 @@ struct knav_queue { ...@@ -292,6 +292,11 @@ struct knav_queue {
struct list_head list; struct list_head list;
}; };
enum qmss_version {
QMSS,
QMSS_66AK2G,
};
struct knav_device { struct knav_device {
struct device *dev; struct device *dev;
unsigned base_id; unsigned base_id;
...@@ -305,6 +310,7 @@ struct knav_device { ...@@ -305,6 +310,7 @@ struct knav_device {
struct list_head pools; struct list_head pools;
struct list_head pdsps; struct list_head pdsps;
struct list_head qmgrs; struct list_head qmgrs;
enum qmss_version version;
}; };
struct knav_range_ops { struct knav_range_ops {
......
...@@ -42,6 +42,15 @@ static DEFINE_MUTEX(knav_dev_lock); ...@@ -42,6 +42,15 @@ static DEFINE_MUTEX(knav_dev_lock);
#define KNAV_QUEUE_PUSH_REG_INDEX 4 #define KNAV_QUEUE_PUSH_REG_INDEX 4
#define KNAV_QUEUE_POP_REG_INDEX 5 #define KNAV_QUEUE_POP_REG_INDEX 5
/* Queue manager register indices in DTS for QMSS in K2G NAVSS.
* There are no status and vbusm push registers on this version
* of QMSS. Push registers are same as pop, So all indices above 1
* are to be re-defined
*/
#define KNAV_L_QUEUE_CONFIG_REG_INDEX 1
#define KNAV_L_QUEUE_REGION_REG_INDEX 2
#define KNAV_L_QUEUE_PUSH_REG_INDEX 3
/* PDSP register indices in DTS */ /* PDSP register indices in DTS */
#define KNAV_QUEUE_PDSP_IRAM_REG_INDEX 0 #define KNAV_QUEUE_PDSP_IRAM_REG_INDEX 0
#define KNAV_QUEUE_PDSP_REGS_REG_INDEX 1 #define KNAV_QUEUE_PDSP_REGS_REG_INDEX 1
...@@ -65,6 +74,13 @@ static DEFINE_MUTEX(knav_dev_lock); ...@@ -65,6 +74,13 @@ static DEFINE_MUTEX(knav_dev_lock);
*/ */
const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"};
static bool device_ready;
bool knav_qmss_device_ready(void)
{
return device_ready;
}
EXPORT_SYMBOL_GPL(knav_qmss_device_ready);
/** /**
* knav_queue_notify: qmss queue notfier call * knav_queue_notify: qmss queue notfier call
* *
...@@ -1169,8 +1185,12 @@ static int knav_queue_setup_link_ram(struct knav_device *kdev) ...@@ -1169,8 +1185,12 @@ static int knav_queue_setup_link_ram(struct knav_device *kdev)
dev_dbg(kdev->dev, "linkram0: dma:%pad, virt:%p, size:%x\n", dev_dbg(kdev->dev, "linkram0: dma:%pad, virt:%p, size:%x\n",
&block->dma, block->virt, block->size); &block->dma, block->virt, block->size);
writel_relaxed((u32)block->dma, &qmgr->reg_config->link_ram_base0); writel_relaxed((u32)block->dma, &qmgr->reg_config->link_ram_base0);
writel_relaxed(block->size, &qmgr->reg_config->link_ram_size0); if (kdev->version == QMSS_66AK2G)
writel_relaxed(block->size,
&qmgr->reg_config->link_ram_size0);
else
writel_relaxed(block->size - 1,
&qmgr->reg_config->link_ram_size0);
block++; block++;
if (!block->size) if (!block->size)
continue; continue;
...@@ -1387,42 +1407,64 @@ static int knav_queue_init_qmgrs(struct knav_device *kdev, ...@@ -1387,42 +1407,64 @@ static int knav_queue_init_qmgrs(struct knav_device *kdev,
qmgr->reg_peek = qmgr->reg_peek =
knav_queue_map_reg(kdev, child, knav_queue_map_reg(kdev, child,
KNAV_QUEUE_PEEK_REG_INDEX); KNAV_QUEUE_PEEK_REG_INDEX);
qmgr->reg_status =
knav_queue_map_reg(kdev, child, if (kdev->version == QMSS) {
KNAV_QUEUE_STATUS_REG_INDEX); qmgr->reg_status =
knav_queue_map_reg(kdev, child,
KNAV_QUEUE_STATUS_REG_INDEX);
}
qmgr->reg_config = qmgr->reg_config =
knav_queue_map_reg(kdev, child, knav_queue_map_reg(kdev, child,
(kdev->version == QMSS_66AK2G) ?
KNAV_L_QUEUE_CONFIG_REG_INDEX :
KNAV_QUEUE_CONFIG_REG_INDEX); KNAV_QUEUE_CONFIG_REG_INDEX);
qmgr->reg_region = qmgr->reg_region =
knav_queue_map_reg(kdev, child, knav_queue_map_reg(kdev, child,
(kdev->version == QMSS_66AK2G) ?
KNAV_L_QUEUE_REGION_REG_INDEX :
KNAV_QUEUE_REGION_REG_INDEX); KNAV_QUEUE_REGION_REG_INDEX);
qmgr->reg_push = qmgr->reg_push =
knav_queue_map_reg(kdev, child, knav_queue_map_reg(kdev, child,
KNAV_QUEUE_PUSH_REG_INDEX); (kdev->version == QMSS_66AK2G) ?
qmgr->reg_pop = KNAV_L_QUEUE_PUSH_REG_INDEX :
knav_queue_map_reg(kdev, child, KNAV_QUEUE_PUSH_REG_INDEX);
KNAV_QUEUE_POP_REG_INDEX);
if (kdev->version == QMSS) {
qmgr->reg_pop =
knav_queue_map_reg(kdev, child,
KNAV_QUEUE_POP_REG_INDEX);
}
if (IS_ERR(qmgr->reg_peek) || IS_ERR(qmgr->reg_status) || if (IS_ERR(qmgr->reg_peek) ||
((kdev->version == QMSS) &&
(IS_ERR(qmgr->reg_status) || IS_ERR(qmgr->reg_pop))) ||
IS_ERR(qmgr->reg_config) || IS_ERR(qmgr->reg_region) || IS_ERR(qmgr->reg_config) || IS_ERR(qmgr->reg_region) ||
IS_ERR(qmgr->reg_push) || IS_ERR(qmgr->reg_pop)) { IS_ERR(qmgr->reg_push)) {
dev_err(dev, "failed to map qmgr regs\n"); dev_err(dev, "failed to map qmgr regs\n");
if (kdev->version == QMSS) {
if (!IS_ERR(qmgr->reg_status))
devm_iounmap(dev, qmgr->reg_status);
if (!IS_ERR(qmgr->reg_pop))
devm_iounmap(dev, qmgr->reg_pop);
}
if (!IS_ERR(qmgr->reg_peek)) if (!IS_ERR(qmgr->reg_peek))
devm_iounmap(dev, qmgr->reg_peek); devm_iounmap(dev, qmgr->reg_peek);
if (!IS_ERR(qmgr->reg_status))
devm_iounmap(dev, qmgr->reg_status);
if (!IS_ERR(qmgr->reg_config)) if (!IS_ERR(qmgr->reg_config))
devm_iounmap(dev, qmgr->reg_config); devm_iounmap(dev, qmgr->reg_config);
if (!IS_ERR(qmgr->reg_region)) if (!IS_ERR(qmgr->reg_region))
devm_iounmap(dev, qmgr->reg_region); devm_iounmap(dev, qmgr->reg_region);
if (!IS_ERR(qmgr->reg_push)) if (!IS_ERR(qmgr->reg_push))
devm_iounmap(dev, qmgr->reg_push); devm_iounmap(dev, qmgr->reg_push);
if (!IS_ERR(qmgr->reg_pop))
devm_iounmap(dev, qmgr->reg_pop);
devm_kfree(dev, qmgr); devm_kfree(dev, qmgr);
continue; continue;
} }
/* Use same push register for pop as well */
if (kdev->version == QMSS_66AK2G)
qmgr->reg_pop = qmgr->reg_push;
list_add_tail(&qmgr->list, &kdev->qmgrs); list_add_tail(&qmgr->list, &kdev->qmgrs);
dev_info(dev, "added qmgr start queue %d, num of queues %d, reg_peek %p, reg_status %p, reg_config %p, reg_region %p, reg_push %p, reg_pop %p\n", dev_info(dev, "added qmgr start queue %d, num of queues %d, reg_peek %p, reg_status %p, reg_config %p, reg_region %p, reg_push %p, reg_pop %p\n",
qmgr->start_queue, qmgr->num_queues, qmgr->start_queue, qmgr->num_queues,
...@@ -1681,10 +1723,24 @@ static int knav_queue_init_queues(struct knav_device *kdev) ...@@ -1681,10 +1723,24 @@ static int knav_queue_init_queues(struct knav_device *kdev)
return 0; return 0;
} }
/* Match table for of_platform binding */
static const struct of_device_id keystone_qmss_of_match[] = {
{
.compatible = "ti,keystone-navigator-qmss",
},
{
.compatible = "ti,66ak2g-navss-qm",
.data = (void *)QMSS_66AK2G,
},
{},
};
MODULE_DEVICE_TABLE(of, keystone_qmss_of_match);
static int knav_queue_probe(struct platform_device *pdev) static int knav_queue_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct device_node *qmgrs, *queue_pools, *regions, *pdsps; struct device_node *qmgrs, *queue_pools, *regions, *pdsps;
const struct of_device_id *match;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
u32 temp[2]; u32 temp[2];
int ret; int ret;
...@@ -1700,6 +1756,10 @@ static int knav_queue_probe(struct platform_device *pdev) ...@@ -1700,6 +1756,10 @@ static int knav_queue_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
match = of_match_device(of_match_ptr(keystone_qmss_of_match), dev);
if (match && match->data)
kdev->version = QMSS_66AK2G;
platform_set_drvdata(pdev, kdev); platform_set_drvdata(pdev, kdev);
kdev->dev = dev; kdev->dev = dev;
INIT_LIST_HEAD(&kdev->queue_ranges); INIT_LIST_HEAD(&kdev->queue_ranges);
...@@ -1796,6 +1856,7 @@ static int knav_queue_probe(struct platform_device *pdev) ...@@ -1796,6 +1856,7 @@ static int knav_queue_probe(struct platform_device *pdev)
debugfs_create_file("qmss", S_IFREG | S_IRUGO, NULL, NULL, debugfs_create_file("qmss", S_IFREG | S_IRUGO, NULL, NULL,
&knav_queue_debug_ops); &knav_queue_debug_ops);
device_ready = true;
return 0; return 0;
err: err:
...@@ -1815,13 +1876,6 @@ static int knav_queue_remove(struct platform_device *pdev) ...@@ -1815,13 +1876,6 @@ static int knav_queue_remove(struct platform_device *pdev)
return 0; return 0;
} }
/* Match table for of_platform binding */
static struct of_device_id keystone_qmss_of_match[] = {
{ .compatible = "ti,keystone-navigator-qmss", },
{},
};
MODULE_DEVICE_TABLE(of, keystone_qmss_of_match);
static struct platform_driver keystone_qmss_driver = { static struct platform_driver keystone_qmss_driver = {
.probe = knav_queue_probe, .probe = knav_queue_probe,
.remove = knav_queue_remove, .remove = knav_queue_remove,
......
...@@ -167,6 +167,8 @@ struct knav_dma_desc { ...@@ -167,6 +167,8 @@ struct knav_dma_desc {
void *knav_dma_open_channel(struct device *dev, const char *name, void *knav_dma_open_channel(struct device *dev, const char *name,
struct knav_dma_cfg *config); struct knav_dma_cfg *config);
void knav_dma_close_channel(void *channel); void knav_dma_close_channel(void *channel);
int knav_dma_get_flow(void *channel);
bool knav_dma_device_ready(void);
#else #else
static inline void *knav_dma_open_channel(struct device *dev, const char *name, static inline void *knav_dma_open_channel(struct device *dev, const char *name,
struct knav_dma_cfg *config) struct knav_dma_cfg *config)
...@@ -176,6 +178,16 @@ static inline void *knav_dma_open_channel(struct device *dev, const char *name, ...@@ -176,6 +178,16 @@ static inline void *knav_dma_open_channel(struct device *dev, const char *name,
static inline void knav_dma_close_channel(void *channel) static inline void knav_dma_close_channel(void *channel)
{} {}
static inline int knav_dma_get_flow(void *channel)
{
return -EINVAL;
}
static inline bool knav_dma_device_ready(void)
{
return false;
}
#endif #endif
#endif /* __SOC_TI_KEYSTONE_NAVIGATOR_DMA_H__ */ #endif /* __SOC_TI_KEYSTONE_NAVIGATOR_DMA_H__ */
...@@ -86,5 +86,6 @@ int knav_pool_desc_map(void *ph, void *desc, unsigned size, ...@@ -86,5 +86,6 @@ int knav_pool_desc_map(void *ph, void *desc, unsigned size,
void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz); void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz);
dma_addr_t knav_pool_desc_virt_to_dma(void *ph, void *virt); dma_addr_t knav_pool_desc_virt_to_dma(void *ph, void *virt);
void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma); void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma);
bool knav_qmss_device_ready(void);
#endif /* __SOC_TI_KNAV_QMSS_H__ */ #endif /* __SOC_TI_KNAV_QMSS_H__ */
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