cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ahb.c (6242B)


      1/*
      2 * Copyright (c) 2008-2009 Atheros Communications Inc.
      3 * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
      4 * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
      5 *
      6 * Permission to use, copy, modify, and/or distribute this software for any
      7 * purpose with or without fee is hereby granted, provided that the above
      8 * copyright notice and this permission notice appear in all copies.
      9 *
     10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17 */
     18
     19#include <linux/module.h>
     20#include <linux/nl80211.h>
     21#include <linux/platform_device.h>
     22#include <linux/etherdevice.h>
     23#include <ath25_platform.h>
     24#include "ath5k.h"
     25#include "debug.h"
     26#include "base.h"
     27#include "reg.h"
     28
     29/* return bus cachesize in 4B word units */
     30static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
     31{
     32	*csz = L1_CACHE_BYTES >> 2;
     33}
     34
     35static bool
     36ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
     37{
     38	struct ath5k_hw *ah = common->priv;
     39	struct platform_device *pdev = to_platform_device(ah->dev);
     40	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
     41	u16 *eeprom, *eeprom_end;
     42
     43	eeprom = (u16 *) bcfg->radio;
     44	eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
     45
     46	eeprom += off;
     47	if (eeprom > eeprom_end)
     48		return false;
     49
     50	*data = *eeprom;
     51	return true;
     52}
     53
     54int ath5k_hw_read_srev(struct ath5k_hw *ah)
     55{
     56	struct platform_device *pdev = to_platform_device(ah->dev);
     57	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
     58	ah->ah_mac_srev = bcfg->devid;
     59	return 0;
     60}
     61
     62static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
     63{
     64	struct platform_device *pdev = to_platform_device(ah->dev);
     65	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
     66	u8 *cfg_mac;
     67
     68	if (to_platform_device(ah->dev)->id == 0)
     69		cfg_mac = bcfg->config->wlan0_mac;
     70	else
     71		cfg_mac = bcfg->config->wlan1_mac;
     72
     73	memcpy(mac, cfg_mac, ETH_ALEN);
     74	return 0;
     75}
     76
     77static const struct ath_bus_ops ath_ahb_bus_ops = {
     78	.ath_bus_type = ATH_AHB,
     79	.read_cachesize = ath5k_ahb_read_cachesize,
     80	.eeprom_read = ath5k_ahb_eeprom_read,
     81	.eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
     82};
     83
     84/*Initialization*/
     85static int ath_ahb_probe(struct platform_device *pdev)
     86{
     87	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
     88	struct ath5k_hw *ah;
     89	struct ieee80211_hw *hw;
     90	struct resource *res;
     91	void __iomem *mem;
     92	int irq;
     93	int ret = 0;
     94	u32 reg;
     95
     96	if (!dev_get_platdata(&pdev->dev)) {
     97		dev_err(&pdev->dev, "no platform data specified\n");
     98		ret = -EINVAL;
     99		goto err_out;
    100	}
    101
    102	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    103	if (res == NULL) {
    104		dev_err(&pdev->dev, "no memory resource found\n");
    105		ret = -ENXIO;
    106		goto err_out;
    107	}
    108
    109	mem = ioremap(res->start, resource_size(res));
    110	if (mem == NULL) {
    111		dev_err(&pdev->dev, "ioremap failed\n");
    112		ret = -ENOMEM;
    113		goto err_out;
    114	}
    115
    116	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    117	if (res == NULL) {
    118		dev_err(&pdev->dev, "no IRQ resource found\n");
    119		ret = -ENXIO;
    120		goto err_iounmap;
    121	}
    122
    123	irq = res->start;
    124
    125	hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
    126	if (hw == NULL) {
    127		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
    128		ret = -ENOMEM;
    129		goto err_iounmap;
    130	}
    131
    132	ah = hw->priv;
    133	ah->hw = hw;
    134	ah->dev = &pdev->dev;
    135	ah->iobase = mem;
    136	ah->irq = irq;
    137	ah->devid = bcfg->devid;
    138
    139	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
    140		/* Enable WMAC AHB arbitration */
    141		reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
    142		reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
    143		iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
    144
    145		/* Enable global WMAC swapping */
    146		reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
    147		reg |= AR5K_AR2315_BYTESWAP_WMAC;
    148		iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
    149	} else {
    150		/* Enable WMAC DMA access (assuming 5312 or 231x*/
    151		/* TODO: check other platforms */
    152		reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
    153		if (to_platform_device(ah->dev)->id == 0)
    154			reg |= AR5K_AR5312_ENABLE_WLAN0;
    155		else
    156			reg |= AR5K_AR5312_ENABLE_WLAN1;
    157		iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
    158
    159		/*
    160		 * On a dual-band AR5312, the multiband radio is only
    161		 * used as pass-through. Disable 2 GHz support in the
    162		 * driver for it
    163		 */
    164		if (to_platform_device(ah->dev)->id == 0 &&
    165		    (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
    166		     (BD_WLAN1 | BD_WLAN0))
    167			ah->ah_capabilities.cap_needs_2GHz_ovr = true;
    168		else
    169			ah->ah_capabilities.cap_needs_2GHz_ovr = false;
    170	}
    171
    172	ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
    173	if (ret != 0) {
    174		dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
    175		ret = -ENODEV;
    176		goto err_free_hw;
    177	}
    178
    179	platform_set_drvdata(pdev, hw);
    180
    181	return 0;
    182
    183 err_free_hw:
    184	ieee80211_free_hw(hw);
    185 err_iounmap:
    186        iounmap(mem);
    187 err_out:
    188	return ret;
    189}
    190
    191static int ath_ahb_remove(struct platform_device *pdev)
    192{
    193	struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
    194	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
    195	struct ath5k_hw *ah;
    196	u32 reg;
    197
    198	if (!hw)
    199		return 0;
    200
    201	ah = hw->priv;
    202
    203	if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
    204		/* Disable WMAC AHB arbitration */
    205		reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
    206		reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
    207		iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
    208	} else {
    209		/*Stop DMA access */
    210		reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
    211		if (to_platform_device(ah->dev)->id == 0)
    212			reg &= ~AR5K_AR5312_ENABLE_WLAN0;
    213		else
    214			reg &= ~AR5K_AR5312_ENABLE_WLAN1;
    215		iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
    216	}
    217
    218	ath5k_deinit_ah(ah);
    219	iounmap(ah->iobase);
    220	ieee80211_free_hw(hw);
    221
    222	return 0;
    223}
    224
    225static struct platform_driver ath_ahb_driver = {
    226	.probe      = ath_ahb_probe,
    227	.remove     = ath_ahb_remove,
    228	.driver		= {
    229		.name	= "ar231x-wmac",
    230	},
    231};
    232
    233module_platform_driver(ath_ahb_driver);