Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ce34bc8 authored by Daniel Drake's avatar Daniel Drake Committed by Jeff Garzik
Browse files

[PATCH] zd1211rw: Remove addressing abstraction



Instead of passing our own custom 32-bit addresses around and
translating them, this patch makes all our register address constants
absolute and removes the translation.

There are two ugly parts:
 - fw_reg_addr() is needed to compute addresses of firmware registers, as this
   is dynamic based upon firmware
 - inc_addr() needs a small hack to handle byte vs word addressing

However, both of those are only small, and we don't use fw_regs a whole
lot anyway.

The bonuses here include simplicity and improved driver readability. Also, the
fact that registers are now referenced by 16-bit absolute addresses (as
opposed to 32-bit pseudo addresses) means that over 2kb compiled code size has
been shaved off.

Includes some touchups and sparse fixes from Ulrich Kunitz.

Signed-off-by: default avatarDaniel Drake <dsd@gentoo.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ee302767
Loading
Loading
Loading
Loading
+48 −11
Original line number Diff line number Diff line
@@ -84,6 +84,18 @@ static void print_id(struct zd_chip *chip)
	dev_info(zd_chip_dev(chip), "%s\n", buffer);
}

static zd_addr_t inc_addr(zd_addr_t addr)
{
	u16 a = (u16)addr;
	/* Control registers use byte addressing, but everything else uses word
	 * addressing. */
	if ((a & 0xf000) == CR_START)
		a += 2;
	else
		a += 1;
	return (zd_addr_t)a;
}

/* Read a variable number of 32-bit values. Parameter count is not allowed to
 * exceed USB_MAX_IOREAD32_COUNT.
 */
@@ -114,7 +126,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
	for (i = 0; i < count; i++) {
		int j = 2*i;
		/* We read the high word always first. */
		a16[j] = zd_inc_word(addr[i]);
		a16[j] = inc_addr(addr[i]);
		a16[j+1] = addr[i];
	}

@@ -163,7 +175,7 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
		j = 2*i;
		/* We write the high word always first. */
		ioreqs16[j].value   = ioreqs[i].value >> 16;
		ioreqs16[j].addr    = zd_inc_word(ioreqs[i].addr);
		ioreqs16[j].addr    = inc_addr(ioreqs[i].addr);
		ioreqs16[j+1].value = ioreqs[i].value;
		ioreqs16[j+1].addr  = ioreqs[i].addr;
	}
