[qca-ssdk]: support link change interrupt for ap148.
Change-Id: I27d17dca074a0cdbca493318c55d83ea4d908d9f
Signed-off-by: Liu Zhongjian <zhongjia@codeaurora.org>
diff --git a/include/init/ssdk_plat.h b/include/init/ssdk_plat.h
index 6912534..963beed 100755
--- a/include/init/ssdk_plat.h
+++ b/include/init/ssdk_plat.h
@@ -231,6 +231,8 @@
a_uint16_t addr, a_uint16_t data);
sw_error_t (*phy_write)(a_uint32_t dev_id, a_uint32_t phy_addr,
a_uint32_t reg, a_uint16_t data);
+ sw_error_t (*phy_read)(a_uint32_t dev_id, a_uint32_t phy_addr,
+ a_uint32_t reg, a_uint16_t* data);
bool init;
struct mutex reg_mutex;
@@ -238,7 +240,6 @@
struct delayed_work mib_dwork;
/*qm_err_check*/
struct mutex qm_lock;
- struct delayed_work qm_dwork;
a_uint32_t port_link_down[AR8327_NUM_PORTS];
a_uint32_t port_link_up[AR8327_NUM_PORTS];
a_uint32_t port_old_link[AR8327_NUM_PORTS];
@@ -248,6 +249,8 @@
a_uint32_t port_qm_buf[AR8327_NUM_PORTS];
a_uint32_t port_old_tx_flowctrl[AR8327_NUM_PORTS];
a_uint32_t port_old_rx_flowctrl[AR8327_NUM_PORTS];
+ struct delayed_work qm_dwork_polling;
+ struct work_struct intr_workqueue;
/*qm_err_check end*/
a_uint8_t device_id;
/*dess_rgmii_mac*/
@@ -262,7 +265,10 @@
u64 *mib_counters;
/* dump buf */
a_uint8_t buf[2048];
-
+ a_uint32_t link_polling_required;
+ /* it is valid only when link_polling_required is false*/
+ a_uint32_t link_interrupt_no;
+ a_uint32_t interrupt_flag;
/* VLAN database */
bool vlan; /* True: 1q vlan mode, False: port vlan mode */
a_uint16_t vlan_id[AR8327_MAX_VLANS];
diff --git a/src/init/ssdk_init.c b/src/init/ssdk_init.c
index a45bd60..a3045d9 100755
--- a/src/init/ssdk_init.c
+++ b/src/init/ssdk_init.c
@@ -37,6 +37,8 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/string.h>
+#include <linux/gpio.h>
+
#if defined(ISIS) ||defined(ISISC) ||defined(GARUDA)
#include <f1_phy.h>
#endif
@@ -507,7 +509,7 @@
}
else
{
- printk("API not support \n");
+ SSDK_ERROR("API not support \n");
}
}
@@ -515,7 +517,7 @@
{
a_uint32_t value, value0, i;
if (priv == NULL || (priv->mii_read == NULL) || (priv->mii_write == NULL)) {
- printk("In qca_switch_set_mac_force, private data is NULL!\r\n");
+ SSDK_ERROR("In qca_switch_set_mac_force, private data is NULL!\r\n");
return;
}
@@ -612,7 +614,7 @@
/* Configure switch register from DT information */
paddr = of_get_property(np, "qca,ar8327-initvals", &len);
if (!paddr || len < (2 * sizeof(*paddr))) {
- printk("len:%d < 2 * sizeof(*paddr):%d\n", len, 2 * sizeof(*paddr));
+ SSDK_ERROR("len:%d < 2 * sizeof(*paddr):%d\n", len, 2 * sizeof(*paddr));
return -EINVAL;
}
@@ -1133,11 +1135,12 @@
}
#define SSDK_QM_CHANGE_WQ
+extern int qca_intr_init(struct qca_phy_priv * priv);
static void
-qm_err_check_work_task(struct work_struct *work)
+qm_err_check_work_task_polling(struct work_struct *work)
{
struct qca_phy_priv *priv = container_of(work, struct qca_phy_priv,
- qm_dwork.work);
+ qm_dwork_polling.work);
mutex_lock(&priv->qm_lock);
@@ -1149,11 +1152,73 @@
schedule_delayed_work(&priv->qm_dwork,
msecs_to_jiffies(QCA_QM_WORK_DELAY));
#else
- queue_delayed_work_on(0, system_long_wq, &priv->qm_dwork,
+ queue_delayed_work_on(0, system_long_wq, &priv->qm_dwork_polling,
msecs_to_jiffies(QCA_QM_WORK_DELAY));
#endif
}
+static int config_gpio(a_uint32_t gpio_num)
+{
+ int error;
+
+ if (gpio_is_valid(gpio_num))
+ {
+ error = gpio_request_one(gpio_num, GPIOF_IN, "linkchange");
+ if (error < 0) {
+ SSDK_ERROR("gpio request faild \n");
+ return -1;
+ }
+ gpio_set_debounce(gpio_num, 60000);
+ }
+ else
+ {
+ SSDK_ERROR("gpio is invalid\n");
+ return -1;
+ }
+
+ return 0;
+}
+static int qca_link_polling_select(struct qca_phy_priv *priv)
+{
+ struct device_node *np = NULL;
+ const __be32 *link_polling_required, *link_intr_gpio;
+ a_int32_t len;
+
+ if(priv->version == QCA_VER_DESS)
+ np = of_find_node_by_name(NULL, "ess-switch");
+ else
+ /*ap148*/
+ np = priv->phy->dev.of_node;
+ if(!np)
+ {
+ SSDK_ERROR("np is null !\n");
+ return -1;
+ }
+
+ link_polling_required = of_get_property(np, "link-polling-required", &len);
+ if (!link_polling_required )
+ {
+ SSDK_ERROR("cannot find link-polling-required node\n");
+ return -1;
+ }
+ priv->link_polling_required = be32_to_cpup(link_polling_required);
+ if(!priv->link_polling_required)
+ {
+ link_intr_gpio = of_get_property(np, "link-intr-gpio", &len);
+ if (!link_intr_gpio )
+ {
+ SSDK_ERROR("cannot find link-intr-gpio node\n");
+ return -1;
+ }
+ if(config_gpio(be32_to_cpup(link_intr_gpio)))
+ return -1;
+ priv->link_interrupt_no = gpio_to_irq (be32_to_cpup(link_intr_gpio));
+ SSDK_INFO("the interrupt number is:%x\n",priv->link_interrupt_no);
+ }
+
+ return 0;
+}
+
int
qm_err_check_work_start(struct qca_phy_priv *priv)
{
@@ -1167,14 +1232,12 @@
return -1;
mutex_init(&priv->qm_lock);
-
- INIT_DELAYED_WORK(&priv->qm_dwork, qm_err_check_work_task);
-
+ INIT_DELAYED_WORK(&priv->qm_dwork_polling, qm_err_check_work_task_polling);
#ifndef SSDK_MIB_CHANGE_WQ
- schedule_delayed_work(&priv->qm_dwork,
+ schedule_delayed_work(&priv->qm_dwork_polling,
msecs_to_jiffies(QCA_QM_WORK_DELAY));
#else
- queue_delayed_work_on(0, system_long_wq, &priv->qm_dwork,
+ queue_delayed_work_on(0, system_long_wq, &priv->qm_dwork_polling,
msecs_to_jiffies(QCA_QM_WORK_DELAY));
#endif
@@ -1189,7 +1252,8 @@
priv->version != QCA_VER_AR8327 &&
priv->version != QCA_VER_DESS) return;
- cancel_delayed_work_sync(&priv->qm_dwork);
+ cancel_delayed_work_sync(&priv->qm_dwork_polling);
+
}
#ifdef DESS
static void
@@ -1291,7 +1355,7 @@
return 0;
} else {
- printk("unsupported QCA device\n");
+ SSDK_ERROR("unsupported QCA device\n");
return -ENODEV;
}
}
@@ -1326,10 +1390,14 @@
priv->mii_read = qca_ar8216_mii_read;
priv->mii_write = qca_ar8216_mii_write;
priv->phy_write = qca_ar8327_phy_write;
+ priv->phy_read = qca_ar8327_phy_read;
priv->phy_dbg_write = qca_ar8327_phy_dbg_write;
priv->phy_dbg_read = qca_ar8327_phy_dbg_read;
priv->phy_mmd_write = qca_ar8327_mmd_write;
+ ret = qca_link_polling_select(priv);
+ if(ret)
+ priv->link_polling_required = 1;
pdev->priv = priv;
pdev->supported |= SUPPORTED_1000baseT_Full;
pdev->advertising |= ADVERTISED_1000baseT_Full;
@@ -1352,7 +1420,24 @@
qca_phy_mib_work_start(priv);
- qm_err_check_work_start(priv);
+ if(priv->link_polling_required)
+ {
+ SSDK_INFO("polling is selected\n");
+ ret = qm_err_check_work_start(priv);
+ if (ret != 0)
+ {
+ SSDK_ERROR("qm_err_check_work_start failed for %s\n", sw_dev->name);
+ return ret;
+ }
+ }
+ else
+ {
+ SSDK_INFO("interrupt is selected\n");
+ priv->interrupt_flag = IRQF_TRIGGER_LOW;
+ ret = qca_intr_init(priv);
+ if(ret)
+ SSDK_ERROR("the interrupt init faild !\n");
+ }
return ret;
}
@@ -1372,6 +1457,7 @@
priv->mii_read = qca_ar8216_mii_read;
priv->mii_write = qca_ar8216_mii_write;
priv->phy_write = qca_ar8327_phy_write;
+ priv->phy_read = qca_ar8327_phy_read;
priv->phy_dbg_write = qca_ar8327_phy_dbg_write;
priv->phy_dbg_read = qca_ar8327_phy_dbg_read;
priv->phy_mmd_write = qca_ar8327_mmd_write;
@@ -1379,7 +1465,7 @@
if (fal_reg_get(0, 0, (a_uint8_t *)&chip_id, 4) == SW_OK) {
priv->version = ((chip_id >> 8) & 0xff);
priv->revision = (chip_id & 0xff);
- printk("Chip version 0x%02x%02x\n", priv->version, priv->revision);
+ SSDK_INFO("Chip version 0x%02x%02x\n", priv->version, priv->revision);
}
#ifdef HAWKEYE_CHIP
@@ -1407,21 +1493,40 @@
ret = register_switch(sw_dev, NULL);
if (ret != 0) {
- printk("register_switch failed for %s\n", sw_dev->name);
+ SSDK_ERROR("register_switch failed for %s\n", sw_dev->name);
return ret;
}
ret = qca_phy_mib_work_start(qca_phy_priv_global);
if (ret != 0) {
- printk("qca_phy_mib_work_start failed for %s\n", sw_dev->name);
+ SSDK_ERROR("qca_phy_mib_work_start failed for %s\n", sw_dev->name);
return ret;
}
+ ret = qca_link_polling_select(priv);
+ if(ret)
+ priv->link_polling_required = 1;
+ if(priv->link_polling_required)
+ {
+ SSDK_INFO("polling is selected\n");
+ ret = qm_err_check_work_start(priv);
+ if (ret != 0)
+ {
+ SSDK_ERROR("qm_err_check_work_start failed for %s\n", sw_dev->name);
+ return ret;
+ }
+ }
+ else
+ {
+ SSDK_INFO("interrupt is selected\n");
+ priv->interrupt_flag = IRQF_TRIGGER_MASK;
+ ret = qca_intr_init(priv);
+ if(ret)
+ {
+ SSDK_ERROR("the interrupt init faild !\n");
+ return ret;
+ }
+ }
- ret = qm_err_check_work_start(qca_phy_priv_global);
- if (ret != 0) {
- printk("qm_err_check_work_start failed for %s\n", sw_dev->name);
- return ret;
- }
#if 0
#ifdef DESS
if ((ssdk_dt_global.mac_mode == PORT_WRAPPER_SGMII0_RGMII5)
@@ -1431,7 +1536,7 @@
||(ssdk_dt_global.mac_mode == PORT_WRAPPER_SGMII4_RGMII4)) {
ret = dess_rgmii_mac_work_start(priv);
if (ret != 0) {
- printk("dess_rgmii_mac_work_start failed for %s\n", sw_dev->name);
+ SSDK_ERROR("dess_rgmii_mac_work_start failed for %s\n", sw_dev->name);
return ret;
}
}
@@ -1595,27 +1700,27 @@
ess_mac_clock_disable[4] = devm_reset_control_get(&pdev->dev, "ess_mac5_clk_dis");
if (IS_ERR(ess_rst)) {
- printk("ess rst fail!\n");
+ SSDK_ERROR("ess rst fail!\n");
return -1;
}
if (!ess_mac_clock_disable[0]) {
- printk("ess_mac1_clock_disable fail!\n");
+ SSDK_ERROR("ess_mac1_clock_disable fail!\n");
return -1;
}
if (!ess_mac_clock_disable[1]) {
- printk("ess_mac2_clock_disable fail!\n");
+ SSDK_ERROR("ess_mac2_clock_disable fail!\n");
return -1;
}
if (!ess_mac_clock_disable[2]) {
- printk("ess_mac3_clock_disable fail!\n");
+ SSDK_ERROR("ess_mac3_clock_disable fail!\n");
return -1;
}
if (!ess_mac_clock_disable[3]) {
- printk("ess_mac4_clock_disable fail!\n");
+ SSDK_ERROR("ess_mac4_clock_disable fail!\n");
return -1;
}
if (!ess_mac_clock_disable[4]) {
- printk("ess_mac5_clock_disable fail!\n");
+ SSDK_ERROR("ess_mac5_clock_disable fail!\n");
return -1;
}
@@ -1623,7 +1728,7 @@
mdelay(10);
reset_control_deassert(ess_rst);
mdelay(100);
- printk("reset ok in probe!\n");
+ SSDK_INFO("reset ok in probe!\n");
return 0;
}
@@ -1670,7 +1775,7 @@
}
#ifdef PSGMII_DEBUG
if (n >= 100)
- printk("MALIBU PSGMII PLL_VCO_CALIB NOT READY\n");
+ SSDK_INFO("MALIBU PSGMII PLL_VCO_CALIB NOT READY\n");
#endif
mdelay(50);
/*check malibu psgmii calibration done end..*/
@@ -1689,7 +1794,7 @@
}
#ifdef PSGMII_DEBUG
if (m >= 100)
- printk("DAKOTA PSGMII PLL_VCO_CALIB NOT READY\n");
+ SSDK_INFO("DAKOTA PSGMII PLL_VCO_CALIB NOT READY\n");
#endif
mdelay(50);
/*check dakota psgmii calibration done end..*/
@@ -1705,7 +1810,7 @@
static void ssdk_psgmii_phy_testing_printf(a_uint32_t phy, u32 tx_ok, u32 rx_ok,
u32 tx_counter_error, u32 rx_counter_error)
{
- printk("tx_ok = 0x%x, rx_ok = 0x%x, tx_counter_error = 0x%x, rx_counter_error = 0x%x\n",
+ SSDK_INFO("tx_ok = 0x%x, rx_ok = 0x%x, tx_counter_error = 0x%x, rx_counter_error = 0x%x\n",
tx_ok, rx_ok, tx_counter_error, rx_counter_error);
if (tx_ok== 0x3000 && tx_counter_error == 0)
SSDK_INFO("PHY %d single PSGMII test pass\n", phy);
@@ -1717,7 +1822,7 @@
static void ssdk_psgmii_all_phy_testing_printf(a_uint32_t phy, u32 tx_ok, u32 rx_ok,
u32 tx_counter_error, u32 rx_counter_error)
{
- printk("tx_ok = 0x%x, rx_ok = 0x%x, tx_counter_error = 0x%x, rx_counter_error = 0x%x\n",
+ SSDK_INFO("tx_ok = 0x%x, rx_ok = 0x%x, tx_counter_error = 0x%x, rx_counter_error = 0x%x\n",
tx_ok, rx_ok, tx_counter_error, rx_counter_error);
if (tx_ok== 0x3000 && tx_counter_error == 0)
SSDK_INFO("PHY %d all PSGMII test pass\n", phy);
@@ -1973,12 +2078,12 @@
rv = fal_init(dev_id, cfg);
if (rv != SW_OK)
- printk("ssdk fal init failed: %d. \r\n", rv);
+ SSDK_ERROR("ssdk fal init failed: %d. \r\n", rv);
if (cfg->chip_type != CHIP_HPPE) {
rv = ssdk_phy_driver_init(dev_id, cfg);
if (rv != SW_OK)
- printk("ssdk phy init failed: %d. \r\n", rv);
+ SSDK_ERROR("ssdk phy init failed: %d. \r\n", rv);
}
return rv;
@@ -2010,7 +2115,6 @@
//According to HW suggestion, enable CPU port flow control for Dakota
fal_port_flowctrl_forcemode_set(0, 0, A_TRUE);
fal_port_flowctrl_set(0, 0, A_TRUE);
-
fal_port_duplex_set(0, 0, FAL_FULL_DUPLEX);
fal_port_speed_set(0, 0, FAL_SPEED_1000);
udelay(10);
@@ -2028,28 +2132,28 @@
mac_mode = of_get_property(switch_node, "switch_mac_mode", &len);
if (!mac_mode)
- printk("mac mode doesn't exit!\n");
+ SSDK_INFO("mac mode doesn't exit!\n");
else {
cfg->mac_mode = be32_to_cpup(mac_mode);
- printk("mac mode = 0x%x\n", be32_to_cpup(mac_mode));
+ SSDK_INFO("mac mode = 0x%x\n", be32_to_cpup(mac_mode));
ssdk_dt_global.mac_mode = cfg->mac_mode;
}
mac_mode = of_get_property(switch_node, "switch_mac_mode1", &len);
if(!mac_mode)
- printk("mac mode1 doesn't exit!\n");
+ SSDK_INFO("mac mode1 doesn't exit!\n");
else {
cfg->mac_mode1 = be32_to_cpup(mac_mode);
- printk("mac mode1 = 0x%x\n", be32_to_cpup(mac_mode));
+ SSDK_INFO("mac mode1 = 0x%x\n", be32_to_cpup(mac_mode));
ssdk_dt_global.mac_mode1 = cfg->mac_mode1;
}
mac_mode = of_get_property(switch_node, "switch_mac_mode2", &len);
if(!mac_mode)
- printk("mac mode2 doesn't exit!\n");
+ SSDK_INFO("mac mode2 doesn't exit!\n");
else {
cfg->mac_mode2 = be32_to_cpup(mac_mode);
- printk("mac mode2 = 0x%x\n", be32_to_cpup(mac_mode));
+ SSDK_INFO("mac mode2 = 0x%x\n", be32_to_cpup(mac_mode));
ssdk_dt_global.mac_mode2 = cfg->mac_mode2;
}
@@ -2065,18 +2169,18 @@
/* read uniphy register base and address space */
uniphy_node = of_find_node_by_name(NULL, "ess-uniphy");
if (!uniphy_node)
- printk("ess-uniphy DT doesn't exist!\n");
+ SSDK_INFO("ess-uniphy DT doesn't exist!\n");
else {
- printk("ess-uniphy DT exist!\n");
+ SSDK_INFO("ess-uniphy DT exist!\n");
reg_cfg = of_get_property(uniphy_node, "reg", &len);
if(!reg_cfg)
- printk("uniphy reg address doesn't exist!\n");
+ SSDK_INFO("uniphy reg address doesn't exist!\n");
else {
ssdk_dt_global.uniphyreg_base_addr = be32_to_cpup(reg_cfg);
ssdk_dt_global.uniphyreg_size = be32_to_cpup(reg_cfg + 1);
}
if (of_property_read_string(uniphy_node, "uniphy_access_mode", (const char **)&ssdk_dt_global.uniphy_access_mode))
- printk("uniphy access mode doesn't exist!\n");
+ SSDK_INFO("uniphy access mode doesn't exist!\n");
else {
if(!strcmp(ssdk_dt_global.uniphy_access_mode, "local bus"))
ssdk_dt_global.uniphy_reg_access_mode = HSL_REG_LOCAL_BUS;
@@ -2099,25 +2203,25 @@
scheduler_node = of_find_node_by_name(port_node, "l1scheduler");
if (!scheduler_node) {
- printk("cannot find l1scheduler node for port\n");
+ SSDK_ERROR("cannot find l1scheduler node for port\n");
return;
}
for_each_available_child_of_node(scheduler_node, child) {
paddr = of_get_property(child, "sp", &len);
len /= sizeof(a_uint32_t);
if (!paddr) {
- printk("error reading sp property\n");
+ SSDK_ERROR("error reading sp property\n");
return;
}
if (of_property_read_u32_array(child,
"cfg", tmp_cfg, 4)) {
- printk("error reading cfg property!\n");
+ SSDK_ERROR("error reading cfg property!\n");
return;
}
for (i = 0; i < len; i++) {
sp_id = be32_to_cpup(paddr+i);
if (sp_id >= SSDK_L1SCHEDULER_CFG_MAX) {
- printk("Invalid parameter for sp(%d)\n",
+ SSDK_ERROR("Invalid parameter for sp(%d)\n",
sp_id);
return;
}
@@ -2144,25 +2248,25 @@
scheduler_node = of_find_node_by_name(port_node, "l0scheduler");
if (!scheduler_node) {
- printk("cannot find l0scheduler node for port\n");
+ SSDK_ERROR("cannot find l0scheduler node for port\n");
return;
}
for_each_available_child_of_node(scheduler_node, child) {
paddr = of_get_property(child, "ucast_queue", &len);
len /= sizeof(a_uint32_t);
if (!paddr) {
- printk("error reading ucast_queue property\n");
+ SSDK_ERROR("error reading ucast_queue property\n");
return;
}
if (of_property_read_u32_array(child,
"cfg", tmp_cfg, 5)) {
- printk("error reading cfg property!\n");
+ SSDK_ERROR("error reading cfg property!\n");
return;
}
for (i = 0; i < len; i++) {
queue_id = be32_to_cpup(paddr+i);
if (queue_id >= SSDK_L0SCHEDULER_UCASTQ_CFG_MAX) {
- printk("Invalid parameter for Uqueue(%d)\n",
+ SSDK_ERROR("Invalid parameter for Uqueue(%d)\n",
queue_id);
return;
}
@@ -2177,13 +2281,13 @@
paddr = of_get_property(child, "mcast_queue", &len);
len /= sizeof(a_uint32_t);
if (!paddr) {
- printk("error reading Mcast_queue property\n");
+ SSDK_ERROR("error reading Mcast_queue property\n");
return;
}
for (i = 0; i < len; i++) {
queue_id = be32_to_cpup(paddr+i);
if (queue_id >= SSDK_L0SCHEDULER_CFG_MAX) {
- printk("Invalid parameter for Mqueue(%d)\n",
+ SSDK_ERROR("Invalid parameter for Mqueue(%d)\n",
queue_id);
return;
}
@@ -2213,7 +2317,7 @@
|| of_property_read_u32_array(port_node, "l0edrr", l0edrr, 2)
|| of_property_read_u32_array(port_node, "l1cdrr", l1cdrr, 2)
|| of_property_read_u32_array(port_node, "l1edrr", l1edrr, 2)){
- printk("error reading port resource scheduler properties\n");
+ SSDK_ERROR("error reading port resource scheduler properties\n");
return;
}
cfg->pool[port_id].ucastq_start = uq[0];
@@ -2240,16 +2344,16 @@
scheduler_node = of_find_node_by_name(switch_node, "port_scheduler_resource");
if (!scheduler_node) {
- printk("cannot find port_scheduler_resource node\n");
+ SSDK_ERROR("cannot find port_scheduler_resource node\n");
return;
}
for_each_available_child_of_node(scheduler_node, child) {
if (of_property_read_u32(child, "port_id", &port_id)) {
- printk("error reading for port_id property!\n");
+ SSDK_ERROR("error reading for port_id property!\n");
return;
}
if (port_id >= SSDK_MAX_PORT_NUM) {
- printk("invalid parameter for port_id(%d)!\n", port_id);
+ SSDK_ERROR("invalid parameter for port_id(%d)!\n", port_id);
return;
}
ssdk_dt_parse_scheduler_resource(child, port_id);
@@ -2257,16 +2361,16 @@
scheduler_node = of_find_node_by_name(switch_node, "port_scheduler_config");
if (!scheduler_node) {
- printk("cannot find port_scheduler_config node\n");
+ SSDK_ERROR("cannot find port_scheduler_config node\n");
return ;
}
for_each_available_child_of_node(scheduler_node, child) {
if (of_property_read_u32(child, "port_id", &port_id)) {
- printk("error reading for port_id property!\n");
+ SSDK_ERROR("error reading for port_id property!\n");
return;
}
if (port_id >= SSDK_MAX_PORT_NUM) {
- printk("invalid parameter for port_id(%d)!\n", port_id);
+ SSDK_ERROR("invalid parameter for port_id(%d)!\n", port_id);
return;
}
ssdk_dt_parse_l1_scheduler_cfg(child, port_id);
@@ -2283,10 +2387,10 @@
mdio_node = of_find_node_by_name(NULL, "mdio");
if (!mdio_node) {
- printk("mdio DT doesn't exist!\n");
+ SSDK_INFO("mdio DT doesn't exist!\n");
}
else {
- printk("mdio DT exist!\n");
+ SSDK_INFO("mdio DT exist!\n");
for_each_available_child_of_node(mdio_node, child) {
phy_addr = of_get_property(child, "reg", &len);
if (phy_addr)
@@ -2307,7 +2411,7 @@
if (of_property_read_u32(switch_node, "switch_cpu_bmp", &cfg->port_cfg.cpu_bmp)
|| of_property_read_u32(switch_node, "switch_lan_bmp", &cfg->port_cfg.lan_bmp)
|| of_property_read_u32(switch_node, "switch_wan_bmp", &cfg->port_cfg.wan_bmp)) {
- printk("port_bmp doesn't exist!\n");
+ SSDK_ERROR("port_bmp doesn't exist!\n");
return;
}
portbmp = cfg->port_cfg.lan_bmp | cfg->port_cfg.wan_bmp;
@@ -2333,10 +2437,10 @@
*/
switch_node = of_find_node_by_name(NULL, "ess-switch");
if (!switch_node) {
- printk("cannot find ess-switch node\n");
+ SSDK_ERROR("cannot find ess-switch node\n");
return SW_BAD_PARAM;
}
- printk("ess-switch DT exist!\n");
+ SSDK_INFO("ess-switch DT exist!\n");
if (!of_property_read_string(switch_node, "status", (const char **)&status_value))
{
@@ -2346,7 +2450,7 @@
reg_cfg = of_get_property(switch_node, "reg", &len);
if(!reg_cfg) {
- printk("%s: error reading device node properties for reg\n", switch_node->name);
+ SSDK_ERROR("%s: error reading device node properties for reg\n", switch_node->name);
return SW_BAD_PARAM;
}
@@ -2354,17 +2458,17 @@
ssdk_dt_global.switchreg_size = be32_to_cpup(reg_cfg + 1);
if (of_property_read_string(switch_node, "switch_access_mode", (const char **)&ssdk_dt_global.reg_access_mode)) {
- printk("%s: error reading device node properties for switch_access_mode\n", switch_node->name);
+ SSDK_ERROR("%s: error reading device node properties for switch_access_mode\n", switch_node->name);
return SW_BAD_PARAM;
}
ssdk_dt_global.ess_clk = of_clk_get_by_name(switch_node, "ess_clk");
if (IS_ERR(ssdk_dt_global.ess_clk))
- printk("Getting ess_clk failed!\n");
+ SSDK_INFO("Getting ess_clk failed!\n");
- printk("switchreg_base_addr: 0x%x\n", ssdk_dt_global.switchreg_base_addr);
- printk("switchreg_size: 0x%x\n", ssdk_dt_global.switchreg_size);
- printk("switch_access_mode: %s\n", ssdk_dt_global.reg_access_mode);
+ SSDK_INFO("switchreg_base_addr: 0x%x\n", ssdk_dt_global.switchreg_base_addr);
+ SSDK_INFO("switchreg_size: 0x%x\n", ssdk_dt_global.switchreg_size);
+ SSDK_INFO("switch_access_mode: %s\n", ssdk_dt_global.reg_access_mode);
if(!strcmp(ssdk_dt_global.reg_access_mode, "local bus"))
ssdk_dt_global.switch_reg_access_mode = HSL_REG_LOCAL_BUS;
else if(!strcmp(ssdk_dt_global.reg_access_mode, "mdio"))
@@ -2386,17 +2490,17 @@
if (!psgmii_node) {
return SW_BAD_PARAM;
}
- printk("ess-psgmii DT exist!\n");
+ SSDK_INFO("ess-psgmii DT exist!\n");
reg_cfg = of_get_property(psgmii_node, "reg", &len);
if(!reg_cfg) {
- printk("%s: error reading device node properties for reg\n", psgmii_node->name);
+ SSDK_ERROR("%s: error reading device node properties for reg\n", psgmii_node->name);
return SW_BAD_PARAM;
}
ssdk_dt_global.psgmiireg_base_addr = be32_to_cpup(reg_cfg);
ssdk_dt_global.psgmiireg_size = be32_to_cpup(reg_cfg + 1);
if (of_property_read_string(psgmii_node, "psgmii_access_mode", (const char **)&ssdk_dt_global.psgmii_reg_access_str)) {
- printk("%s: error reading device node properties for psmgii_access_mode\n", psgmii_node->name);
+ SSDK_INFO("%s: error reading device node properties for psmgii_access_mode\n", psgmii_node->name);
return SW_BAD_PARAM;
}
if(!strcmp(ssdk_dt_global.psgmii_reg_access_str, "local bus"))
@@ -2443,7 +2547,7 @@
i++;
}
cfg->led_source_num = i;
- printk("current dts led_source_num is %d\n",cfg->led_source_num);
+ SSDK_INFO("current dts led_source_num is %d\n",cfg->led_source_num);
return SW_OK;
}
@@ -2464,11 +2568,11 @@
if(ssdk_dt_global.switch_reg_access_mode == HSL_REG_MDIO) {
if(driver_find(qca_phy_driver.name, &mdio_bus_type)){
- printk("QCA PHY driver had been Registered\n");
+ SSDK_ERROR("QCA PHY driver had been Registered\n");
return;
}
- printk("Register QCA PHY driver\n");
+ SSDK_INFO("Register QCA PHY driver\n");
#ifndef BOARD_AR71XX
phy_driver_register(&qca_phy_driver);
#else
@@ -2707,10 +2811,10 @@
/*softreset psgmii, fixme*/
gcc_addr = ioremap_nocache(0x1812000, 0x200);
if (!gcc_addr) {
- printk("gcc map fail!\n");
+ SSDK_ERROR("gcc map fail!\n");
return 0;
} else {
- printk("gcc map success!\n");
+ SSDK_INFO("gcc map success!\n");
writel(0x20, gcc_addr+0xc);
mdelay(10);
writel(0x0, gcc_addr+0xc);
@@ -3281,7 +3385,7 @@
tdm_ctrl.offset = 0;
tdm_ctrl.depth = 100;
p_api->adpt_port_tdm_ctrl_set(0, &tdm_ctrl);
- printk("tdm setup num=%d\n", num);
+ SSDK_INFO("tdm setup num=%d\n", num);
return 0;
}
@@ -3500,10 +3604,10 @@
{
gcc_uniphy_base = ioremap_nocache(0x01856000, 0x280);
if (!gcc_uniphy_base) {
- printk("can't get gcc uniphy address!\n");
+ SSDK_ERROR("can't get gcc uniphy address!\n");
return -1;
}
- printk("Get gcc uniphy address successfully!\n");
+ SSDK_INFO("Get gcc uniphy address successfully!\n");
return 0;
}
@@ -3513,17 +3617,17 @@
{
gcc_hppe_clock_config1_base = ioremap_nocache(0x01868020, 0x5c);
if (!gcc_hppe_clock_config1_base) {
- printk("can't get gcc hppe colck config1 address!\n");
+ SSDK_ERROR("can't get gcc hppe colck config1 address!\n");
return -1;
}
- printk("Get gcc hppe colck config1 address successfully!\n");
+ SSDK_INFO("Get gcc hppe colck config1 address successfully!\n");
gcc_hppe_clock_config2_base = ioremap_nocache(0x01868400, 0x60);
if (!gcc_hppe_clock_config2_base) {
- printk("can't get gcc hppe colck config2 address!\n");
+ SSDK_ERROR("can't get gcc hppe colck config2 address!\n");
return -1;
}
- printk("Get gcc hppe colck config2 address successfully!\n");
+ SSDK_INFO("Get gcc hppe colck config2 address successfully!\n");
return 0;
}
@@ -3803,14 +3907,14 @@
/*fixme*/
ppe_gpio_base = ioremap_nocache(0x01008000, 0x100);
if (!ppe_gpio_base) {
- printk("can't get gpio address!\n");
+ SSDK_ERROR("can't get gpio address!\n");
return -1;
}
/* RUMI specific GPIO configuration for enabling XGMAC */
writel(0x201, ppe_gpio_base + 0);
writel(0x2, ppe_gpio_base + 4);
iounmap(ppe_gpio_base);
- printk("set gpio to enable XGMAC successfully!\n");
+ SSDK_INFO("set gpio to enable XGMAC successfully!\n");
val = 0x3b;
qca_switch_reg_write(0, 0x000010, (a_uint8_t *)&val, 4);
val = 0;
@@ -3841,7 +3945,7 @@
cfg->mac_mode2);
#else
qca_hppe_xgmac_hw_init();
- printk("hppe xgmac init success\n");
+ SSDK_INFO("hppe xgmac init success\n");
for(i = 0; i < 4; i++) {
hppe_port_type[i] = HPPE_PORT_GMAC_TYPE;
@@ -3912,7 +4016,7 @@
a_uint32_t tmp_vid = 0xffffffff;
fal_intf_mac_entry_t intf_entry;
a_uint32_t wan_port = 0;
- sw_error_t rv;
+ sw_error_t rv = 0;
static fal_intf_mac_entry_t if_mac_entry[8] = {{0}};
int index = 0xffffffff;
/*get mac*/
@@ -4107,7 +4211,7 @@
#ifndef BOARD_AR71XX
#if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
if(SW_DISABLE == ssdk_dt_parse(&cfg)) {
- printk("ess-switch status value is disabled\n");
+ SSDK_INFO("ess-switch status value is disabled\n");
return SW_OK;
}
#endif
@@ -4138,9 +4242,9 @@
#if defined(HPPE)
if(cfg.chip_type == CHIP_HPPE)
{
- printk("Initializing HPPE!!\n");
+ SSDK_INFO("Initializing HPPE!!\n");
qca_hppe_hw_init(&cfg);
- printk("Initializing HPPE Done!!\n");
+ SSDK_INFO("Initializing HPPE Done!!\n");
}
#endif
#if defined(DESS)
@@ -4190,13 +4294,13 @@
out:
fal_module_func_init(0, &cfg);
if (rv == 0)
- printk("qca-ssdk module init succeeded!\n");
+ SSDK_INFO("qca-ssdk module init succeeded!\n");
else {
if (rv == -ENODEV) {
rv = 0;
- printk("qca-ssdk module init, no device found!\n");
+ SSDK_INFO("qca-ssdk module init, no device found!\n");
} else
- printk("qca-ssdk module init failed! (code: %d)\n", rv);
+ SSDK_INFO("qca-ssdk module init failed! (code: %d)\n", rv);
}
return rv;
@@ -4208,9 +4312,9 @@
sw_error_t rv=ssdk_cleanup();
if (rv == 0)
- printk("qca-ssdk module exit done!\n");
+ SSDK_INFO("qca-ssdk module exit done!\n");
else
- printk("qca-ssdk module exit failed! (code: %d)\n", rv);
+ SSDK_ERROR("qca-ssdk module exit failed! (code: %d)\n", rv);
kfree(qca_phy_priv_global);
diff --git a/src/init/ssdk_interrupt.c b/src/init/ssdk_interrupt.c
new file mode 100755
index 0000000..5b4c4ed
--- /dev/null
+++ b/src/init/ssdk_interrupt.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "fal_init.h"
+#include "fal_reg_access.h"
+#include "sw.h"
+#include "ssdk_init.h"
+#include "fal_init.h"
+#include <linux/phy.h>
+#include <linux/kernel.h>
+#include <linux/kconfig.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <generated/autoconf.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/if_arp.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#if defined(ISIS)
+#include <isis/isis_reg.h>
+#elif defined(ISISC)
+#include <isisc/isisc_reg.h>
+#else
+#include <dess/dess_reg.h>
+#endif
+#if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0))
+#include <linux/switch.h>
+#include <linux/of.h>
+#elif defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+#include <linux/switch.h>
+#include <linux/of.h>
+#include <drivers/leds/leds-ipq40xx.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+#else
+#include <net/switch.h>
+#include <linux/ar8216_platform.h>
+#endif
+#include "ssdk_plat.h"
+#include "ref_port_ctrl.h"
+
+#define LINK_CHANGE_INTR 0x8000
+/*phy interrupt enable and status register*/
+#define INTERRUPT_ENABLE_REGISTER 0X12
+#define INTERRUPT_STATUS_REGISTER 0X13
+
+static int qca_phy_disable_intr(struct qca_phy_priv *priv)
+{
+ a_uint32_t phy_number = 0;
+ a_uint16_t value;
+
+ for(phy_number = 0; phy_number < 5; phy_number++)
+ {
+ value = 0;
+ priv->phy_write(0,phy_number, INTERRUPT_ENABLE_REGISTER, value);
+ priv->phy_read(0,phy_number, INTERRUPT_STATUS_REGISTER, &value);
+ }
+
+ return 0;
+}
+
+static int qca_mac_disable_intr(struct qca_phy_priv *priv)
+{
+ a_uint8_t data;
+
+ fal_reg_get(0, GBL_INT_MASK1_OFFSET, (a_uint8_t *)&data, 4);
+ if (data )
+ {
+ data = 0;
+ fal_reg_set(0, GBL_INT_MASK1_OFFSET,(a_uint8_t *)&data, 4);
+ }
+ /*fal_reg_get(0, 0x20, (a_uint8_t *)&data, 4);
+ if (data )
+ {
+ data = 0;
+ fal_reg_set(0, 0x20,(a_uint8_t *)&data, 4);
+ }
+
+ fal_reg_get(0, 0x28, (a_uint8_t *)&data, 4);
+ fal_reg_set(0, 0x28,(a_uint8_t *)&data, 4);
+ */
+
+ fal_reg_get(0, GBL_INT_STATUS1_OFFSET, (a_uint8_t *)&data, 4);
+ fal_reg_set(0, GBL_INT_STATUS1_OFFSET,(a_uint8_t *)&data, 4);
+
+ return 0;
+}
+
+static int qca_phy_enable_intr(struct qca_phy_priv *priv)
+{
+ a_uint16_t value = 0;
+ a_uint32_t phy_number;
+
+ for(phy_number = 0; phy_number < 5; phy_number++)
+ {
+ priv->phy_read(0, phy_number, INTERRUPT_STATUS_REGISTER, &value);
+ /*enable link change intr*/
+ if( !priv->link_polling_required)
+ value = 0xc00;
+ priv->phy_write(0,phy_number, INTERRUPT_ENABLE_REGISTER, value);
+ }
+
+ return 0;
+}
+
+static int qca_mac_enable_intr(struct qca_phy_priv *priv)
+{
+ a_uint32_t data = 0;
+
+ /*enable link change intr*/
+ if( !priv->link_polling_required)
+ data = 0x8000;
+ fal_reg_set(0, GBL_INT_MASK1_OFFSET, (a_uint8_t *)&data, 4);
+
+ return 0;
+}
+static int qca_phy_clean_intr(struct qca_phy_priv *priv)
+{
+ a_uint32_t phy_number;
+ a_uint16_t value;
+
+ for(phy_number = 0; phy_number < 5; phy_number++)
+ priv->phy_read(0, phy_number, INTERRUPT_STATUS_REGISTER, &value);
+
+ return 0;
+}
+
+static int qca_mac_clean_intr(struct qca_phy_priv *priv)
+{
+ a_uint32_t data;
+
+ fal_reg_get(0, GBL_INT_STATUS1_OFFSET, (a_uint8_t *) &data, 4);
+ fal_reg_set(0, GBL_INT_STATUS1_OFFSET, (a_uint8_t *)&data, 4);
+
+ return 0;
+}
+
+static void
+qca_link_change_task(struct qca_phy_priv *priv)
+{
+ SSDK_DEBUG("qca_link_change_task is running\n");
+ mutex_lock(&priv->qm_lock);
+ qca_ar8327_sw_mac_polling_task(&priv->sw_dev);
+ mutex_unlock(&priv->qm_lock);
+}
+
+static void
+qca_intr_workqueue_task(struct work_struct *work)
+{
+ a_uint32_t data;
+ struct qca_phy_priv *priv = container_of(work, struct qca_phy_priv, intr_workqueue);
+
+ fal_reg_get(0, GBL_INT_STATUS1_OFFSET, (a_uint8_t*)&data, 4);
+ qca_phy_clean_intr(priv);
+ qca_mac_clean_intr(priv);
+ SSDK_DEBUG("data:%x, priv->version:%x\n", data, priv->version);
+ switch(priv->version)
+ {
+ case QCA_VER_DESS:
+ qca_link_change_task(priv);
+ break;
+ default:
+ if((data &LINK_CHANGE_INTR))
+ qca_link_change_task(priv);
+ break;
+ }
+ enable_irq(priv->link_interrupt_no);
+}
+
+ static irqreturn_t qca_link_intr_handle(int irq, void *sw_dev_t)
+ {
+ struct qca_phy_priv *priv = container_of(sw_dev_t, struct qca_phy_priv, sw_dev);
+
+ disable_irq_nosync(irq);
+ schedule_work(&priv->intr_workqueue);
+ SSDK_DEBUG("irq number is :%x\n",irq);
+
+ return IRQ_HANDLED;
+ }
+
+ int qca_intr_init(struct qca_phy_priv *priv)
+{
+ SSDK_DEBUG("start to init the interrupt!\n");
+ mutex_init(&priv->qm_lock);
+ INIT_WORK(&priv->intr_workqueue, qca_intr_workqueue_task);
+ qca_phy_disable_intr(priv);
+ qca_mac_disable_intr(priv);
+ if(request_irq(priv->link_interrupt_no, qca_link_intr_handle, priv->interrupt_flag, priv->sw_dev.devname, &(priv->sw_dev)))
+ return -1;
+ qca_phy_enable_intr(priv);
+ qca_mac_enable_intr(priv);
+
+ return 0;
+}
+
diff --git a/src/ref/ref_port_ctrl.c b/src/ref/ref_port_ctrl.c
index a7102b5..8c408a4 100755
--- a/src/ref/ref_port_ctrl.c
+++ b/src/ref/ref_port_ctrl.c
@@ -571,11 +571,8 @@
}
else
{
- // a_uint32_t pstatus = 0;
fal_port_link_forcemode_set(priv->device_id, i, A_TRUE);
- // below only for dess debug print
- // qca_switch_reg_read(0, AR8327_REG_PORT_STATUS(i), (a_uint8_t *)&pstatus, 4);
- // printk("%s, %d, port_id %d link down pstatus 0x%x\n",__FUNCTION__,__LINE__,i, pstatus);
+ SSDK_DEBUG("%s, %d, port_id %d link down\n",__FUNCTION__,__LINE__,i);
}
priv->port_link_down[i]=0;
ssdk_port_link_notify(i, 0, 0, 0);
@@ -595,7 +592,7 @@
/* Force MAC 1000M Full before auto negotiation */
qca_switch_force_mac_1000M_full(dev, i);
mdelay(10);
- // printk("%s, %d, port %d link down\n",__FUNCTION__,__LINE__,i);
+ SSDK_DEBUG("%s, %d, port %d link down\n",__FUNCTION__,__LINE__,i);
}
qca_ar8327_phy_dbg_read(priv->device_id, i-1, 0, &value);
value &= (~(1<<12));
@@ -611,11 +608,12 @@
if (qm_buffer_err) {
if(priv->version != 0x14)
qca_qm_err_recovery(priv);
+ if(priv->link_polling_required)
return;
}
}
- else{
- //a_uint32_t pstatus = 0;
+ if(priv->port_link_up[i] >=1)
+ {
priv->port_link_up[i]=0;
qca_switch_force_mac_status(dev, i, speed, duplex);
udelay(100);
@@ -628,9 +626,8 @@
fal_port_txmac_status_set(priv->device_id, i, A_TRUE);
}
udelay(100);
- //qca_switch_reg_read(0, AR8327_REG_PORT_STATUS(i), (a_uint8_t *)&pstatus, 4);
- //printk("%s, %d, port %d link up speed %d, duplex %d pstatus 0x%x\n",__FUNCTION__,__LINE__,i, speed, duplex, pstatus);
- ssdk_port_link_notify(i, 1, speed, duplex);
+ SSDK_DEBUG("%s, %d, port %d link up speed %d, duplex %d\n",__FUNCTION__,__LINE__,i, speed, duplex);
+ ssdk_port_link_notify(i, 1, speed, duplex);
if((speed == 0x01) && (priv->version != 0x14))/*PHY is link up 100M*/
{
a_uint16_t value = 0;