[go: nahoru, domu]

1711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
2711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello/* Radio tuning for RTL8225 on RTL8187SE
3711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello *
4711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
5711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Copyright 2014 Andrea Merello <andrea.merello@gmail.com>
6711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello *
7711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Based on the r8180 and Realtek r8187se drivers, which are:
8711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
9711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello *
10711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Also based on the rtl8187 driver, which is:
11711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
12711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
13711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello *
14711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * This program is free software; you can redistribute it and/or modify
15711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * it under the terms of the GNU General Public License version 2 as
16711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello * published by the Free Software Foundation.
17711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello */
18711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
19711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello#include <net/mac80211.h>
20711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
21711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello#include "rtl8180.h"
22711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello#include "rtl8225se.h"
23711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
24711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello#define PFX "rtl8225 (se) "
25711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
26711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u32 RF_GAIN_TABLE[] = {
27711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6,
28711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057,
29711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3,
30711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3,
31711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0183, 0x0163, 0x0143, 0x0123, 0x0103
32711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
33711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
34711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 cck_ofdm_gain_settings[] = {
35711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
36711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
37711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
38711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
39711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
40711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
41711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
42711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
43711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225se_tx_gain_cck_ofdm[] = {
44711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
45711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
46711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
47711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225se_tx_power_cck[] = {
48711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
49711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
50711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
51711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
52711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
53711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
54711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
55711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
56711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225se_tx_power_cck_ch14[] = {
57711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
58711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
59711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
60711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
61711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
62711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
63711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
64711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
65711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225se_tx_power_ofdm[] = {
66711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
67711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
68711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
69711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u32 rtl8225se_chan[] = {
70711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
71711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A,
72711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
73711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
74711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225sez2_tx_power_cck_ch14[] = {
75711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
76711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
77711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
78711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225sez2_tx_power_cck_B[] = {
79711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
80711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
81711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
82711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225sez2_tx_power_cck_A[] = {
83711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
84711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
85711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
86711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 rtl8225sez2_tx_power_cck[] = {
87711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
88711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
89711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
90711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 ZEBRA_AGC[] = {
91711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A,
92711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
93711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
94711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
95711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27,
96711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
97711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00,
98711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
100711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
101711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b,
102711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
103711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21,
104711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
105711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
106711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
107711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
108711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
109711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const u8 OFDM_CONFIG[] = {
110711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50,
111711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00,
112711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26,
113711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB,
114711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00,
115711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00,
116711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e,
117711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	0xD8, 0x3C, 0x7B, 0x10, 0x10
118711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
119711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
120711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data,
121711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				    u8 len, bool write)
122711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
123711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	struct rtl8180_priv *priv = dev->priv;
124711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	int i;
125711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u8 tmp;
126711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
127711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	do {
128711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		for (i = 0; i < 5; i++) {
129711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
130711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			if (!(tmp & 0x3))
131711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				break;
132711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			udelay(10);
133711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		}
134711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		if (i == 5)
135711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			wiphy_err(dev->wiphy, PFX
136711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				"CmdReg: 0x%x RE/WE bits aren't clear\n", tmp);
137711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
138711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02;
139711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp);
140711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
141711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7;
142711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp);
143711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		if (write) {
144711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			if (len == 16) {
145711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				rtl818x_iowrite16(priv, SW_3W_DB0,
146711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				  *(u16 *)data);
147711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			} else if (len == 64) {
148711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				rtl818x_iowrite32(priv, SW_3W_DB0_4,
149711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				  *((u32 *)data));
150711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				rtl818x_iowrite32(priv, SW_3W_DB1_4,
151711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				  *((u32 *)(data + 4)));
152711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			} else
153711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				wiphy_err(dev->wiphy, PFX
154711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello					"Unimplemented length\n");
155711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		} else {
156711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data);
157711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		}
158711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		if (write)
159711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			tmp = 2;
160711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		else
161711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			tmp = 1;
162711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl818x_iowrite8(priv, SW_3W_CMD1, tmp);
163711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		for (i = 0; i < 5; i++) {
164711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			tmp = rtl818x_ioread8(priv, SW_3W_CMD1);
165711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			if (!(tmp & 0x3))
166711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				break;
167711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			udelay(10);
168711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		}
169711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl818x_iowrite8(priv, SW_3W_CMD1, 0);
170711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		if (!write) {
171711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			*((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG);
172711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			*((u16 *)data) &= 0x0FFF;
173711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		}
174711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	} while (0);
175711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
176711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
177711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr)
178711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
179711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u32 dataread = addr & 0x0F;
180711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0);
181711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	return dataread;
182711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
183711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
184711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data)
185711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
186711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u32 outdata = (data << 4) | (u32)(addr & 0x0F);
187711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1);
188711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
189711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
190711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
191711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev)
192711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
193711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	int i;
194711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
195711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	for (i = 0; i < 128; i++) {
196711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]);
197711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80);
198711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0xE, 0);
199711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	}
200711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
201711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
202711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev)
203711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
204711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* write OFDM_CONFIG table */
205711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	int i;
206711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
207711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	for (i = 0; i < 60; i++)
208711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]);
209711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
210711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
211711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
212711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
213711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
214711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	struct rtl8180_priv *priv = dev->priv;
215711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u8 cck_power, ofdm_power;
216711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
217711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	cck_power = priv->channels[channel - 1].hw_value & 0xFF;
218711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (cck_power > 35)
219711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		cck_power = 35;
220711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
221711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			 cck_ofdm_gain_settings[cck_power]);
222711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
223711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	usleep_range(1000, 5000);
224711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	ofdm_power = priv->channels[channel - 1].hw_value >> 8;
225711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (ofdm_power > 35)
226711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		ofdm_power = 35;
227711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
228711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
229711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello			 cck_ofdm_gain_settings[ofdm_power]);
230711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (ofdm_power < 12) {
231711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 7, 0x5C);
232711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 9, 0x5C);
233711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	}
234711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (ofdm_power < 18) {
235711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 7, 0x54);
236711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 9, 0x54);
237711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	} else {
238711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 7, 0x50);
239711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 9, 0x50);
240711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	}
241711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
242711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	usleep_range(1000, 5000);
243711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
244711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
245711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8187se_write_rf_gain(struct ieee80211_hw *dev)
246711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
247711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	int i;
248711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
249711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	for (i = 0; i <= 36; i++) {
250711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1);
251711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1);
252711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	}
253711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
254711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
255711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic void rtl8187se_write_initial_gain(struct ieee80211_hw *dev,
256711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello					int init_gain)
257711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
258711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	switch (init_gain) {
259711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	default:
260711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
261711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
262711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
263711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
264711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 2:
265711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
266711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
267711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1);
268711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
269711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 3:
270711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
271711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
272711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
273711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
274711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 4:
275711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
276711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
277711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
278711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
279711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 5:
280711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
281711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
282711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1);
283711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
284711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 6:
285711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
286711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
287711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
288711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
289711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 7:
290711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
291711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1);
292711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
293711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
294711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	case 8:
295711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
296711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1);
297711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1);
298711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		break;
299711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	}
300711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
301711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
302711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellovoid rtl8225se_rf_init(struct ieee80211_hw *dev)
303711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
304711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	struct rtl8180_priv *priv = dev->priv;
305711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u32 rf23, rf24;
306711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u8 d_cut = 0;
307711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	u8 tmp;
308711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
309711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* Page 1 */
310711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
311711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1);
312711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1);
313711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (rf23 == 0x0818 && rf24 == 0x070C)
314711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		d_cut = 1;
315711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
316711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	wiphy_info(dev->wiphy, "RTL8225-SE version %s\n",
317711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		d_cut ? "D" : "not-D");
318711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
319711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* Page 0: reg 0 - 15 */
320711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
321711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1);
322711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
323711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1);
324711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1);
325711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1);
326711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1);
327711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1);
328711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1);
329711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1);
330711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1);
331711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1);
332711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1);
333711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
334711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1);
335711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1);
336711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* page 1: reg 16-30 */
337711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1);
338711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1);
339711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1);
340711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1);
341711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1);
342711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1);
343711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
344711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1);
345711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1);
346711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1);
347711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (d_cut)
348711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x0E, 0x0807);
349711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	else
350711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x0E, 0x0806);
351711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	mdelay(1);
352711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1);
353711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1);
354711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1);
355711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1);
356711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
357711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_write_rf_gain(dev);
358711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
359711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1);
360711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1);
361711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
362711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11);
363711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11);
364711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11);
365711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11);
366711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x02, 0x088D); mdelay(221);
367711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11);
368711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1);
369711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1);
370711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1);
371711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1);
372711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1);
373711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1);
374711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if (priv->xtal_cal) {
375711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) |
376711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		      (1 << 11) | (1 << 9);
377711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x0F, tmp);
378711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		wiphy_info(dev->wiphy, "Xtal cal\n");
379711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		mdelay(1);
380711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	} else {
381711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		wiphy_info(dev->wiphy, "NO Xtal cal\n");
382711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC);
383711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		mdelay(1);
384711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	}
385711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* page 0 */
386711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1);
387711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1);
388711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1);
389711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(31);
390711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1);
391711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1);
392711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
393711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1);
394711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1);
395711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1);
396711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* power save parameters */
397711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* TODO: move to dev.c */
398711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl818x_iowrite8(priv, REG_ADDR1(0x024E),
399711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		 rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F);
400711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_cck(dev, 0x00, 0xC8);
401711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_cck(dev, 0x06, 0x1C);
402711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_cck(dev, 0x10, 0x78);
403711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_cck(dev, 0x2E, 0xD0);
404711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_cck(dev, 0x2F, 0x06);
405711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_cck(dev, 0x01, 0x46);
406711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
407711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* power control */
408711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10);
409711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B);
410711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
411711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
412711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_ofdm(dev, 0x00, 0x12);
413711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
414711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_zebra_agc(dev);
415711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
416711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
417711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
418711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_write_ofdm_config(dev);
419711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
420711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* turn on RF */
421711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
422711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
423711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* turn on RF again */
424711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500);
425711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500);
426711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* turn on BB */
427711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_ofdm(dev, 0x10, 0x40);
428711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_ofdm(dev, 0x12, 0x40);
429711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
430711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_write_initial_gain(dev, 4);
431711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
432711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
433711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellovoid rtl8225se_rf_stop(struct ieee80211_hw *dev)
434711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
435711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* checked for 8187se */
436711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	struct rtl8180_priv *priv = dev->priv;
437711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
438711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* turn off BB RXIQ matrix to cut off rx signal */
439711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_ofdm(dev, 0x10, 0x00);
440711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225se_write_phy_ofdm(dev, 0x12, 0x00);
441711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* turn off RF */
442711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x04, 0x0000);
443711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x00, 0x0000);
444711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
445711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	usleep_range(1000, 5000);
446711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	/* turn off A/D and D/A */
447711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF);
448711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF);
449711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
450711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
451711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellovoid rtl8225se_rf_set_channel(struct ieee80211_hw *dev,
452711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello				   struct ieee80211_conf *conf)
453711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
454711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	int chan =
455711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
456711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
457711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8225sez2_rf_set_tx_power(dev, chan);
458711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
459711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) !=
460711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8225se_chan[chan - 1])
461711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello		rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]);
462711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	usleep_range(10000, 20000);
463711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
464711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
465711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merellostatic const struct rtl818x_rf_ops rtl8225se_ops = {
466711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	.name		= "rtl8225-se",
467711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	.init		= rtl8225se_rf_init,
468711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	.stop		= rtl8225se_rf_stop,
469711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	.set_chan	= rtl8225se_rf_set_channel,
470711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello};
471711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello
472711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merelloconst struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev)
473711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello{
474711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello	return &rtl8225se_ops;
475711d4ed38143a01b0f109e11e47e62e9f589d4e3Andrea Merello}
476