18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci/* Radio tuning for RTL8225 on RTL8187SE 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net> 68c2ecf20Sopenharmony_ci * Copyright 2014 Andrea Merello <andrea.merello@gmail.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Based on the r8180 and Realtek r8187se drivers, which are: 98c2ecf20Sopenharmony_ci * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Also based on the rtl8187 driver, which is: 128c2ecf20Sopenharmony_ci * Copyright 2007 Michael Wu <flamingice@sourmilk.net> 138c2ecf20Sopenharmony_ci * Copyright 2007 Andrea Merello <andrea.merello@gmail.com> 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <net/mac80211.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "rtl8180.h" 198c2ecf20Sopenharmony_ci#include "rtl8225se.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define PFX "rtl8225 (se) " 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic const u32 RF_GAIN_TABLE[] = { 248c2ecf20Sopenharmony_ci 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6, 258c2ecf20Sopenharmony_ci 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057, 268c2ecf20Sopenharmony_ci 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3, 278c2ecf20Sopenharmony_ci 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3, 288c2ecf20Sopenharmony_ci 0x0183, 0x0163, 0x0143, 0x0123, 0x0103 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic const u8 cck_ofdm_gain_settings[] = { 328c2ecf20Sopenharmony_ci 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 338c2ecf20Sopenharmony_ci 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 348c2ecf20Sopenharmony_ci 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 358c2ecf20Sopenharmony_ci 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 368c2ecf20Sopenharmony_ci 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 378c2ecf20Sopenharmony_ci 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic const u32 rtl8225se_chan[] = { 418c2ecf20Sopenharmony_ci 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, 428c2ecf20Sopenharmony_ci 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A, 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const u8 ZEBRA_AGC[] = { 468c2ecf20Sopenharmony_ci 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 478c2ecf20Sopenharmony_ci 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 488c2ecf20Sopenharmony_ci 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 498c2ecf20Sopenharmony_ci 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 508c2ecf20Sopenharmony_ci 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, 518c2ecf20Sopenharmony_ci 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07, 528c2ecf20Sopenharmony_ci 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 538c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 548c2ecf20Sopenharmony_ci 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 558c2ecf20Sopenharmony_ci 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 568c2ecf20Sopenharmony_ci 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, 578c2ecf20Sopenharmony_ci 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 588c2ecf20Sopenharmony_ci 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 598c2ecf20Sopenharmony_ci 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24, 608c2ecf20Sopenharmony_ci 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 618c2ecf20Sopenharmony_ci 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic const u8 OFDM_CONFIG[] = { 658c2ecf20Sopenharmony_ci 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50, 668c2ecf20Sopenharmony_ci 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 678c2ecf20Sopenharmony_ci 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26, 688c2ecf20Sopenharmony_ci 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB, 698c2ecf20Sopenharmony_ci 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00, 708c2ecf20Sopenharmony_ci 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00, 718c2ecf20Sopenharmony_ci 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e, 728c2ecf20Sopenharmony_ci 0xD8, 0x3C, 0x7B, 0x10, 0x10 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data, 768c2ecf20Sopenharmony_ci u8 len, bool write) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci struct rtl8180_priv *priv = dev->priv; 798c2ecf20Sopenharmony_ci int i; 808c2ecf20Sopenharmony_ci u8 tmp; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci do { 838c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 848c2ecf20Sopenharmony_ci tmp = rtl818x_ioread8(priv, SW_3W_CMD1); 858c2ecf20Sopenharmony_ci if (!(tmp & 0x3)) 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci udelay(10); 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci if (i == 5) 908c2ecf20Sopenharmony_ci wiphy_err(dev->wiphy, PFX 918c2ecf20Sopenharmony_ci "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02; 948c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7; 978c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp); 988c2ecf20Sopenharmony_ci if (write) { 998c2ecf20Sopenharmony_ci if (len == 16) { 1008c2ecf20Sopenharmony_ci rtl818x_iowrite16(priv, SW_3W_DB0, 1018c2ecf20Sopenharmony_ci *(u16 *)data); 1028c2ecf20Sopenharmony_ci } else if (len == 64) { 1038c2ecf20Sopenharmony_ci rtl818x_iowrite32(priv, SW_3W_DB0_4, 1048c2ecf20Sopenharmony_ci *((u32 *)data)); 1058c2ecf20Sopenharmony_ci rtl818x_iowrite32(priv, SW_3W_DB1_4, 1068c2ecf20Sopenharmony_ci *((u32 *)(data + 4))); 1078c2ecf20Sopenharmony_ci } else 1088c2ecf20Sopenharmony_ci wiphy_err(dev->wiphy, PFX 1098c2ecf20Sopenharmony_ci "Unimplemented length\n"); 1108c2ecf20Sopenharmony_ci } else { 1118c2ecf20Sopenharmony_ci rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data); 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci if (write) 1148c2ecf20Sopenharmony_ci tmp = 2; 1158c2ecf20Sopenharmony_ci else 1168c2ecf20Sopenharmony_ci tmp = 1; 1178c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, SW_3W_CMD1, tmp); 1188c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 1198c2ecf20Sopenharmony_ci tmp = rtl818x_ioread8(priv, SW_3W_CMD1); 1208c2ecf20Sopenharmony_ci if (!(tmp & 0x3)) 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci udelay(10); 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, SW_3W_CMD1, 0); 1258c2ecf20Sopenharmony_ci if (!write) { 1268c2ecf20Sopenharmony_ci *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG); 1278c2ecf20Sopenharmony_ci *((u16 *)data) &= 0x0FFF; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci } while (0); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci u32 dataread = addr & 0x0F; 1358c2ecf20Sopenharmony_ci rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0); 1368c2ecf20Sopenharmony_ci return dataread; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci u32 outdata = (data << 4) | (u32)(addr & 0x0F); 1428c2ecf20Sopenharmony_ci rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci int i; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci for (i = 0; i < 128; i++) { 1518c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]); 1528c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80); 1538c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0xE, 0); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci /* write OFDM_CONFIG table */ 1608c2ecf20Sopenharmony_ci int i; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci for (i = 0; i < 60; i++) 1638c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci struct rtl8180_priv *priv = dev->priv; 1708c2ecf20Sopenharmony_ci u8 cck_power, ofdm_power; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci cck_power = priv->channels[channel - 1].hw_value & 0xFF; 1738c2ecf20Sopenharmony_ci if (cck_power > 35) 1748c2ecf20Sopenharmony_ci cck_power = 35; 1758c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 1768c2ecf20Sopenharmony_ci cck_ofdm_gain_settings[cck_power]); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci usleep_range(1000, 5000); 1798c2ecf20Sopenharmony_ci ofdm_power = priv->channels[channel - 1].hw_value >> 8; 1808c2ecf20Sopenharmony_ci if (ofdm_power > 35) 1818c2ecf20Sopenharmony_ci ofdm_power = 35; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 1848c2ecf20Sopenharmony_ci cck_ofdm_gain_settings[ofdm_power]); 1858c2ecf20Sopenharmony_ci if (ofdm_power < 12) { 1868c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 7, 0x5C); 1878c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 9, 0x5C); 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci if (ofdm_power < 18) { 1908c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 7, 0x54); 1918c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 9, 0x54); 1928c2ecf20Sopenharmony_ci } else { 1938c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 7, 0x50); 1948c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 9, 0x50); 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci usleep_range(1000, 5000); 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic void rtl8187se_write_rf_gain(struct ieee80211_hw *dev) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci int i; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci for (i = 0; i <= 36; i++) { 2058c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1); 2068c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1); 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic void rtl8187se_write_initial_gain(struct ieee80211_hw *dev, 2118c2ecf20Sopenharmony_ci int init_gain) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci switch (init_gain) { 2148c2ecf20Sopenharmony_ci default: 2158c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); 2168c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); 2178c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci case 2: 2208c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); 2218c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); 2228c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci case 3: 2258c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); 2268c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); 2278c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci case 4: 2308c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); 2318c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); 2328c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); 2338c2ecf20Sopenharmony_ci break; 2348c2ecf20Sopenharmony_ci case 5: 2358c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); 2368c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); 2378c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); 2388c2ecf20Sopenharmony_ci break; 2398c2ecf20Sopenharmony_ci case 6: 2408c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); 2418c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); 2428c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); 2438c2ecf20Sopenharmony_ci break; 2448c2ecf20Sopenharmony_ci case 7: 2458c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); 2468c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1); 2478c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); 2488c2ecf20Sopenharmony_ci break; 2498c2ecf20Sopenharmony_ci case 8: 2508c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1); 2518c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1); 2528c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); 2538c2ecf20Sopenharmony_ci break; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_civoid rtl8225se_rf_init(struct ieee80211_hw *dev) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci struct rtl8180_priv *priv = dev->priv; 2608c2ecf20Sopenharmony_ci u32 rf23, rf24; 2618c2ecf20Sopenharmony_ci u8 d_cut = 0; 2628c2ecf20Sopenharmony_ci u8 tmp; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* Page 1 */ 2658c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); 2668c2ecf20Sopenharmony_ci rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1); 2678c2ecf20Sopenharmony_ci rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1); 2688c2ecf20Sopenharmony_ci if (rf23 == 0x0818 && rf24 == 0x070C) 2698c2ecf20Sopenharmony_ci d_cut = 1; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci wiphy_info(dev->wiphy, "RTL8225-SE version %s\n", 2728c2ecf20Sopenharmony_ci d_cut ? "D" : "not-D"); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci /* Page 0: reg 0 - 15 */ 2758c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); 2768c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1); 2778c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); 2788c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1); 2798c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1); 2808c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1); 2818c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1); 2828c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1); 2838c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1); 2848c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1); 2858c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1); 2868c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1); 2878c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1); 2888c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); 2898c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1); 2908c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1); 2918c2ecf20Sopenharmony_ci /* page 1: reg 16-30 */ 2928c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); 2938c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1); 2948c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1); 2958c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1); 2968c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1); 2978c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1); 2988c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); 2998c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1); 3008c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1); 3018c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1); 3028c2ecf20Sopenharmony_ci if (d_cut) 3038c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0E, 0x0807); 3048c2ecf20Sopenharmony_ci else 3058c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0E, 0x0806); 3068c2ecf20Sopenharmony_ci mdelay(1); 3078c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1); 3088c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1); 3098c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1); 3108c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci rtl8187se_write_rf_gain(dev); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1); 3158c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1); 3168c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); 3178c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11); 3188c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11); 3198c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11); 3208c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11); 3218c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x02, 0x088D); msleep(221); 3228c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); 3238c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1); 3248c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1); 3258c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1); 3268c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1); 3278c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1); 3288c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); 3298c2ecf20Sopenharmony_ci if (priv->xtal_cal) { 3308c2ecf20Sopenharmony_ci tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) | 3318c2ecf20Sopenharmony_ci (1 << 11) | (1 << 9); 3328c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0F, tmp); 3338c2ecf20Sopenharmony_ci wiphy_info(dev->wiphy, "Xtal cal\n"); 3348c2ecf20Sopenharmony_ci mdelay(1); 3358c2ecf20Sopenharmony_ci } else { 3368c2ecf20Sopenharmony_ci wiphy_info(dev->wiphy, "NO Xtal cal\n"); 3378c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); 3388c2ecf20Sopenharmony_ci mdelay(1); 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci /* page 0 */ 3418c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1); 3428c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); 3438c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); 3448c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0975); msleep(31); 3458c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1); 3468c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); 3498c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1); 3508c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1); 3518c2ecf20Sopenharmony_ci /* power save parameters */ 3528c2ecf20Sopenharmony_ci /* TODO: move to dev.c */ 3538c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, REG_ADDR1(0x024E), 3548c2ecf20Sopenharmony_ci rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F); 3558c2ecf20Sopenharmony_ci rtl8225se_write_phy_cck(dev, 0x00, 0xC8); 3568c2ecf20Sopenharmony_ci rtl8225se_write_phy_cck(dev, 0x06, 0x1C); 3578c2ecf20Sopenharmony_ci rtl8225se_write_phy_cck(dev, 0x10, 0x78); 3588c2ecf20Sopenharmony_ci rtl8225se_write_phy_cck(dev, 0x2E, 0xD0); 3598c2ecf20Sopenharmony_ci rtl8225se_write_phy_cck(dev, 0x2F, 0x06); 3608c2ecf20Sopenharmony_ci rtl8225se_write_phy_cck(dev, 0x01, 0x46); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci /* power control */ 3638c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10); 3648c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); 3678c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x00, 0x12); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci rtl8225se_write_zebra_agc(dev); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci rtl8187se_write_ofdm_config(dev); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* turn on RF */ 3768c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); 3778c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); 3788c2ecf20Sopenharmony_ci /* turn on RF again */ 3798c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); 3808c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); 3818c2ecf20Sopenharmony_ci /* turn on BB */ 3828c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x10, 0x40); 3838c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x12, 0x40); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci rtl8187se_write_initial_gain(dev, 4); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_civoid rtl8225se_rf_stop(struct ieee80211_hw *dev) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci /* checked for 8187se */ 3918c2ecf20Sopenharmony_ci struct rtl8180_priv *priv = dev->priv; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* turn off BB RXIQ matrix to cut off rx signal */ 3948c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); 3958c2ecf20Sopenharmony_ci rtl8225se_write_phy_ofdm(dev, 0x12, 0x00); 3968c2ecf20Sopenharmony_ci /* turn off RF */ 3978c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x04, 0x0000); 3988c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x00, 0x0000); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci usleep_range(1000, 5000); 4018c2ecf20Sopenharmony_ci /* turn off A/D and D/A */ 4028c2ecf20Sopenharmony_ci rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF); 4038c2ecf20Sopenharmony_ci rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_civoid rtl8225se_rf_set_channel(struct ieee80211_hw *dev, 4078c2ecf20Sopenharmony_ci struct ieee80211_conf *conf) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci int chan = 4108c2ecf20Sopenharmony_ci ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci rtl8225sez2_rf_set_tx_power(dev, chan); 4138c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); 4148c2ecf20Sopenharmony_ci if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) != 4158c2ecf20Sopenharmony_ci rtl8225se_chan[chan - 1]) 4168c2ecf20Sopenharmony_ci rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); 4178c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic const struct rtl818x_rf_ops rtl8225se_ops = { 4218c2ecf20Sopenharmony_ci .name = "rtl8225-se", 4228c2ecf20Sopenharmony_ci .init = rtl8225se_rf_init, 4238c2ecf20Sopenharmony_ci .stop = rtl8225se_rf_stop, 4248c2ecf20Sopenharmony_ci .set_chan = rtl8225se_rf_set_channel, 4258c2ecf20Sopenharmony_ci}; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ciconst struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci return &rtl8225se_ops; 4308c2ecf20Sopenharmony_ci} 431