123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- --- 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,242 @@ 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 of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata)
- +{
- +#ifdef CONFIG_MTD
- + struct device_node *mtd_np = NULL;
- + size_t retlen;
- + int size, ret;
- + struct mtd_info *mtd;
- + const char *part;
- + const __be32 *list;
- + phandle phandle;
- +
- + list = of_get_property(np, "mtd-cal-data", &size);
- + if (!list)
- + return 0;
- +
- + if (size != (2 * sizeof(*list)))
- + return 1;
- +
- + phandle = be32_to_cpup(list++);
- + if (phandle)
- + mtd_np = of_find_node_by_phandle(phandle);
- +
- + if (!mtd_np)
- + return 1;
- +
- + part = of_get_property(mtd_np, "label", NULL);
- + if (!part)
- + part = mtd_np->name;
- +
- + mtd = get_mtd_device_nm(part);
- + if (IS_ERR(mtd))
- + return 1;
- +
- + ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data),
- + &retlen, (u8*)pdata->eeprom_data);
- + put_mtd_device(mtd);
- +
- +#endif
- + return 0;
- +}
- +
- +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,disable-2ghz"))
- + pdata->disable_2ghz = true;
- +
- + if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz"))
- + pdata->disable_5ghz = true;
- +
- + 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;
- +
- + if (of_get_wifi_cal(pdev->dev.of_node, pdata))
- + dev_err(&pdev->dev, "failed to load calibration data from mtd device\n");
- +
- + return data->dev_id;
- +}
- +#endif
- +
- static int ath_ahb_probe(struct platform_device *pdev)
- {
- void __iomem *mem;
- @@ -80,6 +324,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");
- @@ -122,13 +377,16 @@ 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;
- @@ -159,6 +417,9 @@ static int ath_ahb_remove(struct platfor
- free_irq(sc->irq, sc);
- ieee80211_free_hw(sc->hw);
- }
- +#ifdef CONFIG_OF
- + pdev->dev.platform_data = NULL;
- +#endif
-
- return 0;
- }
- @@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr
- .remove = 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
- @@ -25,6 +25,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"
- @@ -1024,6 +1025,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;
|