mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 09:12:39 +00:00
1bfcc1ea8a
Brings lots of driver updates and API changes needed for mt76 updates. Disable iwlwifi and ath11k on 5.15, since backport is too difficult, and the only remaining targets won't need those drivers. Signed-off-by: Felix Fietkau <nbd@nbd.name>
285 lines
6.9 KiB
Diff
285 lines
6.9 KiB
Diff
--- a/drivers/net/wireless/ath/ath9k/ahb.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
|
|
@@ -20,7 +20,15 @@
|
|
#include <linux/platform_device.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mod_devicetable.h>
|
|
+#include <linux/of_device.h>
|
|
#include "ath9k.h"
|
|
+#include <linux/ath9k_platform.h>
|
|
+
|
|
+#ifdef CONFIG_OF
|
|
+#include <asm/mach-ath79/ath79.h>
|
|
+#include <asm/mach-ath79/ar71xx_regs.h>
|
|
+#include <linux/mtd/mtd.h>
|
|
+#endif
|
|
|
|
static const struct platform_device_id ath9k_platform_id_table[] = {
|
|
{
|
|
@@ -69,6 +77,192 @@ static const struct ath_bus_ops ath_ahb_
|
|
.eeprom_read = ath_ahb_eeprom_read,
|
|
};
|
|
|
|
+#ifdef CONFIG_OF
|
|
+
|
|
+#define QCA955X_DDR_CTL_CONFIG 0x108
|
|
+#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23)
|
|
+
|
|
+static int ar913x_wmac_reset(void)
|
|
+{
|
|
+ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
|
|
+ mdelay(10);
|
|
+
|
|
+ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
|
|
+ mdelay(10);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ar933x_wmac_reset(void)
|
|
+{
|
|
+ int retries = 20;
|
|
+
|
|
+ ath79_device_reset_set(AR933X_RESET_WMAC);
|
|
+ ath79_device_reset_clear(AR933X_RESET_WMAC);
|
|
+
|
|
+ while (1) {
|
|
+ u32 bootstrap;
|
|
+
|
|
+ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
|
|
+ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0)
|
|
+ return 0;
|
|
+
|
|
+ if (retries-- == 0)
|
|
+ break;
|
|
+
|
|
+ udelay(10000);
|
|
+ }
|
|
+
|
|
+ pr_err("ar933x: WMAC reset timed out");
|
|
+ return -ETIMEDOUT;
|
|
+}
|
|
+
|
|
+static int qca955x_wmac_reset(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ /* Try to wait for WMAC DDR activity to stop */
|
|
+ for (i = 0; i < 10; i++) {
|
|
+ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) &
|
|
+ QCA955X_DDR_CTL_CONFIG_ACT_WMAC))
|
|
+ break;
|
|
+
|
|
+ udelay(10);
|
|
+ }
|
|
+
|
|
+ ath79_device_reset_set(QCA955X_RESET_RTC);
|
|
+ udelay(10);
|
|
+ ath79_device_reset_clear(QCA955X_RESET_RTC);
|
|
+ udelay(10);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ AR913X_WMAC = 0,
|
|
+ AR933X_WMAC,
|
|
+ AR934X_WMAC,
|
|
+ QCA953X_WMAC,
|
|
+ QCA955X_WMAC,
|
|
+ QCA956X_WMAC,
|
|
+};
|
|
+
|
|
+static int ar9330_get_soc_revision(void)
|
|
+{
|
|
+ if (ath79_soc_rev == 1)
|
|
+ return ath79_soc_rev;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ath79_get_soc_revision(void)
|
|
+{
|
|
+ return ath79_soc_rev;
|
|
+}
|
|
+
|
|
+static const struct of_ath_ahb_data {
|
|
+ u16 dev_id;
|
|
+ u32 bootstrap_reg;
|
|
+ u32 bootstrap_ref;
|
|
+
|
|
+ int (*soc_revision)(void);
|
|
+ int (*wmac_reset)(void);
|
|
+} of_ath_ahb_data[] = {
|
|
+ [AR913X_WMAC] = {
|
|
+ .dev_id = AR5416_AR9100_DEVID,
|
|
+ .wmac_reset = ar913x_wmac_reset,
|
|
+
|
|
+ },
|
|
+ [AR933X_WMAC] = {
|
|
+ .dev_id = AR9300_DEVID_AR9330,
|
|
+ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP,
|
|
+ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40,
|
|
+ .soc_revision = ar9330_get_soc_revision,
|
|
+ .wmac_reset = ar933x_wmac_reset,
|
|
+ },
|
|
+ [AR934X_WMAC] = {
|
|
+ .dev_id = AR9300_DEVID_AR9340,
|
|
+ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP,
|
|
+ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40,
|
|
+ .soc_revision = ath79_get_soc_revision,
|
|
+ },
|
|
+ [QCA953X_WMAC] = {
|
|
+ .dev_id = AR9300_DEVID_AR953X,
|
|
+ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP,
|
|
+ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40,
|
|
+ .soc_revision = ath79_get_soc_revision,
|
|
+ },
|
|
+ [QCA955X_WMAC] = {
|
|
+ .dev_id = AR9300_DEVID_QCA955X,
|
|
+ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP,
|
|
+ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40,
|
|
+ .wmac_reset = qca955x_wmac_reset,
|
|
+ },
|
|
+ [QCA956X_WMAC] = {
|
|
+ .dev_id = AR9300_DEVID_QCA956X,
|
|
+ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP,
|
|
+ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40,
|
|
+ .soc_revision = ath79_get_soc_revision,
|
|
+ },
|
|
+};
|
|
+
|
|
+const struct of_device_id of_ath_ahb_match[] = {
|
|
+ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] },
|
|
+ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] },
|
|
+ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] },
|
|
+ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] },
|
|
+ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] },
|
|
+ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] },
|
|
+ {},
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, of_ath_ahb_match);
|
|
+
|
|
+static int of_ath_ahb_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct ath9k_platform_data *pdata;
|
|
+ const struct of_device_id *match;
|
|
+ const struct of_ath_ahb_data *data;
|
|
+ u8 led_pin;
|
|
+
|
|
+ match = of_match_device(of_ath_ahb_match, &pdev->dev);
|
|
+ data = (const struct of_ath_ahb_data *)match->data;
|
|
+
|
|
+ pdata = dev_get_platdata(&pdev->dev);
|
|
+
|
|
+ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin))
|
|
+ pdata->led_pin = led_pin;
|
|
+ else
|
|
+ pdata->led_pin = -1;
|
|
+
|
|
+ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo"))
|
|
+ pdata->tx_gain_buffalo = true;
|
|
+
|
|
+ if (data->wmac_reset) {
|
|
+ data->wmac_reset();
|
|
+ pdata->external_reset = data->wmac_reset;
|
|
+ }
|
|
+
|
|
+ if (data->dev_id == AR9300_DEVID_AR953X) {
|
|
+ /*
|
|
+ * QCA953x only supports 25MHz refclk.
|
|
+ * Some vendors have an invalid bootstrap option
|
|
+ * set, which would break the WMAC here.
|
|
+ */
|
|
+ pdata->is_clk_25mhz = true;
|
|
+ } else if (data->bootstrap_reg && data->bootstrap_ref) {
|
|
+ u32 t = ath79_reset_rr(data->bootstrap_reg);
|
|
+ if (t & data->bootstrap_ref)
|
|
+ pdata->is_clk_25mhz = false;
|
|
+ else
|
|
+ pdata->is_clk_25mhz = true;
|
|
+ }
|
|
+
|
|
+ pdata->get_mac_revision = data->soc_revision;
|
|
+
|
|
+ return data->dev_id;
|
|
+}
|
|
+#endif
|
|
+
|
|
static int ath_ahb_probe(struct platform_device *pdev)
|
|
{
|
|
void __iomem *mem;
|
|
@@ -80,6 +274,17 @@ static int ath_ahb_probe(struct platform
|
|
int ret = 0;
|
|
struct ath_hw *ah;
|
|
char hw_name[64];
|
|
+ u16 dev_id;
|
|
+
|
|
+ if (id)
|
|
+ dev_id = id->driver_data;
|
|
+
|
|
+#ifdef CONFIG_OF
|
|
+ if (pdev->dev.of_node)
|
|
+ pdev->dev.platform_data = devm_kzalloc(&pdev->dev,
|
|
+ sizeof(struct ath9k_platform_data),
|
|
+ GFP_KERNEL);
|
|
+#endif
|
|
|
|
if (!dev_get_platdata(&pdev->dev)) {
|
|
dev_err(&pdev->dev, "no platform data specified\n");
|
|
@@ -118,17 +323,23 @@ static int ath_ahb_probe(struct platform
|
|
sc->mem = mem;
|
|
sc->irq = irq;
|
|
|
|
+#ifdef CONFIG_OF
|
|
+ dev_id = of_ath_ahb_probe(pdev);
|
|
+#endif
|
|
ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "request_irq failed\n");
|
|
goto err_free_hw;
|
|
}
|
|
|
|
- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
|
|
+ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "failed to initialize device\n");
|
|
goto err_irq;
|
|
}
|
|
+#ifdef CONFIG_OF
|
|
+ pdev->dev.platform_data = NULL;
|
|
+#endif
|
|
|
|
ah = sc->sc_ah;
|
|
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
|
|
@@ -162,6 +373,9 @@ static struct platform_driver ath_ahb_dr
|
|
.remove_new = ath_ahb_remove,
|
|
.driver = {
|
|
.name = "ath9k",
|
|
+#ifdef CONFIG_OF
|
|
+ .of_match_table = of_ath_ahb_match,
|
|
+#endif
|
|
},
|
|
.id_table = ath9k_platform_id_table,
|
|
};
|
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
@@ -26,6 +26,7 @@
|
|
#include <linux/time.h>
|
|
#include <linux/hw_random.h>
|
|
#include <linux/gpio/driver.h>
|
|
+#include <linux/reset.h>
|
|
|
|
#include "common.h"
|
|
#include "debug.h"
|
|
@@ -1012,6 +1013,9 @@ struct ath_softc {
|
|
struct ath_hw *sc_ah;
|
|
void __iomem *mem;
|
|
int irq;
|
|
+#ifdef CONFIG_OF
|
|
+ struct reset_control *reset;
|
|
+#endif
|
|
spinlock_t sc_serial_rw;
|
|
spinlock_t sc_pm_lock;
|
|
spinlock_t sc_pcu_lock;
|