1a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 2a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Intel Wireless WiMAX Connection 2400m 3a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Linux driver model glue for the SDIO device, reset & fw upload 4a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 5a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 6a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> 7a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Dirk Brandewie <dirk.j.brandewie@intel.com> 8a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 9a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Yanir Lubetkin <yanirx.lubetkin@intel.com> 10a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 11a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 12a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 13a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 14a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 15a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 16a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 17a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * GNU General Public License for more details. 19a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 20a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 21a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * along with this program; if not, write to the Free Software 22a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 02110-1301, USA. 24a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 25a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 26a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * See i2400m-sdio.h for a general description of this driver. 27a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 28a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * This file implements driver model glue, and hook ups for the 29a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * generic driver to implement the bus-specific functions (device 30a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * communication setup/tear down, firmware upload and resetting). 31a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 32a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * ROADMAP 33a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 34a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400m_probe() 35a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * alloc_netdev() 36a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400ms_netdev_setup() 37a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400ms_init() 38a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400m_netdev_setup() 39a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400ms_enable_function() 40a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400m_setup() 41a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 42a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400m_remove() 43a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * i2400m_release() 44a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * free_netdev(net_dev) 45a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 46c931ceeb780560ff652a8f9875f88778439ee87eInaky Perez-Gonzalez * i2400ms_bus_reset() Called by i2400m_reset 47a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * __i2400ms_reset() 48a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * __i2400ms_send_barker() 49a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 50a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 515a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 52a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#include <linux/debugfs.h> 5351def0bea92629dff02ff1de40603eb90c609c55Tomas Winkler#include <linux/mmc/sdio_ids.h> 54a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#include <linux/mmc/sdio.h> 55a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#include <linux/mmc/sdio_func.h> 56a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#include "i2400m-sdio.h" 57a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#include <linux/wimax/i2400m.h> 589d9779e723a5d23b94abbe5bb7d1197921f6f3ddPaul Gortmaker#include <linux/module.h> 59a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 60a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#define D_SUBMODULE main 61a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#include "sdio-debug-levels.h" 62a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 63a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* IOE WiMAX function timeout in seconds */ 64a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic int ioe_timeout = 2; 65a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezmodule_param(ioe_timeout, int, 0); 66a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 674c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalezstatic char i2400ms_debug_params[128]; 684c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalezmodule_param_string(debug, i2400ms_debug_params, sizeof(i2400ms_debug_params), 694c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez 0644); 704c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-GonzalezMODULE_PARM_DESC(debug, 714c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez "String of space-separated NAME:VALUE pairs, where NAMEs " 724c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez "are the different debug submodules and VALUE are the " 734c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez "initial debug value to set."); 744c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez 751039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez/* Our firmware file name list */ 761039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalezstatic const char *i2400ms_bus_fw_names[] = { 771039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-1.3.sbcf" 781039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez I2400MS_FW_FILE_NAME, 791039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez NULL 801039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez}; 811039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez 82a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 831c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewiestatic const struct i2400m_poke_table i2400ms_pokes[] = { 841c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie I2400M_FW_POKE(0x6BE260, 0x00000088), 851c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie I2400M_FW_POKE(0x080550, 0x00000005), 861c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie I2400M_FW_POKE(0xAE0000, 0x00000000), 871c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie I2400M_FW_POKE(0x000000, 0x00000000), /* MUST be 0 terminated or bad 881c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie * things will happen */ 891c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie}; 901c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie 91a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 92a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Enable the SDIO function 93a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 94a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Tries to enable the SDIO function; might fail if it is still not 95a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * ready (in some hardware, the SDIO WiMAX function is only enabled 96a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * when we ask it to explicitly doing). Tries until a timeout is 97a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * reached. 98a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 99c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez * The @maxtries argument indicates how many times (at most) it should 100c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez * be tried to enable the function. 0 means forever. This acts along 101c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez * with the timeout (ie: it'll stop trying as soon as the maximum 102c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez * number of tries is reached _or_ as soon as the timeout is reached). 103c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez * 104a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * The reverse of this is...sdio_disable_function() 105a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 106a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Returns: 0 if the SDIO function was enabled, < 0 errno code on 107a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * error (-ENODEV when it was unable to enable the function). 108a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 109a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 11002eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalezint i2400ms_enable_function(struct i2400ms *i2400ms, unsigned maxtries) 111a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 11202eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez struct sdio_func *func = i2400ms->func; 113a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez u64 timeout; 114a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez int err; 115a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct device *dev = &func->dev; 116c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez unsigned tries = 0; 117a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 118a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_fnstart(3, dev, "(func %p)\n", func); 119a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez /* Setup timeout (FIXME: This needs to read the CIS table to 120a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * get a real timeout) and then wait for the device to signal 121a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * it is ready */ 122a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez timeout = get_jiffies_64() + ioe_timeout * HZ; 123a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez err = -ENODEV; 124a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez while (err != 0 && time_before64(get_jiffies_64(), timeout)) { 125a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_claim_host(func); 126f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao /* 127f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao * There is a sillicon bug on the IWMC3200, where the 128f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao * IOE timeout will cause problems on Moorestown 129f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao * platforms (system hang). We explicitly overwrite 130f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao * func->enable_timeout here to work around the issue. 131f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao */ 13202eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez if (i2400ms->iwmc3200) 133f2696fbdb623993a9b4c05455df7ae3158a01111Cindy H Kao func->enable_timeout = IWMC3200_IOR_TIMEOUT; 134a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez err = sdio_enable_func(func); 135a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (0 == err) { 136a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_release_host(func); 137a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_printf(2, dev, "SDIO function enabled\n"); 138a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto function_enabled; 139a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 140a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_printf(2, dev, "SDIO function failed to enable: %d\n", err); 141a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_release_host(func); 142c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez if (maxtries > 0 && ++tries >= maxtries) { 143c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez err = -ETIME; 144c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez break; 145c77ca950abb587bcebad6dcd0b0b41d7c0255ce9Inaky Perez-Gonzalez } 146a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez msleep(I2400MS_INIT_SLEEP_INTERVAL); 147a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 148a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez /* If timed out, device is not there yet -- get -ENODEV so 149a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * the device driver core will retry later on. */ 150a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (err == -ETIME) { 151a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez dev_err(dev, "Can't enable WiMAX function; " 152a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez " has the function been enabled?\n"); 153a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez err = -ENODEV; 154a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 155a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezfunction_enabled: 156a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_fnend(3, dev, "(func %p) = %d\n", func, err); 157a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return err; 158a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 159a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 160a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 161a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 1620856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez * Setup minimal device communication infrastructure needed to at 1630856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez * least be able to update the firmware. 164fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez * 165fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez * Note the ugly trick: if we are in the probe path 166fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez * (i2400ms->debugfs_dentry == NULL), we only retry function 167fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez * enablement one, to avoid racing with the iwmc3200 top controller. 1680856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez */ 1690856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezstatic 1700856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezint i2400ms_bus_setup(struct i2400m *i2400m) 1710856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez{ 1720856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez int result; 1730856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez struct i2400ms *i2400ms = 1740856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez container_of(i2400m, struct i2400ms, i2400m); 1750856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez struct device *dev = i2400m_dev(i2400m); 1760856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez struct sdio_func *func = i2400ms->func; 177fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez int retries; 1780856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 1790856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_claim_host(func); 1800856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez result = sdio_set_block_size(func, I2400MS_BLK_SIZE); 1810856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_release_host(func); 1820856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez if (result < 0) { 1830856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez dev_err(dev, "Failed to set block size: %d\n", result); 1840856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez goto error_set_blk_size; 1850856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez } 1860856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 187fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL) 188fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez retries = 1; 189e7fec0bbf13b9bc2869a18e66f0cda7bb7f559f0Inaky Perez-Gonzalez else 190e7fec0bbf13b9bc2869a18e66f0cda7bb7f559f0Inaky Perez-Gonzalez retries = 0; 191fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez result = i2400ms_enable_function(i2400ms, retries); 1920856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez if (result < 0) { 1930856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez dev_err(dev, "Cannot enable SDIO function: %d\n", result); 1940856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez goto error_func_enable; 1950856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez } 1960856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 197a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez result = i2400ms_tx_setup(i2400ms); 198a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez if (result < 0) 199a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez goto error_tx_setup; 2000856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez result = i2400ms_rx_setup(i2400ms); 2010856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez if (result < 0) 2020856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez goto error_rx_setup; 2030856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez return 0; 2040856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 2050856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezerror_rx_setup: 206a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez i2400ms_tx_release(i2400ms); 207a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalezerror_tx_setup: 2080856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_claim_host(func); 2090856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_disable_func(func); 2100856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_release_host(func); 2110856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezerror_func_enable: 2120856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezerror_set_blk_size: 2130856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez return result; 2140856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez} 2150856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 2160856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 2170856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez/* 2180856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez * Tear down minimal device communication infrastructure needed to at 2190856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez * least be able to update the firmware. 2200856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez */ 2210856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezstatic 2220856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalezvoid i2400ms_bus_release(struct i2400m *i2400m) 2230856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez{ 2240856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez struct i2400ms *i2400ms = 2250856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez container_of(i2400m, struct i2400ms, i2400m); 2260856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez struct sdio_func *func = i2400ms->func; 2270856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 2280856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez i2400ms_rx_release(i2400ms); 229a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez i2400ms_tx_release(i2400ms); 2300856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_claim_host(func); 2310856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_disable_func(func); 2320856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez sdio_release_host(func); 2330856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez} 2340856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 2350856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez 2360856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez/* 237a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Setup driver resources needed to communicate with the device 238a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 239a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * The fw needs some time to settle, and it was just uploaded, 240a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * so give it a break first. I'd prefer to just wait for the device to 241a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * send something, but seems the poking we do to enable SDIO stuff 242a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * interferes with it, so just give it a break before starting... 243a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 244a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 245a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezint i2400ms_bus_dev_start(struct i2400m *i2400m) 246a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 247a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); 248a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct sdio_func *func = i2400ms->func; 249a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct device *dev = &func->dev; 250a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 251a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_fnstart(3, dev, "(i2400m %p)\n", i2400m); 252a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez msleep(200); 253a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0); 254a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez return 0; 255a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 256a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 257a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 258a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 259a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Sends a barker buffer to the device 260a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 261a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * This helper will allocate a kmalloced buffer and use it to transmit 262a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * (then free it). Reason for this is that the SDIO host controller 263a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * expects alignment (unknown exactly which) which the stack won't 264a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * really provide and certain arches/host-controller combinations 265a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * cannot use stack/vmalloc/text areas for DMA transfers. 266a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 267a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 268a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezint __i2400ms_send_barker(struct i2400ms *i2400ms, 269a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez const __le32 *barker, size_t barker_size) 270a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 271a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez int ret; 272a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct sdio_func *func = i2400ms->func; 273a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct device *dev = &func->dev; 274a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez void *buffer; 275a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 276a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez ret = -ENOMEM; 277a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL); 278a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (buffer == NULL) 279a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto error_kzalloc; 280a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 281a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez memcpy(buffer, barker, barker_size); 282a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_claim_host(func); 283a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE); 284a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_release_host(func); 285a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 286a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (ret < 0) 287a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_printf(0, dev, "E: barker error: %d\n", ret); 288a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 289a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez kfree(buffer); 290a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezerror_kzalloc: 291a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return ret; 292a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 293a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 294a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 295a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 296a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Reset a device at different levels (warm, cold or bus) 297a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 298a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * @i2400ms: device descriptor 299a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) 300a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 301a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * FIXME: not tested -- need to confirm expected effects 302a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 303a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Warm and cold resets get an SDIO reset if they fail (unimplemented) 304a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 305a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Warm reset: 306a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 307a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * The device will be fully reset internally, but won't be 30881b182a7542c4282191fa0b1e8d9fcb022c03e68Dirk Brandewie * disconnected from the bus (so no reenumeration will 3093ad2f3fbb961429d2aa627465ae4829758bc7e07Daniel Mack * happen). Firmware upload will be necessary. 310a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 31181b182a7542c4282191fa0b1e8d9fcb022c03e68Dirk Brandewie * The device will send a reboot barker that will trigger the driver 31281b182a7542c4282191fa0b1e8d9fcb022c03e68Dirk Brandewie * to reinitialize the state via __i2400m_dev_reset_handle. 313a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 31481b182a7542c4282191fa0b1e8d9fcb022c03e68Dirk Brandewie * 31581b182a7542c4282191fa0b1e8d9fcb022c03e68Dirk Brandewie * Cold and bus reset: 316a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 317a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * The device will be fully reset internally, disconnected from the 31881b182a7542c4282191fa0b1e8d9fcb022c03e68Dirk Brandewie * bus an a reenumeration will happen. Firmware upload will be 3193ad2f3fbb961429d2aa627465ae4829758bc7e07Daniel Mack * necessary. Thus, we don't do any locking or struct 320a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * reinitialization, as we are going to be fully disconnected and 321a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * reenumerated. 322a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 323a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Note we need to return -ENODEV if a warm reset was requested and we 324a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() 325a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * and wimax_dev->op_reset. 326a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 327a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * WARNING: no driver state saved/fixed 328a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 329a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 330a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezint i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) 331a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 33210b1de6b774a531c9054ee01e734a85ffbab179eDirk Brandewie int result = 0; 333a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400ms *i2400ms = 334a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez container_of(i2400m, struct i2400ms, i2400m); 335a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct device *dev = i2400m_dev(i2400m); 336a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez static const __le32 i2400m_WARM_BOOT_BARKER[4] = { 337ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_WARM_RESET_BARKER), 338ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_WARM_RESET_BARKER), 339ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_WARM_RESET_BARKER), 340ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_WARM_RESET_BARKER), 341a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez }; 342a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez static const __le32 i2400m_COLD_BOOT_BARKER[4] = { 343ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_COLD_RESET_BARKER), 344ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_COLD_RESET_BARKER), 345ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_COLD_RESET_BARKER), 346ee437770c42088b9b653e8b3bf28a61fa647f84eHarvey Harrison cpu_to_le32(I2400M_COLD_RESET_BARKER), 347a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez }; 348a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 349a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (rt == I2400M_RT_WARM) 350a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER, 351a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sizeof(i2400m_WARM_BOOT_BARKER)); 352a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez else if (rt == I2400M_RT_COLD) 353a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER, 354a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sizeof(i2400m_COLD_BOOT_BARKER)); 355a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez else if (rt == I2400M_RT_BUS) { 356a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezdo_bus_reset: 35710b1de6b774a531c9054ee01e734a85ffbab179eDirk Brandewie 3580856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez i2400ms_bus_release(i2400m); 35910b1de6b774a531c9054ee01e734a85ffbab179eDirk Brandewie 36010b1de6b774a531c9054ee01e734a85ffbab179eDirk Brandewie /* Wait for the device to settle */ 36110b1de6b774a531c9054ee01e734a85ffbab179eDirk Brandewie msleep(40); 36210b1de6b774a531c9054ee01e734a85ffbab179eDirk Brandewie 3630856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez result = i2400ms_bus_setup(i2400m); 364a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } else 365a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez BUG(); 366a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (result < 0 && rt != I2400M_RT_BUS) { 367a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez dev_err(dev, "%s reset failed (%d); trying SDIO reset\n", 368a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez rt == I2400M_RT_WARM ? "warm" : "cold", result); 369a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez rt = I2400M_RT_BUS; 370a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto do_bus_reset; 371a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 372a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return result; 373a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 374a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 375a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 376a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 377a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezvoid i2400ms_netdev_setup(struct net_device *net_dev) 378a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 379a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400m *i2400m = net_dev_to_i2400m(net_dev); 380a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); 381a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400ms_init(i2400ms); 382a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m_netdev_setup(net_dev); 383a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 384a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 385a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 386a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 387a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Debug levels control; see debug.h 388a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 389a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstruct d_level D_LEVEL[] = { 390a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez D_SUBMODULE_DEFINE(main), 391a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez D_SUBMODULE_DEFINE(tx), 392a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez D_SUBMODULE_DEFINE(rx), 393a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez D_SUBMODULE_DEFINE(fw), 394a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez}; 395a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezsize_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); 396a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 397a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 398a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez#define __debugfs_register(prefix, name, parent) \ 399a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezdo { \ 400a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = d_level_register_debugfs(prefix, name, parent); \ 401a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (result < 0) \ 402a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto error; \ 403a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} while (0) 404a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 405a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 406a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 407a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezint i2400ms_debugfs_add(struct i2400ms *i2400ms) 408a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 409a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez int result; 410a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry; 411a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 41220d57f8e2553fa6f5cd382131b7f18e91c7141fcInaky Perez-Gonzalez dentry = debugfs_create_dir("i2400m-sdio", dentry); 413a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = PTR_ERR(dentry); 414a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (IS_ERR(dentry)) { 415a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (result == -ENODEV) 416a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = 0; /* No debugfs support */ 417a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto error; 418a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 419a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400ms->debugfs_dentry = dentry; 420a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez __debugfs_register("dl_", main, dentry); 421a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez __debugfs_register("dl_", tx, dentry); 422a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez __debugfs_register("dl_", rx, dentry); 423a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez __debugfs_register("dl_", fw, dentry); 424a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 425a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return 0; 426a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 427a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezerror: 428a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez debugfs_remove_recursive(i2400ms->debugfs_dentry); 429fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez i2400ms->debugfs_dentry = NULL; 430a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return result; 431a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 432a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 433a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 434384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmannstatic struct device_type i2400ms_type = { 435384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann .name = "wimax", 436384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann}; 437384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann 438a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez/* 439a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Probe a i2400m interface and register it 440a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 441a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * @func: SDIO function 442a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * @id: SDIO device ID 443a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * @returns: 0 if ok, < 0 errno code on error. 444a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 445a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Alloc a net device, initialize the bus-specific details and then 446a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * calls the bus-generic initialization routine. That will register 447a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * the wimax and netdev devices, upload the firmware [using 448a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the 449a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * communication with the device and then will start to talk to it to 450a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * finnish setting it up. 451a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * 452a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * Initialization is tricky; some instances of the hw are packed with 453a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * others in a way that requires a third driver that enables the WiMAX 454a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * function. In those cases, we can't enable the SDIO function and 455a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * we'll return with -ENODEV. When the driver that enables the WiMAX 456a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * function does its thing, it has to do a bus_rescan_devices() on the 457a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * SDIO bus so this driver is called again to enumerate the WiMAX 458a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez * function. 459a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez */ 460a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 461a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezint i2400ms_probe(struct sdio_func *func, 462a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez const struct sdio_device_id *id) 463a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 464a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez int result; 465a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct net_device *net_dev; 466a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct device *dev = &func->dev; 467a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400m *i2400m; 468a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400ms *i2400ms; 469a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 470a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez /* Allocate instance [calls i2400m_netdev_setup() on it]. */ 471a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = -ENOMEM; 472a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d", 473a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400ms_netdev_setup); 474a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (net_dev == NULL) { 475a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez dev_err(dev, "no memory for network device instance\n"); 476a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto error_alloc_netdev; 477a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 478a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez SET_NETDEV_DEV(net_dev, dev); 479384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type); 480a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m = net_dev_to_i2400m(net_dev); 481a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400ms = container_of(i2400m, struct i2400ms, i2400m); 482a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->wimax_dev.net_dev = net_dev; 483a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400ms->func = func; 484a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_set_drvdata(func, i2400ms); 485a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 486a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; 4878a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi /* 4888a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi * Room required in the TX queue for SDIO message to accommodate 4898a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi * a smallest payload while allocating header space is 224 bytes, 4908a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi * which is the smallest message size(the block size 256 bytes) 4918a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi * minus the smallest message header size(32 bytes). 4928a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi */ 4938a3a1b65eeecd18357ac0cc941f43df153d4f271Prasanna S. Panchamukhi i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2; 494a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; 4950856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez i2400m->bus_setup = i2400ms_bus_setup; 496a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_dev_start = i2400ms_bus_dev_start; 497a8ee303cae6fbdaa639afa50b9d03ce6f0c7d7daInaky Perez-Gonzalez i2400m->bus_dev_stop = NULL; 4980856ccf29dfbaf957e4be80dd3eb88d97810b633Inaky Perez-Gonzalez i2400m->bus_release = i2400ms_bus_release; 499a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_tx_kick = i2400ms_bus_tx_kick; 500a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_reset = i2400ms_bus_reset; 501ecddfd5ed73c070413f07a5251c16c10e69f35a2Inaky Perez-Gonzalez /* The iwmc3200-wimax sometimes requires the driver to try 502ecddfd5ed73c070413f07a5251c16c10e69f35a2Inaky Perez-Gonzalez * hard when we paint it into a corner. */ 503c30836580b35ae5cab3de97a3df16878fe097868Dirk Brandewie i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES; 504a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; 505a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; 5061039abbc5b1bfa943b6daabbe9de1499037a90c0Inaky Perez-Gonzalez i2400m->bus_fw_names = i2400ms_bus_fw_names; 507a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m->bus_bm_mac_addr_impaired = 1; 5081c0b2dd75772cbce0aef8886b7f38313542216deDirk Brandewie i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; 509a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 51002eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez switch (func->device) { 51102eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX: 51202eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5: 51302eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez i2400ms->iwmc3200 = 1; 51402eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez break; 51502eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez default: 51602eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez i2400ms->iwmc3200 = 0; 51702eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez } 51802eb41ef2a8631022fd90e096c57562dec9e7a9aInaky Perez-Gonzalez 519a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); 520a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (result < 0) { 521a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez dev_err(dev, "cannot setup device: %d\n", result); 522a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto error_setup; 523a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 524a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 525a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result = i2400ms_debugfs_add(i2400ms); 526a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez if (result < 0) { 527a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez dev_err(dev, "cannot create SDIO debugfs: %d\n", 528a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez result); 529a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez goto error_debugfs_add; 530a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez } 531a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return 0; 532a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 533a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezerror_debugfs_add: 534a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m_release(i2400m); 535a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezerror_setup: 536a0a4c4c9e54ee4255f46eedb572ad69ee34c77b6Inaky Perez-Gonzalez sdio_set_drvdata(func, NULL); 537a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez free_netdev(net_dev); 538a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezerror_alloc_netdev: 539a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return result; 540a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 541a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 542a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 543a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 544a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezvoid i2400ms_remove(struct sdio_func *func) 545a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 546a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct device *dev = &func->dev; 547a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400ms *i2400ms = sdio_get_drvdata(func); 548a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct i2400m *i2400m = &i2400ms->i2400m; 549a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez struct net_device *net_dev = i2400m->wimax_dev.net_dev; 550a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 551a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_fnstart(3, dev, "SDIO func %p\n", func); 552a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez debugfs_remove_recursive(i2400ms->debugfs_dentry); 553fae92216da87d1c78aa51c4503acb312a47266e9Inaky Perez-Gonzalez i2400ms->debugfs_dentry = NULL; 554a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez i2400m_release(i2400m); 555a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_set_drvdata(func, NULL); 556a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez free_netdev(net_dev); 557a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez d_fnend(3, dev, "SDIO func %p\n", func); 558a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 559a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 560a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 561a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezconst struct sdio_device_id i2400ms_sdio_ids[] = { 56251def0bea92629dff02ff1de40603eb90c609c55Tomas Winkler /* Intel: i2400m WiMAX (iwmc3200) over SDIO */ 56351def0bea92629dff02ff1de40603eb90c609c55Tomas Winkler { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 56451def0bea92629dff02ff1de40603eb90c609c55Tomas Winkler SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) }, 565f8fc3295570115267ce1ce901f362d13d194aefcCindy H Kao { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 566f8fc3295570115267ce1ce901f362d13d194aefcCindy H Kao SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5) }, 56751def0bea92629dff02ff1de40603eb90c609c55Tomas Winkler { /* end: all zeroes */ }, 568a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez}; 569a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-GonzalezMODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids); 570a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 571a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 572a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 573a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstruct sdio_driver i2400m_sdio_driver = { 574a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez .name = KBUILD_MODNAME, 575a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez .probe = i2400ms_probe, 576a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez .remove = i2400ms_remove, 577a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez .id_table = i2400ms_sdio_ids, 578a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez}; 579a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 580a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 581a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 582a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezint __init i2400ms_driver_init(void) 583a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 5844c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez d_parse_params(D_LEVEL, D_LEVEL_SIZE, i2400ms_debug_params, 5854c2b1a11646bf74e2926ce8b13a21884adc1e05cInaky Perez-Gonzalez "i2400m_sdio.debug"); 586a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez return sdio_register_driver(&i2400m_sdio_driver); 587a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 588a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezmodule_init(i2400ms_driver_init); 589a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 590a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 591a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezstatic 592a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezvoid __exit i2400ms_driver_exit(void) 593a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez{ 594a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez sdio_unregister_driver(&i2400m_sdio_driver); 595a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez} 596a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalezmodule_exit(i2400ms_driver_exit); 597a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 598a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-Gonzalez 599a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-GonzalezMODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>"); 600a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-GonzalezMODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO"); 601a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-GonzalezMODULE_LICENSE("GPL"); 602a0848826bfaf0815ec9654d78c218a40f755ccd4Inaky Perez-GonzalezMODULE_FIRMWARE(I2400MS_FW_FILE_NAME); 603