@@ -466,7 +478,8 @@ static int read_values(struct zd_chip *chip, u8 *values, size_t count,

	ZD_ASSERT(mutex_is_locked(&chip->mutex));
	for (i = 0;;) {
		r = zd_ioread32_locked(chip, &v, e2p_addr+i/2);
		r = zd_ioread32_locked(chip, &v,
			               (zd_addr_t)((u16)e2p_addr+i/2));
		if (r)
			return r;
		v -= guard;
@@ -953,6 +966,11 @@ static int hw_init(struct zd_chip *chip)
	return set_beacon_interval(chip, 100);
}

static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
{
	return (zd_addr_t)((u16)chip->fw_regs_base + offset);
}

#ifdef DEBUG
static int dump_cr(struct zd_chip *chip, const zd_addr_t addr,
	           const char *addr_string)
@@ -987,9 +1005,11 @@ static int test_init(struct zd_chip *chip)

static void dump_fw_registers(struct zd_chip *chip)
{
	static const zd_addr_t addr[4] = {
		FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE,
		FW_LINK_STATUS
	const zd_addr_t addr[4] = {
		fw_reg_addr(chip, FW_REG_FIRMWARE_VER),
		fw_reg_addr(chip, FW_REG_USB_SPEED),
		fw_reg_addr(chip, FW_REG_FIX_TX_RATE),
		fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
	};

	int r;
@@ -1015,7 +1035,8 @@ static int print_fw_version(struct zd_chip *chip)
	int r;
	u16 version;

	r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER);
	r = zd_ioread16_locked(chip, &version,
		fw_reg_addr(chip, FW_REG_FIRMWARE_VER));
	if (r)
		return r;

@@ -1095,6 +1116,22 @@ int zd_chip_disable_hwint(struct zd_chip *chip)
	return r;
}

static int read_fw_regs_offset(struct zd_chip *chip)
{
	int r;

	ZD_ASSERT(mutex_is_locked(&chip->mutex));
	r = zd_ioread16_locked(chip, (u16*)&chip->fw_regs_base,
		               FWRAW_REGS_ADDR);
	if (r)
		return r;
	dev_dbg_f(zd_chip_dev(chip), "fw_regs_base: %#06hx\n",
		  (u16)chip->fw_regs_base);

	return 0;
}


int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
{
	int r;
@@ -1114,7 +1151,7 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
	if (r)
		goto out;

	r = zd_usb_init_hw(&chip->usb);
	r = read_fw_regs_offset(chip);
	if (r)
		goto out;

@@ -1294,15 +1331,15 @@ u8 zd_chip_get_channel(struct zd_chip *chip)

int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
{
	static const zd_addr_t a[] = {
		FW_LINK_STATUS,
	const zd_addr_t a[] = {
		fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
		CR_LED,
	};

	int r;
	u16 v[ARRAY_SIZE(a)];
	struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
		[0] = { FW_LINK_STATUS },
		[0] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS) },
		[1] = { CR_LED },
	};
	u16 other_led;
+49 −40
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
#ifndef _ZD_CHIP_H
#define _ZD_CHIP_H

#include "zd_types.h"
#include "zd_rf.h"
#include "zd_usb.h"

@@ -27,6 +26,37 @@
 * adds a processor for handling the USB protocol.
 */

/* Address space */
enum {
	/* CONTROL REGISTERS */
	CR_START			= 0x9000,


	/* FIRMWARE */
	FW_START			= 0xee00,


	/* EEPROM */
	E2P_START			= 0xf800,
	E2P_LEN				= 0x800,

	/* EEPROM layout */
	E2P_LOAD_CODE_LEN		= 0xe,		/* base 0xf800 */
	E2P_LOAD_VECT_LEN		= 0x9,		/* base 0xf80e */
	/* E2P_DATA indexes into this */
	E2P_DATA_LEN			= 0x7e,		/* base 0xf817 */
	E2P_BOOT_CODE_LEN		= 0x760,	/* base 0xf895 */
	E2P_INTR_VECT_LEN		= 0xb,		/* base 0xfff5 */

	/* Some precomputed offsets into the EEPROM */
	E2P_DATA_OFFSET			= E2P_LOAD_CODE_LEN + E2P_LOAD_VECT_LEN,
	E2P_BOOT_CODE_OFFSET		= E2P_DATA_OFFSET + E2P_DATA_LEN,
};

#define CTL_REG(offset) ((zd_addr_t)(CR_START + (offset)))
#define E2P_DATA(offset) ((zd_addr_t)(E2P_START + E2P_DATA_OFFSET + (offset)))
#define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset)))

/* 8-bit hardware registers */
#define CR0   CTL_REG(0x0000)
#define CR1   CTL_REG(0x0004)
@@ -302,7 +332,7 @@

#define CR_MAX_PHY_REG 255

/* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211
/* Taken from the ZYDAS driver, not all of them are relevant for the ZD1211
 * driver.
 */

@@ -638,49 +668,26 @@
#define E2P_54M_INT_VALUE3	E2P_DATA(0x54)
#define E2P_54M_INT_VALUE4	E2P_DATA(0x56)

/* All 16 bit values */
#define FW_FIRMWARE_VER         FW_REG(0)
/* This word contains the base address of the FW_REG_ registers below */
#define FWRAW_REGS_ADDR		FWRAW_DATA(0x1d)

/* All 16 bit values, offset from the address in FWRAW_REGS_ADDR */
enum {
	FW_REG_FIRMWARE_VER	= 0,
	/* non-zero if USB high speed connection */
#define FW_USB_SPEED            FW_REG(1)
#define FW_FIX_TX_RATE          FW_REG(2)
	FW_REG_USB_SPEED	= 1,
	FW_REG_FIX_TX_RATE	= 2,
	/* Seems to be able to control LEDs over the firmware */
#define FW_LINK_STATUS          FW_REG(3)
#define FW_SOFT_RESET           FW_REG(4)
#define FW_FLASH_CHK            FW_REG(5)
	FW_REG_LED_LINK_STATUS	= 3,
	FW_REG_SOFT_RESET	= 4,
	FW_REG_FLASH_CHK	= 5,
};

/* Values for FW_LINK_STATUS */
#define FW_LINK_OFF		0x0
#define FW_LINK_TX		0x1
/* 0x2 - link led on? */

enum {
	/* CONTROL REGISTERS */
	CR_START			= 0x9000,

	/* FIRMWARE */
	FW_START			= 0xee00,

	/* The word at this offset contains the base address of the FW_REG
	 * registers */
	FW_REGS_ADDR_OFFSET		= 0x1d,


	/* EEPROM */
	E2P_START			= 0xf800,
	E2P_LEN				= 0x800,

	/* EEPROM layout */
	E2P_LOAD_CODE_LEN		= 0xe,		/* base 0xf800 */
	E2P_LOAD_VECT_LEN		= 0x9,		/* base 0xf80e */
	/* E2P_DATA indexes into this */
	E2P_DATA_LEN			= 0x7e,		/* base 0xf817 */
	E2P_BOOT_CODE_LEN		= 0x760,	/* base 0xf895 */
	E2P_INTR_VECT_LEN		= 0xb,		/* base 0xfff5 */

	/* Some precomputed offsets into the EEPROM */
	E2P_DATA_OFFSET			= E2P_LOAD_CODE_LEN + E2P_LOAD_VECT_LEN,
	E2P_BOOT_CODE_OFFSET		= E2P_DATA_OFFSET + E2P_DATA_LEN,
};

enum {
	/* indices for ofdm_cal_values */
	OFDM_36M_INDEX = 0,
@@ -692,6 +699,8 @@ struct zd_chip {
	struct zd_usb usb;
	struct zd_rf rf;
	struct mutex mutex;
	/* Base address of FW_REG_ registers */
	zd_addr_t fw_regs_base;
	u8 e2p_mac[ETH_ALEN];
	/* EepSetPoint in the vendor driver */
	u8 pwr_cal_values[E2P_CHANNEL_COUNT];
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <linux/device.h>
#include <linux/kernel.h>

typedef u16 __nocast zd_addr_t;

#define dev_printk_f(level, dev, fmt, args...) \
	dev_printk(level, dev, "%s() " fmt, __func__, ##args)

+0 −1
Original line number Diff line number Diff line
@@ -2,7 +2,6 @@
#define _ZD_IEEE80211_H

#include <net/ieee80211.h>
#include "zd_types.h"

/* Additional definitions from the standards.
 */
+0 −2
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@
#ifndef _ZD_RF_H
#define _ZD_RF_H

#include "zd_types.h"

#define UW2451_RF			0x2
#define UCHIP_RF			0x3
#define AL2230_RF			0x4
Loading