forked from Minki/linux
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
This commit is contained in:
commit
3230e8cd80
@ -636,7 +636,7 @@ P: Dirk Opfer
|
||||
M: dirk@opfer-online.de
|
||||
S: Maintained
|
||||
|
||||
ARM/PALMTX,PALMT5,PALMLD SUPPORT
|
||||
ARM/PALMTX,PALMT5,PALMLD,PALMTE2 SUPPORT
|
||||
P: Marek Vasut
|
||||
M: marek.vasut@gmail.com
|
||||
W: http://hackndev.com
|
||||
@ -3057,7 +3057,7 @@ S: Supported
|
||||
|
||||
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
|
||||
P: Pierre Ossman
|
||||
M: drzeus-mmc@drzeus.cx
|
||||
M: pierre@ossman.eu
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
@ -3939,7 +3939,7 @@ S: Maintained
|
||||
|
||||
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
|
||||
P: Pierre Ossman
|
||||
M: drzeus-sdhci@drzeus.cx
|
||||
M: pierre@ossman.eu
|
||||
L: sdhci-devel@lists.ossman.eu
|
||||
S: Maintained
|
||||
|
||||
@ -4926,7 +4926,7 @@ S: Maintained
|
||||
|
||||
W83L51xD SD/MMC CARD INTERFACE DRIVER
|
||||
P: Pierre Ossman
|
||||
M: drzeus-wbsd@drzeus.cx
|
||||
M: pierre@ossman.eu
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
|
@ -1183,7 +1183,11 @@ CONFIG_RTC_INTF_DEV=y
|
||||
CONFIG_RTC_DRV_SA1100=y
|
||||
# CONFIG_RTC_DRV_PXA is not set
|
||||
# CONFIG_DMADEVICES is not set
|
||||
# CONFIG_REGULATOR is not set
|
||||
CONFIG_REGULATOR=y
|
||||
# CONFIG_REGULATOR_DEBUG is not set
|
||||
# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
|
||||
# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
|
||||
CONFIG_REGULATOR_BQ24022=y
|
||||
# CONFIG_UIO is not set
|
||||
# CONFIG_STAGING is not set
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define SZ_4K 0x00001000
|
||||
#define SZ_8K 0x00002000
|
||||
#define SZ_16K 0x00004000
|
||||
#define SZ_32K 0x00008000
|
||||
#define SZ_64K 0x00010000
|
||||
#define SZ_128K 0x00020000
|
||||
#define SZ_256K 0x00040000
|
||||
|
@ -87,7 +87,7 @@ extern void __init at91_add_device_eth(struct at91_eth_data *data);
|
||||
/* USB Host */
|
||||
struct at91_usbh_data {
|
||||
u8 ports; /* number of ports on root hub */
|
||||
u8 vbus_pin[]; /* port power-control pin */
|
||||
u8 vbus_pin[2]; /* port power-control pin */
|
||||
};
|
||||
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
|
||||
|
||||
|
@ -590,27 +590,28 @@ static void omap1_init_ext_clk(struct clk * clk)
|
||||
static int omap1_clk_enable(struct clk *clk)
|
||||
{
|
||||
int ret = 0;
|
||||
if (clk->usecount++ == 0) {
|
||||
if (likely(clk->parent)) {
|
||||
ret = omap1_clk_enable(clk->parent);
|
||||
|
||||
if (unlikely(ret != 0)) {
|
||||
clk->usecount--;
|
||||
return ret;
|
||||
}
|
||||
if (clk->usecount++ == 0) {
|
||||
if (clk->parent) {
|
||||
ret = omap1_clk_enable(clk->parent);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (clk->flags & CLOCK_NO_IDLE_PARENT)
|
||||
omap1_clk_deny_idle(clk->parent);
|
||||
}
|
||||
|
||||
ret = clk->ops->enable(clk);
|
||||
|
||||
if (unlikely(ret != 0) && clk->parent) {
|
||||
omap1_clk_disable(clk->parent);
|
||||
clk->usecount--;
|
||||
if (ret) {
|
||||
if (clk->parent)
|
||||
omap1_clk_disable(clk->parent);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
err:
|
||||
clk->usecount--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -343,6 +343,15 @@ config ARCH_PXA_PALM
|
||||
bool "PXA based Palm PDAs"
|
||||
select HAVE_PWM
|
||||
|
||||
config MACH_PALMTE2
|
||||
bool "Palm Tungsten|E2"
|
||||
default y
|
||||
depends on ARCH_PXA_PALM
|
||||
select PXA25x
|
||||
help
|
||||
Say Y here if you intend to run this kernel on a Palm Tungsten|E2
|
||||
handheld computer.
|
||||
|
||||
config MACH_PALMT5
|
||||
bool "Palm Tungsten|T5"
|
||||
default y
|
||||
|
@ -57,6 +57,7 @@ obj-$(CONFIG_MACH_E740) += e740.o
|
||||
obj-$(CONFIG_MACH_E750) += e750.o
|
||||
obj-$(CONFIG_MACH_E400) += e400.o
|
||||
obj-$(CONFIG_MACH_E800) += e800.o
|
||||
obj-$(CONFIG_MACH_PALMTE2) += palmte2.o
|
||||
obj-$(CONFIG_MACH_PALMT5) += palmt5.o
|
||||
obj-$(CONFIG_MACH_PALMTX) += palmtx.o
|
||||
obj-$(CONFIG_MACH_PALMLD) += palmld.o
|
||||
|
@ -121,7 +121,7 @@ static inline void cmx2xx_init_dm9000(void) {}
|
||||
/* UCB1400 touchscreen controller */
|
||||
#if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
|
||||
static struct platform_device cmx2xx_ts_device = {
|
||||
.name = "ucb1400_ts",
|
||||
.name = "ucb1400_core",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <net/ax88796.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/sizes.h>
|
||||
@ -32,12 +32,13 @@
|
||||
|
||||
#if defined(CONFIG_AX88796)
|
||||
#define COLIBRI_ETH_IRQ_GPIO mfp_to_gpio(GPIO26_GPIO)
|
||||
|
||||
/*
|
||||
* Asix AX88796 Ethernet
|
||||
*/
|
||||
static struct ax_plat_data colibri_asix_platdata = {
|
||||
.flags = AXFLG_MAC_FROMDEV,
|
||||
.wordlength = 2
|
||||
.flags = 0, /* defined later */
|
||||
.wordlength = 2,
|
||||
};
|
||||
|
||||
static struct resource colibri_asix_resource[] = {
|
||||
@ -49,7 +50,7 @@ static struct resource colibri_asix_resource[] = {
|
||||
[1] = {
|
||||
.start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
|
||||
.end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
|
||||
.flags = IORESOURCE_IRQ
|
||||
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
|
||||
}
|
||||
};
|
||||
|
||||
@ -70,8 +71,8 @@ static mfp_cfg_t colibri_pxa300_eth_pin_config[] __initdata = {
|
||||
|
||||
static void __init colibri_pxa300_init_eth(void)
|
||||
{
|
||||
colibri_pxa3xx_init_eth(&colibri_asix_platdata);
|
||||
pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_eth_pin_config));
|
||||
set_irq_type(gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), IRQ_TYPE_EDGE_FALLING);
|
||||
platform_device_register(&asix_device);
|
||||
}
|
||||
#else
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <net/ax88796.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/sizes.h>
|
||||
@ -38,8 +38,8 @@
|
||||
* Asix AX88796 Ethernet
|
||||
*/
|
||||
static struct ax_plat_data colibri_asix_platdata = {
|
||||
.flags = AXFLG_MAC_FROMDEV,
|
||||
.wordlength = 2
|
||||
.flags = 0, /* defined later */
|
||||
.wordlength = 2,
|
||||
};
|
||||
|
||||
static struct resource colibri_asix_resource[] = {
|
||||
@ -51,7 +51,7 @@ static struct resource colibri_asix_resource[] = {
|
||||
[1] = {
|
||||
.start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
|
||||
.end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
|
||||
.flags = IORESOURCE_IRQ
|
||||
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
|
||||
}
|
||||
};
|
||||
|
||||
@ -72,8 +72,8 @@ static mfp_cfg_t colibri_pxa320_eth_pin_config[] __initdata = {
|
||||
|
||||
static void __init colibri_pxa320_init_eth(void)
|
||||
{
|
||||
colibri_pxa3xx_init_eth(&colibri_asix_platdata);
|
||||
pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_eth_pin_config));
|
||||
set_irq_type(gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), IRQ_TYPE_EDGE_FALLING);
|
||||
platform_device_register(&asix_device);
|
||||
}
|
||||
#else
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/sizes.h>
|
||||
@ -28,6 +29,40 @@
|
||||
#include "generic.h"
|
||||
#include "devices.h"
|
||||
|
||||
#if defined(CONFIG_AX88796)
|
||||
#define ETHER_ADDR_LEN 6
|
||||
static u8 ether_mac_addr[ETHER_ADDR_LEN];
|
||||
|
||||
void __init colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data)
|
||||
{
|
||||
int i;
|
||||
u64 serial = ((u64) system_serial_high << 32) | system_serial_low;
|
||||
|
||||
/*
|
||||
* If the bootloader passed in a serial boot tag, which contains a
|
||||
* valid ethernet MAC, pass it to the interface. Toradex ships the
|
||||
* modules with their own bootloader which provides a valid MAC
|
||||
* this way.
|
||||
*/
|
||||
|
||||
for (i = 0; i < ETHER_ADDR_LEN; i++) {
|
||||
ether_mac_addr[i] = serial & 0xff;
|
||||
serial >>= 8;
|
||||
}
|
||||
|
||||
if (is_valid_ether_addr(ether_mac_addr)) {
|
||||
plat_data->flags |= AXFLG_MAC_FROMPLATFORM;
|
||||
plat_data->mac_addr = ether_mac_addr;
|
||||
printk(KERN_INFO "%s(): taking MAC from serial boot tag\n",
|
||||
__func__);
|
||||
} else {
|
||||
plat_data->flags |= AXFLG_MAC_FROMDEV;
|
||||
printk(KERN_INFO "%s(): no valid serial boot tag found, "
|
||||
"taking MAC from device\n", __func__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
|
||||
static int mmc_detect_pin;
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/leds.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
static struct gpio_keys_button csb701_buttons[] = {
|
||||
{
|
||||
.code = 0x7,
|
||||
@ -54,6 +56,9 @@ static struct platform_device *devices[] __initdata = {
|
||||
|
||||
static int __init csb701_init(void)
|
||||
{
|
||||
if (!machine_is_csb726())
|
||||
return -ENODEV;
|
||||
|
||||
return platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <mach/udc.h>
|
||||
#include <mach/irda.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/audio.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "eseries.h"
|
||||
@ -197,6 +198,7 @@ static void __init e740_init(void)
|
||||
eseries_get_tmio_gpios();
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
pxa_set_udc_info(&e7xx_udc_mach_info);
|
||||
pxa_set_ac97_info(NULL);
|
||||
e7xx_irda_init();
|
||||
pxa_set_ficp_info(&e7xx_ficp_platform_data);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <mach/udc.h>
|
||||
#include <mach/irda.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/audio.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "eseries.h"
|
||||
@ -198,6 +199,7 @@ static void __init e750_init(void)
|
||||
eseries_get_tmio_gpios();
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
pxa_set_udc_info(&e7xx_udc_mach_info);
|
||||
pxa_set_ac97_info(NULL);
|
||||
e7xx_irda_init();
|
||||
pxa_set_ficp_info(&e7xx_ficp_platform_data);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <mach/eseries-gpio.h>
|
||||
#include <mach/udc.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/audio.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "eseries.h"
|
||||
@ -199,6 +200,7 @@ static void __init e800_init(void)
|
||||
eseries_get_tmio_gpios();
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
pxa_set_udc_info(&e800_udc_mach_info);
|
||||
pxa_set_ac97_info(NULL);
|
||||
}
|
||||
|
||||
MACHINE_START(E800, "Toshiba e800")
|
||||
|
@ -25,8 +25,10 @@
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/tdo24m.h>
|
||||
#include <linux/spi/libertas_spi.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/apm-emulation.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <media/soc_camera.h>
|
||||
|
||||
@ -62,6 +64,8 @@
|
||||
#define GPIO93_CAM_RESET (93)
|
||||
#define GPIO41_ETHIRQ (41)
|
||||
#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ)
|
||||
#define GPIO115_WLAN_PWEN (115)
|
||||
#define GPIO19_WLAN_STRAP (19)
|
||||
|
||||
static int mmc_cd;
|
||||
static int nand_rb;
|
||||
@ -159,8 +163,8 @@ static unsigned long common_pin_config[] = {
|
||||
GPIO57_SSP1_TXD,
|
||||
|
||||
/* SSP2 */
|
||||
GPIO19_SSP2_SCLK,
|
||||
GPIO14_SSP2_SFRM,
|
||||
GPIO19_GPIO, /* SSP2 clock is used as GPIO for Libertas pin-strap */
|
||||
GPIO14_GPIO,
|
||||
GPIO89_SSP2_TXD,
|
||||
GPIO88_SSP2_RXD,
|
||||
|
||||
@ -648,20 +652,86 @@ static struct tdo24m_platform_data em_x270_tdo24m_pdata = {
|
||||
.model = TDO35S,
|
||||
};
|
||||
|
||||
static struct pxa2xx_spi_master em_x270_spi_2_info = {
|
||||
.num_chipselect = 1,
|
||||
.enable_dma = 1,
|
||||
};
|
||||
|
||||
static struct pxa2xx_spi_chip em_x270_libertas_chip = {
|
||||
.rx_threshold = 1,
|
||||
.tx_threshold = 1,
|
||||
.timeout = 1000,
|
||||
};
|
||||
|
||||
static unsigned long em_x270_libertas_pin_config[] = {
|
||||
/* SSP2 */
|
||||
GPIO19_SSP2_SCLK,
|
||||
GPIO14_GPIO,
|
||||
GPIO89_SSP2_TXD,
|
||||
GPIO88_SSP2_RXD,
|
||||
};
|
||||
|
||||
static int em_x270_libertas_setup(struct spi_device *spi)
|
||||
{
|
||||
int err = gpio_request(GPIO115_WLAN_PWEN, "WLAN PWEN");
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
gpio_direction_output(GPIO19_WLAN_STRAP, 1);
|
||||
mdelay(100);
|
||||
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_libertas_pin_config));
|
||||
|
||||
gpio_direction_output(GPIO115_WLAN_PWEN, 0);
|
||||
mdelay(100);
|
||||
gpio_set_value(GPIO115_WLAN_PWEN, 1);
|
||||
mdelay(100);
|
||||
|
||||
spi->bits_per_word = 16;
|
||||
spi_setup(spi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int em_x270_libertas_teardown(struct spi_device *spi)
|
||||
{
|
||||
gpio_set_value(GPIO115_WLAN_PWEN, 0);
|
||||
gpio_free(GPIO115_WLAN_PWEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct libertas_spi_platform_data em_x270_libertas_pdata = {
|
||||
.use_dummy_writes = 1,
|
||||
.gpio_cs = 14,
|
||||
.setup = em_x270_libertas_setup,
|
||||
.teardown = em_x270_libertas_teardown,
|
||||
};
|
||||
|
||||
static struct spi_board_info em_x270_spi_devices[] __initdata = {
|
||||
{
|
||||
.modalias = "tdo24m",
|
||||
.max_speed_hz = 1000000,
|
||||
.bus_num = 1,
|
||||
.chip_select = 0,
|
||||
.controller_data = &em_x270_tdo24m_chip,
|
||||
.platform_data = &em_x270_tdo24m_pdata,
|
||||
.modalias = "tdo24m",
|
||||
.max_speed_hz = 1000000,
|
||||
.bus_num = 1,
|
||||
.chip_select = 0,
|
||||
.controller_data = &em_x270_tdo24m_chip,
|
||||
.platform_data = &em_x270_tdo24m_pdata,
|
||||
},
|
||||
{
|
||||
.modalias = "libertas_spi",
|
||||
.max_speed_hz = 13000000,
|
||||
.bus_num = 2,
|
||||
.irq = IRQ_GPIO(116),
|
||||
.chip_select = 0,
|
||||
.controller_data = &em_x270_libertas_chip,
|
||||
.platform_data = &em_x270_libertas_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init em_x270_init_spi(void)
|
||||
{
|
||||
pxa2xx_set_spi_info(1, &em_x270_spi_info);
|
||||
pxa2xx_set_spi_info(2, &em_x270_spi_2_info);
|
||||
spi_register_board_info(ARRAY_AND_SIZE(em_x270_spi_devices));
|
||||
}
|
||||
#else
|
||||
|
@ -1,5 +1,8 @@
|
||||
#ifndef _COLIBRI_H_
|
||||
#define _COLIBRI_H_
|
||||
|
||||
#include <net/ax88796.h>
|
||||
|
||||
/*
|
||||
* common settings for all modules
|
||||
*/
|
||||
@ -16,6 +19,10 @@ extern void colibri_pxa3xx_init_lcd(int bl_pin);
|
||||
static inline void colibri_pxa3xx_init_lcd(int) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AX88796)
|
||||
extern void colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data);
|
||||
#endif
|
||||
|
||||
/* physical memory regions */
|
||||
#define COLIBRI_SDRAM_BASE 0xa0000000 /* SDRAM region */
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#define GPIO22_MAGICIAN_VIBRA_EN 22
|
||||
#define GPIO26_MAGICIAN_GSM_POWER 26
|
||||
#define GPIO27_MAGICIAN_USBC_PUEN 27
|
||||
#define GPIO30_MAGICIAN_nCHARGE_EN 30
|
||||
#define GPIO30_MAGICIAN_BQ24022_nCHARGE_EN 30
|
||||
#define GPIO37_MAGICIAN_KEY_HANGUP 37
|
||||
#define GPIO38_MAGICIAN_KEY_CONTACTS 38
|
||||
#define GPIO40_MAGICIAN_GSM_OUT2 40
|
||||
@ -98,7 +98,7 @@
|
||||
#define EGPIO_MAGICIAN_UNKNOWN_WAVEDEV_DLL MAGICIAN_EGPIO(2, 2)
|
||||
#define EGPIO_MAGICIAN_FLASH_VPP MAGICIAN_EGPIO(2, 3)
|
||||
#define EGPIO_MAGICIAN_BL_POWER2 MAGICIAN_EGPIO(2, 4)
|
||||
#define EGPIO_MAGICIAN_CHARGE_EN MAGICIAN_EGPIO(2, 5)
|
||||
#define EGPIO_MAGICIAN_BQ24022_ISET2 MAGICIAN_EGPIO(2, 5)
|
||||
#define EGPIO_MAGICIAN_GSM_POWER MAGICIAN_EGPIO(2, 7)
|
||||
|
||||
/* input */
|
||||
|
@ -87,6 +87,7 @@
|
||||
#define PALMLD_IDE_SIZE 0x00100000
|
||||
|
||||
#define PALMLD_PHYS_IO_START 0x40000000
|
||||
#define PALMLD_STR_BASE 0xa0200000
|
||||
|
||||
/* BATTERY */
|
||||
#define PALMLD_BAT_MAX_VOLTAGE 4000 /* 4.00V maximum voltage */
|
||||
|
@ -59,6 +59,7 @@
|
||||
/* Various addresses */
|
||||
#define PALMT5_PHYS_RAM_START 0xa0000000
|
||||
#define PALMT5_PHYS_IO_START 0x40000000
|
||||
#define PALMT5_STR_BASE 0xa0200000
|
||||
|
||||
/* TOUCHSCREEN */
|
||||
#define AC97_LINK_FRAME 21
|
||||
|
68
arch/arm/mach-pxa/include/mach/palmte2.h
Normal file
68
arch/arm/mach-pxa/include/mach/palmte2.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* GPIOs and interrupts for Palm Tungsten|E2 Handheld Computer
|
||||
*
|
||||
* Author:
|
||||
* Carlos Eduardo Medaglia Dyonisio <cadu@nerdfeliz.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PALMTE2_H_
|
||||
#define _INCLUDE_PALMTE2_H_
|
||||
|
||||
/** HERE ARE GPIOs **/
|
||||
|
||||
/* GPIOs */
|
||||
#define GPIO_NR_PALMTE2_POWER_DETECT 9
|
||||
#define GPIO_NR_PALMTE2_HOTSYNC_BUTTON_N 4
|
||||
#define GPIO_NR_PALMTE2_EARPHONE_DETECT 15
|
||||
|
||||
/* SD/MMC */
|
||||
#define GPIO_NR_PALMTE2_SD_DETECT_N 10
|
||||
#define GPIO_NR_PALMTE2_SD_POWER 55
|
||||
#define GPIO_NR_PALMTE2_SD_READONLY 51
|
||||
|
||||
/* IRDA - disable GPIO connected to SD pin of tranceiver (TFBS4710?) ? */
|
||||
#define GPIO_NR_PALMTE2_IR_DISABLE 48
|
||||
|
||||
/* USB */
|
||||
#define GPIO_NR_PALMTE2_USB_DETECT_N 35
|
||||
#define GPIO_NR_PALMTE2_USB_PULLUP 53
|
||||
|
||||
/* LCD/BACKLIGHT */
|
||||
#define GPIO_NR_PALMTE2_BL_POWER 56
|
||||
#define GPIO_NR_PALMTE2_LCD_POWER 37
|
||||
|
||||
/* KEYS */
|
||||
#define GPIO_NR_PALMTE2_KEY_NOTES 5
|
||||
#define GPIO_NR_PALMTE2_KEY_TASKS 7
|
||||
#define GPIO_NR_PALMTE2_KEY_CALENDAR 11
|
||||
#define GPIO_NR_PALMTE2_KEY_CONTACTS 13
|
||||
#define GPIO_NR_PALMTE2_KEY_CENTER 14
|
||||
#define GPIO_NR_PALMTE2_KEY_LEFT 19
|
||||
#define GPIO_NR_PALMTE2_KEY_RIGHT 20
|
||||
#define GPIO_NR_PALMTE2_KEY_DOWN 21
|
||||
#define GPIO_NR_PALMTE2_KEY_UP 22
|
||||
|
||||
/** HERE ARE INIT VALUES **/
|
||||
|
||||
/* BACKLIGHT */
|
||||
#define PALMTE2_MAX_INTENSITY 0xFE
|
||||
#define PALMTE2_DEFAULT_INTENSITY 0x7E
|
||||
#define PALMTE2_LIMIT_MASK 0x7F
|
||||
#define PALMTE2_PRESCALER 0x3F
|
||||
#define PALMTE2_PERIOD_NS 3500
|
||||
|
||||
/* BATTERY */
|
||||
#define PALMTE2_BAT_MAX_VOLTAGE 4000 /* 4.00v current voltage */
|
||||
#define PALMTE2_BAT_MIN_VOLTAGE 3550 /* 3.55v critical voltage */
|
||||
#define PALMTE2_BAT_MAX_CURRENT 0 /* unknokn */
|
||||
#define PALMTE2_BAT_MIN_CURRENT 0 /* unknown */
|
||||
#define PALMTE2_BAT_MAX_CHARGE 1 /* unknown */
|
||||
#define PALMTE2_BAT_MIN_CHARGE 1 /* unknown */
|
||||
#define PALMTE2_MAX_LIFE_MINS 360 /* on-life in minutes */
|
||||
|
||||
#endif
|
@ -78,6 +78,8 @@
|
||||
#define PALMTX_PHYS_RAM_START 0xa0000000
|
||||
#define PALMTX_PHYS_IO_START 0x40000000
|
||||
|
||||
#define PALMTX_STR_BASE 0xa0200000
|
||||
|
||||
#define PALMTX_PHYS_FLASH_START PXA_CS0_PHYS /* ChipSelect 0 */
|
||||
#define PALMTX_PHYS_NAND_START PXA_CS1_PHYS /* ChipSelect 1 */
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/pwm_backlight.h>
|
||||
#include <linux/regulator/bq24022.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/usb/gpio_vbus.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
@ -552,33 +554,7 @@ static struct platform_device gpio_vbus = {
|
||||
|
||||
static int power_supply_init(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC");
|
||||
if (ret)
|
||||
goto err_cs_ac;
|
||||
ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_USB, "CABLE_STATE_USB");
|
||||
if (ret)
|
||||
goto err_cs_usb;
|
||||
ret = gpio_request(EGPIO_MAGICIAN_CHARGE_EN, "CHARGE_EN");
|
||||
if (ret)
|
||||
goto err_chg_en;
|
||||
ret = gpio_request(GPIO30_MAGICIAN_nCHARGE_EN, "nCHARGE_EN");
|
||||
if (!ret)
|
||||
ret = gpio_direction_output(GPIO30_MAGICIAN_nCHARGE_EN, 0);
|
||||
if (ret)
|
||||
goto err_nchg_en;
|
||||
|
||||
return 0;
|
||||
|
||||
err_nchg_en:
|
||||
gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
|
||||
err_chg_en:
|
||||
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
|
||||
err_cs_usb:
|
||||
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
|
||||
err_cs_ac:
|
||||
return ret;
|
||||
return gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC");
|
||||
}
|
||||
|
||||
static int magician_is_ac_online(void)
|
||||
@ -586,22 +562,8 @@ static int magician_is_ac_online(void)
|
||||
return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
|
||||
}
|
||||
|
||||
static int magician_is_usb_online(void)
|
||||
{
|
||||
return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_USB);
|
||||
}
|
||||
|
||||
static void magician_set_charge(int flags)
|
||||
{
|
||||
gpio_set_value(GPIO30_MAGICIAN_nCHARGE_EN, !flags);
|
||||
gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
|
||||
}
|
||||
|
||||
static void power_supply_exit(struct device *dev)
|
||||
{
|
||||
gpio_free(GPIO30_MAGICIAN_nCHARGE_EN);
|
||||
gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
|
||||
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
|
||||
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
|
||||
}
|
||||
|
||||
@ -612,8 +574,6 @@ static char *magician_supplicants[] = {
|
||||
static struct pda_power_pdata power_supply_info = {
|
||||
.init = power_supply_init,
|
||||
.is_ac_online = magician_is_ac_online,
|
||||
.is_usb_online = magician_is_usb_online,
|
||||
.set_charge = magician_set_charge,
|
||||
.exit = power_supply_exit,
|
||||
.supplied_to = magician_supplicants,
|
||||
.num_supplicants = ARRAY_SIZE(magician_supplicants),
|
||||
@ -646,6 +606,43 @@ static struct platform_device power_supply = {
|
||||
.num_resources = ARRAY_SIZE(power_supply_resources),
|
||||
};
|
||||
|
||||
/*
|
||||
* Battery charger
|
||||
*/
|
||||
|
||||
static struct regulator_consumer_supply bq24022_consumers[] = {
|
||||
{
|
||||
.dev = &gpio_vbus.dev,
|
||||
.supply = "vbus_draw",
|
||||
},
|
||||
{
|
||||
.dev = &power_supply.dev,
|
||||
.supply = "ac_draw",
|
||||
},
|
||||
};
|
||||
|
||||
static struct regulator_init_data bq24022_init_data = {
|
||||
.constraints = {
|
||||
.max_uA = 500000,
|
||||
.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
|
||||
},
|
||||
.num_consumer_supplies = ARRAY_SIZE(bq24022_consumers),
|
||||
.consumer_supplies = bq24022_consumers,
|
||||
};
|
||||
|
||||
static struct bq24022_mach_info bq24022_info = {
|
||||
.gpio_nce = GPIO30_MAGICIAN_BQ24022_nCHARGE_EN,
|
||||
.gpio_iset2 = EGPIO_MAGICIAN_BQ24022_ISET2,
|
||||
.init_data = &bq24022_init_data,
|
||||
};
|
||||
|
||||
static struct platform_device bq24022 = {
|
||||
.name = "bq24022",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &bq24022_info,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* MMC/SD
|
||||
@ -756,6 +753,7 @@ static struct platform_device *devices[] __initdata = {
|
||||
&egpio,
|
||||
&backlight,
|
||||
&pasic3,
|
||||
&bq24022,
|
||||
&gpio_vbus,
|
||||
&power_supply,
|
||||
&strataflash,
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <mach/pxa27x-udc.h>
|
||||
#include <mach/i2c.h>
|
||||
#include <mach/camera.h>
|
||||
#include <mach/audio.h>
|
||||
#include <media/soc_camera.h>
|
||||
|
||||
#include <mach/mioa701.h>
|
||||
@ -763,8 +764,6 @@ MIO_PARENT_DEV(mioa701_backlight, "pwm-backlight", &pxa27x_device_pwm0.dev,
|
||||
&mioa701_backlight_data);
|
||||
MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info)
|
||||
MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL)
|
||||
MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL)
|
||||
MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL)
|
||||
MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL)
|
||||
MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL)
|
||||
MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data);
|
||||
@ -774,8 +773,6 @@ static struct platform_device *devices[] __initdata = {
|
||||
&mioa701_backlight,
|
||||
&mioa701_led,
|
||||
&pxa2xx_pcm,
|
||||
&pxa2xx_ac97,
|
||||
&mio_wm9713_codec,
|
||||
&mioa701_sound,
|
||||
&power_dev,
|
||||
&strataflash,
|
||||
@ -818,6 +815,7 @@ static void __init mioa701_machine_init(void)
|
||||
pxa_set_keypad_info(&mioa701_keypad_info);
|
||||
wm97xx_bat_set_pdata(&mioa701_battery_data);
|
||||
pxa_set_udc_info(&mioa701_udc_info);
|
||||
pxa_set_ac97_info(NULL);
|
||||
pm_power_off = mioa701_poweroff;
|
||||
arm_pm_restart = mioa701_restart;
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/wm97xx_batt.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
@ -68,10 +69,10 @@ static unsigned long palmld_pin_config[] __initdata = {
|
||||
GPIO47_FICP_TXD,
|
||||
|
||||
/* MATRIX KEYPAD */
|
||||
GPIO100_KP_MKIN_0,
|
||||
GPIO101_KP_MKIN_1,
|
||||
GPIO102_KP_MKIN_2,
|
||||
GPIO97_KP_MKIN_3,
|
||||
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO103_KP_MKOUT_0,
|
||||
GPIO104_KP_MKOUT_1,
|
||||
GPIO105_KP_MKOUT_2,
|
||||
@ -506,6 +507,33 @@ static struct pxafb_mach_info palmld_lcd_screen = {
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Power management - standby
|
||||
******************************************************************************/
|
||||
#ifdef CONFIG_PM
|
||||
static u32 *addr __initdata;
|
||||
static u32 resume[3] __initdata = {
|
||||
0xe3a00101, /* mov r0, #0x40000000 */
|
||||
0xe380060f, /* orr r0, r0, #0x00f00000 */
|
||||
0xe590f008, /* ldr pc, [r0, #0x08] */
|
||||
};
|
||||
|
||||
static int __init palmld_pm_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* this is where the bootloader jumps */
|
||||
addr = phys_to_virt(PALMLD_STR_BASE);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
addr[i] = resume[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(palmld_pm_init);
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Machine init
|
||||
******************************************************************************/
|
||||
|
@ -75,10 +75,10 @@ static unsigned long palmt5_pin_config[] __initdata = {
|
||||
GPIO95_GPIO, /* usb power */
|
||||
|
||||
/* MATRIX KEYPAD */
|
||||
GPIO100_KP_MKIN_0,
|
||||
GPIO101_KP_MKIN_1,
|
||||
GPIO102_KP_MKIN_2,
|
||||
GPIO97_KP_MKIN_3,
|
||||
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO103_KP_MKOUT_0,
|
||||
GPIO104_KP_MKOUT_1,
|
||||
GPIO105_KP_MKOUT_2,
|
||||
@ -449,6 +449,33 @@ static struct pxafb_mach_info palmt5_lcd_screen = {
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Power management - standby
|
||||
******************************************************************************/
|
||||
#ifdef CONFIG_PM
|
||||
static u32 *addr __initdata;
|
||||
static u32 resume[3] __initdata = {
|
||||
0xe3a00101, /* mov r0, #0x40000000 */
|
||||
0xe380060f, /* orr r0, r0, #0x00f00000 */
|
||||
0xe590f008, /* ldr pc, [r0, #0x08] */
|
||||
};
|
||||
|
||||
static int __init palmt5_pm_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* this is where the bootloader jumps */
|
||||
addr = phys_to_virt(PALMT5_STR_BASE);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
addr[i] = resume[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(palmt5_pm_init);
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Machine init
|
||||
******************************************************************************/
|
||||
|
466
arch/arm/mach-pxa/palmte2.c
Normal file
466
arch/arm/mach-pxa/palmte2.c
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Hardware definitions for Palm Tungsten|E2
|
||||
*
|
||||
* Author:
|
||||
* Carlos Eduardo Medaglia Dyonisio <cadu@nerdfeliz.com>
|
||||
*
|
||||
* Rewrite for mainline:
|
||||
* Marek Vasut <marek.vasut@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* (find more info at www.hackndev.com)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/pwm_backlight.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/wm97xx_batt.h>
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/audio.h>
|
||||
#include <mach/palmte2.h>
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/pxafb.h>
|
||||
#include <mach/mfp-pxa25x.h>
|
||||
#include <mach/irda.h>
|
||||
#include <mach/udc.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "devices.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Pin configuration
|
||||
******************************************************************************/
|
||||
static unsigned long palmte2_pin_config[] __initdata = {
|
||||
/* MMC */
|
||||
GPIO6_MMC_CLK,
|
||||
GPIO8_MMC_CS0,
|
||||
GPIO10_GPIO, /* SD detect */
|
||||
GPIO55_GPIO, /* SD power */
|
||||
GPIO51_GPIO, /* SD r/o switch */
|
||||
|
||||
/* AC97 */
|
||||
GPIO28_AC97_BITCLK,
|
||||
GPIO29_AC97_SDATA_IN_0,
|
||||
GPIO30_AC97_SDATA_OUT,
|
||||
GPIO31_AC97_SYNC,
|
||||
|
||||
/* PWM */
|
||||
GPIO16_PWM0_OUT,
|
||||
|
||||
/* USB */
|
||||
GPIO15_GPIO, /* usb detect */
|
||||
GPIO53_GPIO, /* usb power */
|
||||
|
||||
/* IrDA */
|
||||
GPIO48_GPIO, /* ir disable */
|
||||
GPIO46_FICP_RXD,
|
||||
GPIO47_FICP_TXD,
|
||||
|
||||
/* LCD */
|
||||
GPIO58_LCD_LDD_0,
|
||||
GPIO59_LCD_LDD_1,
|
||||
GPIO60_LCD_LDD_2,
|
||||
GPIO61_LCD_LDD_3,
|
||||
GPIO62_LCD_LDD_4,
|
||||
GPIO63_LCD_LDD_5,
|
||||
GPIO64_LCD_LDD_6,
|
||||
GPIO65_LCD_LDD_7,
|
||||
GPIO66_LCD_LDD_8,
|
||||
GPIO67_LCD_LDD_9,
|
||||
GPIO68_LCD_LDD_10,
|
||||
GPIO69_LCD_LDD_11,
|
||||
GPIO70_LCD_LDD_12,
|
||||
GPIO71_LCD_LDD_13,
|
||||
GPIO72_LCD_LDD_14,
|
||||
GPIO73_LCD_LDD_15,
|
||||
GPIO74_LCD_FCLK,
|
||||
GPIO75_LCD_LCLK,
|
||||
GPIO76_LCD_PCLK,
|
||||
GPIO77_LCD_BIAS,
|
||||
|
||||
/* GPIO KEYS */
|
||||
GPIO5_GPIO, /* notes */
|
||||
GPIO7_GPIO, /* tasks */
|
||||
GPIO11_GPIO, /* calendar */
|
||||
GPIO13_GPIO, /* contacts */
|
||||
GPIO14_GPIO, /* center */
|
||||
GPIO19_GPIO, /* left */
|
||||
GPIO20_GPIO, /* right */
|
||||
GPIO21_GPIO, /* down */
|
||||
GPIO22_GPIO, /* up */
|
||||
|
||||
/* MISC */
|
||||
GPIO1_RST, /* reset */
|
||||
GPIO4_GPIO, /* Hotsync button */
|
||||
GPIO9_GPIO, /* power detect */
|
||||
GPIO37_GPIO, /* LCD power */
|
||||
GPIO56_GPIO, /* Backlight power */
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* SD/MMC card controller
|
||||
******************************************************************************/
|
||||
static int palmte2_mci_init(struct device *dev,
|
||||
irq_handler_t palmte2_detect_int, void *data)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
/* Setup an interrupt for detecting card insert/remove events */
|
||||
err = gpio_request(GPIO_NR_PALMTE2_SD_DETECT_N, "SD IRQ");
|
||||
if (err)
|
||||
goto err;
|
||||
err = gpio_direction_input(GPIO_NR_PALMTE2_SD_DETECT_N);
|
||||
if (err)
|
||||
goto err2;
|
||||
err = request_irq(gpio_to_irq(GPIO_NR_PALMTE2_SD_DETECT_N),
|
||||
palmte2_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
|
||||
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
|
||||
"SD/MMC card detect", data);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
|
||||
__func__);
|
||||
goto err2;
|
||||
}
|
||||
|
||||
err = gpio_request(GPIO_NR_PALMTE2_SD_POWER, "SD_POWER");
|
||||
if (err)
|
||||
goto err3;
|
||||
err = gpio_direction_output(GPIO_NR_PALMTE2_SD_POWER, 0);
|
||||
if (err)
|
||||
goto err4;
|
||||
|
||||
err = gpio_request(GPIO_NR_PALMTE2_SD_READONLY, "SD_READONLY");
|
||||
if (err)
|
||||
goto err4;
|
||||
err = gpio_direction_input(GPIO_NR_PALMTE2_SD_READONLY);
|
||||
if (err)
|
||||
goto err5;
|
||||
|
||||
printk(KERN_DEBUG "%s: irq registered\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
err5:
|
||||
gpio_free(GPIO_NR_PALMTE2_SD_READONLY);
|
||||
err4:
|
||||
gpio_free(GPIO_NR_PALMTE2_SD_POWER);
|
||||
err3:
|
||||
free_irq(gpio_to_irq(GPIO_NR_PALMTE2_SD_DETECT_N), data);
|
||||
err2:
|
||||
gpio_free(GPIO_NR_PALMTE2_SD_DETECT_N);
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void palmte2_mci_exit(struct device *dev, void *data)
|
||||
{
|
||||
gpio_free(GPIO_NR_PALMTE2_SD_READONLY);
|
||||
gpio_free(GPIO_NR_PALMTE2_SD_POWER);
|
||||
free_irq(gpio_to_irq(GPIO_NR_PALMTE2_SD_DETECT_N), data);
|
||||
gpio_free(GPIO_NR_PALMTE2_SD_DETECT_N);
|
||||
}
|
||||
|
||||
static void palmte2_mci_power(struct device *dev, unsigned int vdd)
|
||||
{
|
||||
struct pxamci_platform_data *p_d = dev->platform_data;
|
||||
gpio_set_value(GPIO_NR_PALMTE2_SD_POWER, p_d->ocr_mask & (1 << vdd));
|
||||
}
|
||||
|
||||
static int palmte2_mci_get_ro(struct device *dev)
|
||||
{
|
||||
return gpio_get_value(GPIO_NR_PALMTE2_SD_READONLY);
|
||||
}
|
||||
|
||||
static struct pxamci_platform_data palmte2_mci_platform_data = {
|
||||
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.setpower = palmte2_mci_power,
|
||||
.get_ro = palmte2_mci_get_ro,
|
||||
.init = palmte2_mci_init,
|
||||
.exit = palmte2_mci_exit,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* GPIO keys
|
||||
******************************************************************************/
|
||||
static struct gpio_keys_button palmte2_pxa_buttons[] = {
|
||||
{KEY_F1, GPIO_NR_PALMTE2_KEY_CONTACTS, 1, "Contacts" },
|
||||
{KEY_F2, GPIO_NR_PALMTE2_KEY_CALENDAR, 1, "Calendar" },
|
||||
{KEY_F3, GPIO_NR_PALMTE2_KEY_TASKS, 1, "Tasks" },
|
||||
{KEY_F4, GPIO_NR_PALMTE2_KEY_NOTES, 1, "Notes" },
|
||||
{KEY_ENTER, GPIO_NR_PALMTE2_KEY_CENTER, 1, "Center" },
|
||||
{KEY_LEFT, GPIO_NR_PALMTE2_KEY_LEFT, 1, "Left" },
|
||||
{KEY_RIGHT, GPIO_NR_PALMTE2_KEY_RIGHT, 1, "Right" },
|
||||
{KEY_DOWN, GPIO_NR_PALMTE2_KEY_DOWN, 1, "Down" },
|
||||
{KEY_UP, GPIO_NR_PALMTE2_KEY_UP, 1, "Up" },
|
||||
};
|
||||
|
||||
static struct gpio_keys_platform_data palmte2_pxa_keys_data = {
|
||||
.buttons = palmte2_pxa_buttons,
|
||||
.nbuttons = ARRAY_SIZE(palmte2_pxa_buttons),
|
||||
};
|
||||
|
||||
static struct platform_device palmte2_pxa_keys = {
|
||||
.name = "gpio-keys",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &palmte2_pxa_keys_data,
|
||||
},
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Backlight
|
||||
******************************************************************************/
|
||||
static int palmte2_backlight_init(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(GPIO_NR_PALMTE2_BL_POWER, "BL POWER");
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = gpio_direction_output(GPIO_NR_PALMTE2_BL_POWER, 0);
|
||||
if (ret)
|
||||
goto err2;
|
||||
ret = gpio_request(GPIO_NR_PALMTE2_LCD_POWER, "LCD POWER");
|
||||
if (ret)
|
||||
goto err2;
|
||||
ret = gpio_direction_output(GPIO_NR_PALMTE2_LCD_POWER, 0);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
||||
return 0;
|
||||
err3:
|
||||
gpio_free(GPIO_NR_PALMTE2_LCD_POWER);
|
||||
err2:
|
||||
gpio_free(GPIO_NR_PALMTE2_BL_POWER);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int palmte2_backlight_notify(int brightness)
|
||||
{
|
||||
gpio_set_value(GPIO_NR_PALMTE2_BL_POWER, brightness);
|
||||
gpio_set_value(GPIO_NR_PALMTE2_LCD_POWER, brightness);
|
||||
return brightness;
|
||||
}
|
||||
|
||||
static void palmte2_backlight_exit(struct device *dev)
|
||||
{
|
||||
gpio_free(GPIO_NR_PALMTE2_BL_POWER);
|
||||
gpio_free(GPIO_NR_PALMTE2_LCD_POWER);
|
||||
}
|
||||
|
||||
static struct platform_pwm_backlight_data palmte2_backlight_data = {
|
||||
.pwm_id = 0,
|
||||
.max_brightness = PALMTE2_MAX_INTENSITY,
|
||||
.dft_brightness = PALMTE2_MAX_INTENSITY,
|
||||
.pwm_period_ns = PALMTE2_PERIOD_NS,
|
||||
.init = palmte2_backlight_init,
|
||||
.notify = palmte2_backlight_notify,
|
||||
.exit = palmte2_backlight_exit,
|
||||
};
|
||||
|
||||
static struct platform_device palmte2_backlight = {
|
||||
.name = "pwm-backlight",
|
||||
.dev = {
|
||||
.parent = &pxa25x_device_pwm0.dev,
|
||||
.platform_data = &palmte2_backlight_data,
|
||||
},
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* IrDA
|
||||
******************************************************************************/
|
||||
static int palmte2_irda_startup(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
err = gpio_request(GPIO_NR_PALMTE2_IR_DISABLE, "IR DISABLE");
|
||||
if (err)
|
||||
goto err;
|
||||
err = gpio_direction_output(GPIO_NR_PALMTE2_IR_DISABLE, 1);
|
||||
if (err)
|
||||
gpio_free(GPIO_NR_PALMTE2_IR_DISABLE);
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void palmte2_irda_shutdown(struct device *dev)
|
||||
{
|
||||
gpio_free(GPIO_NR_PALMTE2_IR_DISABLE);
|
||||
}
|
||||
|
||||
static void palmte2_irda_transceiver_mode(struct device *dev, int mode)
|
||||
{
|
||||
gpio_set_value(GPIO_NR_PALMTE2_IR_DISABLE, mode & IR_OFF);
|
||||
pxa2xx_transceiver_mode(dev, mode);
|
||||
}
|
||||
|
||||
static struct pxaficp_platform_data palmte2_ficp_platform_data = {
|
||||
.startup = palmte2_irda_startup,
|
||||
.shutdown = palmte2_irda_shutdown,
|
||||
.transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF,
|
||||
.transceiver_mode = palmte2_irda_transceiver_mode,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* UDC
|
||||
******************************************************************************/
|
||||
static struct pxa2xx_udc_mach_info palmte2_udc_info __initdata = {
|
||||
.gpio_vbus = GPIO_NR_PALMTE2_USB_DETECT_N,
|
||||
.gpio_vbus_inverted = 1,
|
||||
.gpio_pullup = GPIO_NR_PALMTE2_USB_PULLUP,
|
||||
.gpio_pullup_inverted = 0,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Power supply
|
||||
******************************************************************************/
|
||||
static int power_supply_init(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request(GPIO_NR_PALMTE2_POWER_DETECT, "CABLE_STATE_AC");
|
||||
if (ret)
|
||||
goto err1;
|
||||
ret = gpio_direction_input(GPIO_NR_PALMTE2_POWER_DETECT);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
gpio_free(GPIO_NR_PALMTE2_POWER_DETECT);
|
||||
err1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int palmte2_is_ac_online(void)
|
||||
{
|
||||
return gpio_get_value(GPIO_NR_PALMTE2_POWER_DETECT);
|
||||
}
|
||||
|
||||
static void power_supply_exit(struct device *dev)
|
||||
{
|
||||
gpio_free(GPIO_NR_PALMTE2_POWER_DETECT);
|
||||
}
|
||||
|
||||
static char *palmte2_supplicants[] = {
|
||||
"main-battery",
|
||||
};
|
||||
|
||||
static struct pda_power_pdata power_supply_info = {
|
||||
.init = power_supply_init,
|
||||
.is_ac_online = palmte2_is_ac_online,
|
||||
.exit = power_supply_exit,
|
||||
.supplied_to = palmte2_supplicants,
|
||||
.num_supplicants = ARRAY_SIZE(palmte2_supplicants),
|
||||
};
|
||||
|
||||
static struct platform_device power_supply = {
|
||||
.name = "pda-power",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &power_supply_info,
|
||||
},
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* WM97xx battery
|
||||
******************************************************************************/
|
||||
static struct wm97xx_batt_info wm97xx_batt_pdata = {
|
||||
.batt_aux = WM97XX_AUX_ID3,
|
||||
.temp_aux = WM97XX_AUX_ID2,
|
||||
.charge_gpio = -1,
|
||||
.max_voltage = PALMTE2_BAT_MAX_VOLTAGE,
|
||||
.min_voltage = PALMTE2_BAT_MIN_VOLTAGE,
|
||||
.batt_mult = 1000,
|
||||
.batt_div = 414,
|
||||
.temp_mult = 1,
|
||||
.temp_div = 1,
|
||||
.batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO,
|
||||
.batt_name = "main-batt",
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Framebuffer
|
||||
******************************************************************************/
|
||||
static struct pxafb_mode_info palmte2_lcd_modes[] = {
|
||||
{
|
||||
.pixclock = 77757,
|
||||
.xres = 320,
|
||||
.yres = 320,
|
||||
.bpp = 16,
|
||||
|
||||
.left_margin = 28,
|
||||
.right_margin = 7,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
|
||||
.hsync_len = 4,
|
||||
.vsync_len = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct pxafb_mach_info palmte2_lcd_screen = {
|
||||
.modes = palmte2_lcd_modes,
|
||||
.num_modes = ARRAY_SIZE(palmte2_lcd_modes),
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Machine init
|
||||
******************************************************************************/
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
|
||||
&palmte2_pxa_keys,
|
||||
#endif
|
||||
&palmte2_backlight,
|
||||
&power_supply,
|
||||
};
|
||||
|
||||
/* setup udc GPIOs initial state */
|
||||
static void __init palmte2_udc_init(void)
|
||||
{
|
||||
if (!gpio_request(GPIO_NR_PALMTE2_USB_PULLUP, "UDC Vbus")) {
|
||||
gpio_direction_output(GPIO_NR_PALMTE2_USB_PULLUP, 1);
|
||||
gpio_free(GPIO_NR_PALMTE2_USB_PULLUP);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init palmte2_init(void)
|
||||
{
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(palmte2_pin_config));
|
||||
|
||||
set_pxa_fb_info(&palmte2_lcd_screen);
|
||||
pxa_set_mci_info(&palmte2_mci_platform_data);
|
||||
palmte2_udc_init();
|
||||
pxa_set_udc_info(&palmte2_udc_info);
|
||||
pxa_set_ac97_info(NULL);
|
||||
pxa_set_ficp_info(&palmte2_ficp_platform_data);
|
||||
wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
|
||||
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
MACHINE_START(PALMTE2, "Palm Tungsten|E2")
|
||||
.phys_io = 0x40000000,
|
||||
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
||||
.boot_params = 0xa0000100,
|
||||
.map_io = pxa_map_io,
|
||||
.init_irq = pxa25x_init_irq,
|
||||
.timer = &pxa_timer,
|
||||
.init_machine = palmte2_init
|
||||
MACHINE_END
|
@ -93,10 +93,10 @@ static unsigned long palmtx_pin_config[] __initdata = {
|
||||
GPIO116_GPIO, /* wifi ready */
|
||||
|
||||
/* MATRIX KEYPAD */
|
||||
GPIO100_KP_MKIN_0,
|
||||
GPIO101_KP_MKIN_1,
|
||||
GPIO102_KP_MKIN_2,
|
||||
GPIO97_KP_MKIN_3,
|
||||
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
|
||||
GPIO103_KP_MKOUT_0,
|
||||
GPIO104_KP_MKOUT_1,
|
||||
GPIO105_KP_MKOUT_2,
|
||||
@ -458,6 +458,33 @@ static struct pxafb_mach_info palmtx_lcd_screen = {
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Power management - standby
|
||||
******************************************************************************/
|
||||
#ifdef CONFIG_PM
|
||||
static u32 *addr __initdata;
|
||||
static u32 resume[3] __initdata = {
|
||||
0xe3a00101, /* mov r0, #0x40000000 */
|
||||
0xe380060f, /* orr r0, r0, #0x00f00000 */
|
||||
0xe590f008, /* ldr pc, [r0, #0x08] */
|
||||
};
|
||||
|
||||
static int __init palmtx_pm_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* this is where the bootloader jumps */
|
||||
addr = phys_to_virt(PALMTX_STR_BASE);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
addr[i] = resume[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(palmtx_pm_init);
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Machine init
|
||||
******************************************************************************/
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <mach/udc.h>
|
||||
#include <mach/tosa_bt.h>
|
||||
#include <mach/pxa2xx_spi.h>
|
||||
#include <mach/audio.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <mach/tosa.h>
|
||||
@ -914,6 +915,7 @@ static void __init tosa_init(void)
|
||||
pxa_set_udc_info(&udc_info);
|
||||
pxa_set_ficp_info(&tosa_ficp_platform_data);
|
||||
pxa_set_i2c_info(NULL);
|
||||
pxa_set_ac97_info(NULL);
|
||||
platform_scoop_config = &tosa_pcmcia_config;
|
||||
|
||||
pxa2xx_set_spi_info(2, &pxa_ssp_master_info);
|
||||
|
@ -828,6 +828,17 @@ void __init reserve_node_zero(pg_data_t *pgdat)
|
||||
BOOTMEM_DEFAULT);
|
||||
}
|
||||
|
||||
if (machine_is_palmld() || machine_is_palmtx()) {
|
||||
reserve_bootmem_node(pgdat, 0xa0000000, 0x1000,
|
||||
BOOTMEM_EXCLUSIVE);
|
||||
reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
|
||||
BOOTMEM_EXCLUSIVE);
|
||||
}
|
||||
|
||||
if (machine_is_palmt5())
|
||||
reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
|
||||
BOOTMEM_EXCLUSIVE);
|
||||
|
||||
#ifdef CONFIG_SA1111
|
||||
/*
|
||||
* Because of the SA1111 DMA bug, we want to preserve our
|
||||
|
@ -308,11 +308,13 @@
|
||||
#define __NR_dup3 1316
|
||||
#define __NR_pipe2 1317
|
||||
#define __NR_inotify_init1 1318
|
||||
#define __NR_preadv 1319
|
||||
#define __NR_pwritev 1320
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
||||
#define NR_syscalls 295 /* length of syscall table */
|
||||
#define NR_syscalls 297 /* length of syscall table */
|
||||
|
||||
/*
|
||||
* The following defines stop scripts/checksyscalls.sh from complaining about
|
||||
|
@ -1803,6 +1803,8 @@ sys_call_table:
|
||||
data8 sys_dup3
|
||||
data8 sys_pipe2
|
||||
data8 sys_inotify_init1
|
||||
data8 sys_preadv
|
||||
data8 sys_pwritev // 1320
|
||||
|
||||
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
@ -392,8 +392,10 @@
|
||||
#define __NR_pipe2 321
|
||||
#define __NR_inotify_init1 322
|
||||
#define __NR_accept4 323
|
||||
#define __NR_preadv 324
|
||||
#define __NR_pwritev 325
|
||||
|
||||
#define NR_SYSCALLS 324
|
||||
#define NR_SYSCALLS 326
|
||||
|
||||
#ifdef __32bit_syscall_numbers__
|
||||
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
|
||||
|
@ -99,8 +99,7 @@ static inline u64 of_read_addr(const u32 *cell, int size)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __init get_cells(struct device_node *dp,
|
||||
int *addrc, int *sizec)
|
||||
static void get_cells(struct device_node *dp, int *addrc, int *sizec)
|
||||
{
|
||||
if (addrc)
|
||||
*addrc = of_n_addr_cells(dp);
|
||||
|
@ -409,8 +409,8 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
|
||||
upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB);
|
||||
}
|
||||
|
||||
static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op, u32 portid)
|
||||
static int __devinit pci_fire_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op, u32 portid)
|
||||
{
|
||||
const struct linux_prom64_registers *regs;
|
||||
struct device_node *dp = op->node;
|
||||
|
@ -365,8 +365,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm)
|
||||
pci_config_write8(addr, 64);
|
||||
}
|
||||
|
||||
static void __init psycho_scan_bus(struct pci_pbm_info *pbm,
|
||||
struct device *parent)
|
||||
static void __devinit psycho_scan_bus(struct pci_pbm_info *pbm,
|
||||
struct device *parent)
|
||||
{
|
||||
pbm_config_busmastering(pbm);
|
||||
pbm->is_66mhz_capable = 0;
|
||||
@ -482,8 +482,8 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm,
|
||||
#define PSYCHO_MEMSPACE_B 0x180000000UL
|
||||
#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL
|
||||
|
||||
static void __init psycho_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op, int is_pbm_a)
|
||||
static void __devinit psycho_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op, int is_pbm_a)
|
||||
{
|
||||
psycho_pbm_init_common(pbm, op, "PSYCHO", PBM_CHIP_TYPE_PSYCHO);
|
||||
psycho_pbm_strbuf_init(pbm, is_pbm_a);
|
||||
|
@ -402,8 +402,8 @@ static void apb_init(struct pci_bus *sabre_bus)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init sabre_scan_bus(struct pci_pbm_info *pbm,
|
||||
struct device *parent)
|
||||
static void __devinit sabre_scan_bus(struct pci_pbm_info *pbm,
|
||||
struct device *parent)
|
||||
{
|
||||
static int once;
|
||||
|
||||
@ -442,8 +442,8 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm,
|
||||
sabre_register_error_handlers(pbm);
|
||||
}
|
||||
|
||||
static void __init sabre_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op)
|
||||
static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op)
|
||||
{
|
||||
psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE);
|
||||
pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR;
|
||||
|
@ -545,8 +545,8 @@ static const struct dma_ops sun4v_dma_ops = {
|
||||
.sync_sg_for_cpu = dma_4v_sync_sg_for_cpu,
|
||||
};
|
||||
|
||||
static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm,
|
||||
struct device *parent)
|
||||
static void __devinit pci_sun4v_scan_bus(struct pci_pbm_info *pbm,
|
||||
struct device *parent)
|
||||
{
|
||||
struct property *prop;
|
||||
struct device_node *dp;
|
||||
@ -559,8 +559,8 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm,
|
||||
/* XXX register error interrupt handlers XXX */
|
||||
}
|
||||
|
||||
static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
|
||||
struct iommu *iommu)
|
||||
static unsigned long __devinit probe_existing_entries(struct pci_pbm_info *pbm,
|
||||
struct iommu *iommu)
|
||||
{
|
||||
struct iommu_arena *arena = &iommu->arena;
|
||||
unsigned long i, cnt = 0;
|
||||
@ -587,7 +587,7 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
|
||||
static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
|
||||
{
|
||||
static const u32 vdma_default[] = { 0x80000000, 0x80000000 };
|
||||
struct iommu *iommu = pbm->iommu;
|
||||
@ -889,8 +889,8 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
|
||||
}
|
||||
#endif /* !(CONFIG_PCI_MSI) */
|
||||
|
||||
static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op, u32 devhandle)
|
||||
static int __devinit pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
|
||||
struct of_device *op, u32 devhandle)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
int err;
|
||||
|
@ -23,7 +23,7 @@ static irqreturn_t power_handler(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
|
||||
static int __devinit has_button_interrupt(unsigned int irq, struct device_node *dp)
|
||||
{
|
||||
if (irq == 0xffffffff)
|
||||
return 0;
|
||||
|
@ -81,4 +81,4 @@ sys_call_table:
|
||||
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
|
||||
/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
|
||||
/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
|
||||
/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
|
||||
/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv, sys_pwritev
|
||||
|
@ -82,7 +82,7 @@ sys_call_table32:
|
||||
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
|
||||
/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
|
||||
.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
|
||||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
|
||||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv, compat_sys_pwritev
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
@ -156,4 +156,4 @@ sys_call_table:
|
||||
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
|
||||
/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
|
||||
.word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
|
||||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4
|
||||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv, sys_pwritev
|
||||
|
@ -70,8 +70,8 @@ extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
|
||||
|
||||
#define MAX_BANKS 32
|
||||
|
||||
static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
|
||||
static int pavail_ents __initdata;
|
||||
static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata;
|
||||
static int pavail_ents __devinitdata;
|
||||
|
||||
static int cmp_p64(const void *a, const void *b)
|
||||
{
|
||||
@ -968,7 +968,7 @@ int of_node_to_nid(struct device_node *dp)
|
||||
return nid;
|
||||
}
|
||||
|
||||
static void add_node_ranges(void)
|
||||
static void __init add_node_ranges(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1841,7 +1841,7 @@ void __init paging_init(void)
|
||||
printk("Booting Linux...\n");
|
||||
}
|
||||
|
||||
int __init page_in_phys_avail(unsigned long paddr)
|
||||
int __devinit page_in_phys_avail(unsigned long paddr)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -154,6 +154,7 @@
|
||||
* CPUID levels like 0x6, 0xA etc
|
||||
*/
|
||||
#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */
|
||||
#define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */
|
||||
|
||||
/* Virtualization flags: Linux defined */
|
||||
#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */
|
||||
|
@ -431,6 +431,12 @@ static void __cpuinit setup_APIC_timer(void)
|
||||
{
|
||||
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
|
||||
|
||||
if (cpu_has(¤t_cpu_data, X86_FEATURE_ARAT)) {
|
||||
lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP;
|
||||
/* Make LAPIC timer preferrable over percpu HPET */
|
||||
lapic_clockevent.rating = 150;
|
||||
}
|
||||
|
||||
memcpy(levt, &lapic_clockevent, sizeof(*levt));
|
||||
levt->cpumask = cpumask_of(smp_processor_id());
|
||||
|
||||
|
@ -31,6 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
|
||||
|
||||
static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
|
||||
{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
|
||||
{ X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -68,6 +68,7 @@ struct acpi_cpufreq_data {
|
||||
unsigned int max_freq;
|
||||
unsigned int resume;
|
||||
unsigned int cpu_feature;
|
||||
u64 saved_aperf, saved_mperf;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data);
|
||||
@ -241,26 +242,23 @@ static u32 get_cur_val(const struct cpumask *mask)
|
||||
return cmd.val;
|
||||
}
|
||||
|
||||
struct perf_cur {
|
||||
struct perf_pair {
|
||||
union {
|
||||
struct {
|
||||
u32 lo;
|
||||
u32 hi;
|
||||
} split;
|
||||
u64 whole;
|
||||
} aperf_cur, mperf_cur;
|
||||
} aperf, mperf;
|
||||
};
|
||||
|
||||
|
||||
static long read_measured_perf_ctrs(void *_cur)
|
||||
{
|
||||
struct perf_cur *cur = _cur;
|
||||
struct perf_pair *cur = _cur;
|
||||
|
||||
rdmsr(MSR_IA32_APERF, cur->aperf_cur.split.lo, cur->aperf_cur.split.hi);
|
||||
rdmsr(MSR_IA32_MPERF, cur->mperf_cur.split.lo, cur->mperf_cur.split.hi);
|
||||
|
||||
wrmsr(MSR_IA32_APERF, 0, 0);
|
||||
wrmsr(MSR_IA32_MPERF, 0, 0);
|
||||
rdmsr(MSR_IA32_APERF, cur->aperf.split.lo, cur->aperf.split.hi);
|
||||
rdmsr(MSR_IA32_MPERF, cur->mperf.split.lo, cur->mperf.split.hi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -281,52 +279,57 @@ static long read_measured_perf_ctrs(void *_cur)
|
||||
static unsigned int get_measured_perf(struct cpufreq_policy *policy,
|
||||
unsigned int cpu)
|
||||
{
|
||||
struct perf_cur cur;
|
||||
struct perf_pair readin, cur;
|
||||
unsigned int perf_percent;
|
||||
unsigned int retval;
|
||||
|
||||
if (!work_on_cpu(cpu, read_measured_perf_ctrs, &cur))
|
||||
if (!work_on_cpu(cpu, read_measured_perf_ctrs, &readin))
|
||||
return 0;
|
||||
|
||||
cur.aperf.whole = readin.aperf.whole -
|
||||
per_cpu(drv_data, cpu)->saved_aperf;
|
||||
cur.mperf.whole = readin.mperf.whole -
|
||||
per_cpu(drv_data, cpu)->saved_mperf;
|
||||
per_cpu(drv_data, cpu)->saved_aperf = readin.aperf.whole;
|
||||
per_cpu(drv_data, cpu)->saved_mperf = readin.mperf.whole;
|
||||
|
||||
#ifdef __i386__
|
||||
/*
|
||||
* We dont want to do 64 bit divide with 32 bit kernel
|
||||
* Get an approximate value. Return failure in case we cannot get
|
||||
* an approximate value.
|
||||
*/
|
||||
if (unlikely(cur.aperf_cur.split.hi || cur.mperf_cur.split.hi)) {
|
||||
if (unlikely(cur.aperf.split.hi || cur.mperf.split.hi)) {
|
||||
int shift_count;
|
||||
u32 h;
|
||||
|
||||
h = max_t(u32, cur.aperf_cur.split.hi, cur.mperf_cur.split.hi);
|
||||
h = max_t(u32, cur.aperf.split.hi, cur.mperf.split.hi);
|
||||
shift_count = fls(h);
|
||||
|
||||
cur.aperf_cur.whole >>= shift_count;
|
||||
cur.mperf_cur.whole >>= shift_count;
|
||||
cur.aperf.whole >>= shift_count;
|
||||
cur.mperf.whole >>= shift_count;
|
||||
}
|
||||
|
||||
if (((unsigned long)(-1) / 100) < cur.aperf_cur.split.lo) {
|
||||
if (((unsigned long)(-1) / 100) < cur.aperf.split.lo) {
|
||||
int shift_count = 7;
|
||||
cur.aperf_cur.split.lo >>= shift_count;
|
||||
cur.mperf_cur.split.lo >>= shift_count;
|
||||
cur.aperf.split.lo >>= shift_count;
|
||||
cur.mperf.split.lo >>= shift_count;
|
||||
}
|
||||
|
||||
if (cur.aperf_cur.split.lo && cur.mperf_cur.split.lo)
|
||||
perf_percent = (cur.aperf_cur.split.lo * 100) /
|
||||
cur.mperf_cur.split.lo;
|
||||
if (cur.aperf.split.lo && cur.mperf.split.lo)
|
||||
perf_percent = (cur.aperf.split.lo * 100) / cur.mperf.split.lo;
|
||||
else
|
||||
perf_percent = 0;
|
||||
|
||||
#else
|
||||
if (unlikely(((unsigned long)(-1) / 100) < cur.aperf_cur.whole)) {
|
||||
if (unlikely(((unsigned long)(-1) / 100) < cur.aperf.whole)) {
|
||||
int shift_count = 7;
|
||||
cur.aperf_cur.whole >>= shift_count;
|
||||
cur.mperf_cur.whole >>= shift_count;
|
||||
cur.aperf.whole >>= shift_count;
|
||||
cur.mperf.whole >>= shift_count;
|
||||
}
|
||||
|
||||
if (cur.aperf_cur.whole && cur.mperf_cur.whole)
|
||||
perf_percent = (cur.aperf_cur.whole * 100) /
|
||||
cur.mperf_cur.whole;
|
||||
if (cur.aperf.whole && cur.mperf.whole)
|
||||
perf_percent = (cur.aperf.whole * 100) / cur.mperf.whole;
|
||||
else
|
||||
perf_percent = 0;
|
||||
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <linux/timex.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <acpi/processor.h>
|
||||
|
@ -90,7 +90,6 @@ static const struct acpi_port_info acpi_protected_ports[] = {
|
||||
{"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
|
||||
{"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
|
||||
{"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
|
||||
{"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
|
||||
{"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
|
||||
{"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
|
||||
{"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
|
||||
|
@ -903,7 +903,7 @@ static struct acpi_driver acpi_battery_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
||||
static void acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
||||
{
|
||||
if (acpi_disabled)
|
||||
return;
|
||||
|
@ -343,9 +343,6 @@ acpi_system_write_alarm(struct file *file,
|
||||
}
|
||||
#endif /* HAVE_ACPI_LEGACY_ALARM */
|
||||
|
||||
extern struct list_head acpi_wakeup_device_list;
|
||||
extern spinlock_t acpi_device_lock;
|
||||
|
||||
static int
|
||||
acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
@ -353,7 +350,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
||||
|
||||
seq_printf(seq, "Device\tS-state\t Status Sysfs node\n");
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
mutex_lock(&acpi_device_lock);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev =
|
||||
container_of(node, struct acpi_device, wakeup_list);
|
||||
@ -361,7 +358,6 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
||||
|
||||
if (!dev->wakeup.flags.valid)
|
||||
continue;
|
||||
spin_unlock(&acpi_device_lock);
|
||||
|
||||
ldev = acpi_get_physical_device(dev->handle);
|
||||
seq_printf(seq, "%s\t S%d\t%c%-8s ",
|
||||
@ -376,9 +372,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
||||
seq_printf(seq, "\n");
|
||||
put_device(ldev);
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -409,7 +404,7 @@ acpi_system_write_wakeup_device(struct file *file,
|
||||
strbuf[len] = '\0';
|
||||
sscanf(strbuf, "%s", str);
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
mutex_lock(&acpi_device_lock);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev =
|
||||
container_of(node, struct acpi_device, wakeup_list);
|
||||
@ -446,7 +441,7 @@ acpi_system_write_wakeup_device(struct file *file,
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -145,6 +145,9 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr,
|
||||
struct acpi_processor_power *pwr = &pr->power;
|
||||
u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2;
|
||||
|
||||
if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check, if one of the previous states already marked the lapic
|
||||
* unstable
|
||||
|
@ -24,7 +24,7 @@ extern struct acpi_device *acpi_root;
|
||||
|
||||
static LIST_HEAD(acpi_device_list);
|
||||
static LIST_HEAD(acpi_bus_id_list);
|
||||
DEFINE_SPINLOCK(acpi_device_lock);
|
||||
DEFINE_MUTEX(acpi_device_lock);
|
||||
LIST_HEAD(acpi_wakeup_device_list);
|
||||
|
||||
struct acpi_device_bus_id{
|
||||
@ -491,7 +491,6 @@ static int acpi_device_register(struct acpi_device *device,
|
||||
*/
|
||||
INIT_LIST_HEAD(&device->children);
|
||||
INIT_LIST_HEAD(&device->node);
|
||||
INIT_LIST_HEAD(&device->g_list);
|
||||
INIT_LIST_HEAD(&device->wakeup_list);
|
||||
|
||||
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
|
||||
@ -500,7 +499,7 @@ static int acpi_device_register(struct acpi_device *device,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
mutex_lock(&acpi_device_lock);
|
||||
/*
|
||||
* Find suitable bus_id and instance number in acpi_bus_id_list
|
||||
* If failed, create one and link it into acpi_bus_id_list
|
||||
@ -521,14 +520,12 @@ static int acpi_device_register(struct acpi_device *device,
|
||||
}
|
||||
dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
|
||||
|
||||
if (device->parent) {
|
||||
if (device->parent)
|
||||
list_add_tail(&device->node, &device->parent->children);
|
||||
list_add_tail(&device->g_list, &device->parent->g_list);
|
||||
} else
|
||||
list_add_tail(&device->g_list, &acpi_device_list);
|
||||
|
||||
if (device->wakeup.flags.valid)
|
||||
list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
|
||||
spin_unlock(&acpi_device_lock);
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
|
||||
if (device->parent)
|
||||
device->dev.parent = &parent->dev;
|
||||
@ -549,28 +546,22 @@ static int acpi_device_register(struct acpi_device *device,
|
||||
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
|
||||
return 0;
|
||||
end:
|
||||
spin_lock(&acpi_device_lock);
|
||||
if (device->parent) {
|
||||
mutex_lock(&acpi_device_lock);
|
||||
if (device->parent)
|
||||
list_del(&device->node);
|
||||
list_del(&device->g_list);
|
||||
} else
|
||||
list_del(&device->g_list);
|
||||
list_del(&device->wakeup_list);
|
||||
spin_unlock(&acpi_device_lock);
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void acpi_device_unregister(struct acpi_device *device, int type)
|
||||
{
|
||||
spin_lock(&acpi_device_lock);
|
||||
if (device->parent) {
|
||||
mutex_lock(&acpi_device_lock);
|
||||
if (device->parent)
|
||||
list_del(&device->node);
|
||||
list_del(&device->g_list);
|
||||
} else
|
||||
list_del(&device->g_list);
|
||||
|
||||
list_del(&device->wakeup_list);
|
||||
spin_unlock(&acpi_device_lock);
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
|
||||
acpi_detach_data(device->handle, acpi_bus_data_handler);
|
||||
|
||||
|
@ -5,3 +5,6 @@ extern int acpi_suspend (u32 state);
|
||||
extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
|
||||
extern void acpi_enable_wakeup_device(u8 sleep_state);
|
||||
extern void acpi_disable_wakeup_device(u8 sleep_state);
|
||||
|
||||
extern struct list_head acpi_wakeup_device_list;
|
||||
extern struct mutex acpi_device_lock;
|
||||
|
@ -98,6 +98,7 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
|
||||
static int acpi_thermal_add(struct acpi_device *device);
|
||||
static int acpi_thermal_remove(struct acpi_device *device, int type);
|
||||
static int acpi_thermal_resume(struct acpi_device *device);
|
||||
static void acpi_thermal_notify(struct acpi_device *device, u32 event);
|
||||
static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
|
||||
static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
|
||||
static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
|
||||
@ -123,6 +124,7 @@ static struct acpi_driver acpi_thermal_driver = {
|
||||
.add = acpi_thermal_add,
|
||||
.remove = acpi_thermal_remove,
|
||||
.resume = acpi_thermal_resume,
|
||||
.notify = acpi_thermal_notify,
|
||||
},
|
||||
};
|
||||
|
||||
@ -192,6 +194,7 @@ struct acpi_thermal {
|
||||
struct acpi_handle_list devices;
|
||||
struct thermal_zone_device *thermal_zone;
|
||||
int tz_enabled;
|
||||
int kelvin_offset;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
@ -581,7 +584,7 @@ static void acpi_thermal_check(void *data)
|
||||
}
|
||||
|
||||
/* sys I/F for generic thermal sysfs support */
|
||||
#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
|
||||
#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
|
||||
|
||||
static int thermal_get_temp(struct thermal_zone_device *thermal,
|
||||
unsigned long *temp)
|
||||
@ -596,7 +599,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
*temp = KELVIN_TO_MILLICELSIUS(tz->temperature);
|
||||
*temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -702,7 +705,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
if (tz->trips.critical.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
tz->trips.critical.temperature);
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
trip--;
|
||||
@ -711,7 +715,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
if (tz->trips.hot.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
tz->trips.hot.temperature);
|
||||
tz->trips.hot.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
trip--;
|
||||
@ -720,7 +725,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
if (tz->trips.passive.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
tz->trips.passive.temperature);
|
||||
tz->trips.passive.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
trip--;
|
||||
@ -730,7 +736,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
tz->trips.active[i].flags.valid; i++) {
|
||||
if (!trip) {
|
||||
*temp = KELVIN_TO_MILLICELSIUS(
|
||||
tz->trips.active[i].temperature);
|
||||
tz->trips.active[i].temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
trip--;
|
||||
@ -745,7 +752,8 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
|
||||
|
||||
if (tz->trips.critical.flags.valid) {
|
||||
*temperature = KELVIN_TO_MILLICELSIUS(
|
||||
tz->trips.critical.temperature);
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
@ -1264,17 +1272,14 @@ static int acpi_thermal_remove_fs(struct acpi_device *device)
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
|
||||
static void acpi_thermal_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct acpi_thermal *tz = data;
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_thermal *tz = acpi_driver_data(device);
|
||||
|
||||
|
||||
if (!tz)
|
||||
return;
|
||||
|
||||
device = tz->device;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_THERMAL_NOTIFY_TEMPERATURE:
|
||||
acpi_thermal_check(tz);
|
||||
@ -1298,8 +1303,6 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
|
||||
"Unsupported event [0x%x]\n", event));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int acpi_thermal_get_info(struct acpi_thermal *tz)
|
||||
@ -1334,10 +1337,28 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
|
||||
* handles temperature values with a single decimal place. As a consequence,
|
||||
* some implementations use an offset of 273.1 and others use an offset of
|
||||
* 273.2. Try to find out which one is being used, to present the most
|
||||
* accurate and visually appealing number.
|
||||
*
|
||||
* The heuristic below should work for all ACPI thermal zones which have a
|
||||
* critical trip point with a value being a multiple of 0.5 degree Celsius.
|
||||
*/
|
||||
static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
|
||||
{
|
||||
if (tz->trips.critical.flags.valid &&
|
||||
(tz->trips.critical.temperature % 5) == 1)
|
||||
tz->kelvin_offset = 2731;
|
||||
else
|
||||
tz->kelvin_offset = 2732;
|
||||
}
|
||||
|
||||
static int acpi_thermal_add(struct acpi_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_thermal *tz = NULL;
|
||||
|
||||
|
||||
@ -1360,6 +1381,8 @@ static int acpi_thermal_add(struct acpi_device *device)
|
||||
if (result)
|
||||
goto free_memory;
|
||||
|
||||
acpi_thermal_guess_offset(tz);
|
||||
|
||||
result = acpi_thermal_register_thermal_zone(tz);
|
||||
if (result)
|
||||
goto free_memory;
|
||||
@ -1368,21 +1391,11 @@ static int acpi_thermal_add(struct acpi_device *device)
|
||||
if (result)
|
||||
goto unregister_thermal_zone;
|
||||
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_thermal_notify, tz);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
result = -ENODEV;
|
||||
goto remove_fs;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
|
||||
acpi_device_name(device), acpi_device_bid(device),
|
||||
KELVIN_TO_CELSIUS(tz->temperature));
|
||||
goto end;
|
||||
|
||||
remove_fs:
|
||||
acpi_thermal_remove_fs(device);
|
||||
unregister_thermal_zone:
|
||||
thermal_zone_device_unregister(tz->thermal_zone);
|
||||
free_memory:
|
||||
@ -1393,7 +1406,6 @@ end:
|
||||
|
||||
static int acpi_thermal_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_thermal *tz = NULL;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
@ -1401,10 +1413,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
|
||||
|
||||
tz = acpi_driver_data(device);
|
||||
|
||||
status = acpi_remove_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_thermal_notify);
|
||||
|
||||
acpi_thermal_remove_fs(device);
|
||||
acpi_thermal_unregister_thermal_zone(tz);
|
||||
mutex_destroy(&tz->lock);
|
||||
|
@ -79,6 +79,7 @@ module_param(brightness_switch_enabled, bool, 0644);
|
||||
static int acpi_video_bus_add(struct acpi_device *device);
|
||||
static int acpi_video_bus_remove(struct acpi_device *device, int type);
|
||||
static int acpi_video_resume(struct acpi_device *device);
|
||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id video_device_ids[] = {
|
||||
{ACPI_VIDEO_HID, 0},
|
||||
@ -94,6 +95,7 @@ static struct acpi_driver acpi_video_bus = {
|
||||
.add = acpi_video_bus_add,
|
||||
.remove = acpi_video_bus_remove,
|
||||
.resume = acpi_video_resume,
|
||||
.notify = acpi_video_bus_notify,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1986,17 +1988,15 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
|
||||
return acpi_video_bus_DOS(video, 0, 1);
|
||||
}
|
||||
|
||||
static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
|
||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct acpi_video_bus *video = data;
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_video_bus *video = acpi_driver_data(device);
|
||||
struct input_dev *input;
|
||||
int keycode;
|
||||
|
||||
if (!video)
|
||||
return;
|
||||
|
||||
device = video->device;
|
||||
input = video->input;
|
||||
|
||||
switch (event) {
|
||||
@ -2127,7 +2127,6 @@ static int acpi_video_resume(struct acpi_device *device)
|
||||
|
||||
static int acpi_video_bus_add(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_video_bus *video;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
@ -2169,20 +2168,10 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
acpi_video_bus_get_devices(video, device);
|
||||
acpi_video_bus_start_devices(video);
|
||||
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify, video);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error installing notify handler\n");
|
||||
error = -ENODEV;
|
||||
goto err_stop_video;
|
||||
}
|
||||
|
||||
video->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_uninstall_notify;
|
||||
goto err_stop_video;
|
||||
}
|
||||
|
||||
snprintf(video->phys, sizeof(video->phys),
|
||||
@ -2218,9 +2207,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
|
||||
err_free_input_dev:
|
||||
input_free_device(input);
|
||||
err_uninstall_notify:
|
||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify);
|
||||
err_stop_video:
|
||||
acpi_video_bus_stop_devices(video);
|
||||
acpi_video_bus_put_devices(video);
|
||||
@ -2235,7 +2221,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
||||
|
||||
static int acpi_video_bus_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
struct acpi_video_bus *video = NULL;
|
||||
|
||||
|
||||
@ -2245,11 +2230,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
|
||||
video = acpi_driver_data(device);
|
||||
|
||||
acpi_video_bus_stop_devices(video);
|
||||
|
||||
status = acpi_remove_notify_handler(video->device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify);
|
||||
|
||||
acpi_video_bus_put_devices(video);
|
||||
acpi_video_bus_remove_fs(device);
|
||||
|
||||
|
@ -12,12 +12,14 @@
|
||||
#include "internal.h"
|
||||
#include "sleep.h"
|
||||
|
||||
/*
|
||||
* We didn't lock acpi_device_lock in the file, because it invokes oops in
|
||||
* suspend/resume and isn't really required as this is called in S-state. At
|
||||
* that time, there is no device hotplug
|
||||
**/
|
||||
#define _COMPONENT ACPI_SYSTEM_COMPONENT
|
||||
ACPI_MODULE_NAME("wakeup_devices")
|
||||
|
||||
extern struct list_head acpi_wakeup_device_list;
|
||||
extern spinlock_t acpi_device_lock;
|
||||
|
||||
/**
|
||||
* acpi_enable_wakeup_device_prep - prepare wakeup devices
|
||||
* @sleep_state: ACPI state
|
||||
@ -29,7 +31,6 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev = container_of(node,
|
||||
struct acpi_device,
|
||||
@ -40,11 +41,8 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
|
||||
(sleep_state > (u32) dev->wakeup.sleep_state))
|
||||
continue;
|
||||
|
||||
spin_unlock(&acpi_device_lock);
|
||||
acpi_enable_wakeup_device_power(dev, sleep_state);
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +58,6 @@ void acpi_enable_wakeup_device(u8 sleep_state)
|
||||
* Caution: this routine must be invoked when interrupt is disabled
|
||||
* Refer ACPI2.0: P212
|
||||
*/
|
||||
spin_lock(&acpi_device_lock);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev =
|
||||
container_of(node, struct acpi_device, wakeup_list);
|
||||
@ -74,22 +71,17 @@ void acpi_enable_wakeup_device(u8 sleep_state)
|
||||
if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
|
||||
|| sleep_state > (u32) dev->wakeup.sleep_state) {
|
||||
if (dev->wakeup.flags.run_wake) {
|
||||
spin_unlock(&acpi_device_lock);
|
||||
/* set_gpe_type will disable GPE, leave it like that */
|
||||
acpi_set_gpe_type(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_RUNTIME);
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
if (!dev->wakeup.flags.run_wake)
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +93,6 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev =
|
||||
container_of(node, struct acpi_device, wakeup_list);
|
||||
@ -112,19 +103,16 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|
||||
if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
|
||||
|| sleep_state > (u32) dev->wakeup.sleep_state) {
|
||||
if (dev->wakeup.flags.run_wake) {
|
||||
spin_unlock(&acpi_device_lock);
|
||||
acpi_set_gpe_type(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
/* Re-enable it, since set_gpe_type will disable it */
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_unlock(&acpi_device_lock);
|
||||
acpi_disable_wakeup_device_power(dev);
|
||||
/* Never disable run-wake GPE */
|
||||
if (!dev->wakeup.flags.run_wake) {
|
||||
@ -133,16 +121,14 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|
||||
acpi_clear_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number, ACPI_NOT_ISR);
|
||||
}
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
}
|
||||
|
||||
int __init acpi_wakeup_device_init(void)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
|
||||
spin_lock(&acpi_device_lock);
|
||||
mutex_lock(&acpi_device_lock);
|
||||
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
|
||||
struct acpi_device *dev = container_of(node,
|
||||
struct acpi_device,
|
||||
@ -150,15 +136,13 @@ int __init acpi_wakeup_device_init(void)
|
||||
/* In case user doesn't load button driver */
|
||||
if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
|
||||
continue;
|
||||
spin_unlock(&acpi_device_lock);
|
||||
acpi_set_gpe_type(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number,
|
||||
ACPI_GPE_TYPE_WAKE_RUN);
|
||||
acpi_enable_gpe(dev->wakeup.gpe_device,
|
||||
dev->wakeup.gpe_number);
|
||||
dev->wakeup.state.enabled = 1;
|
||||
spin_lock(&acpi_device_lock);
|
||||
}
|
||||
spin_unlock(&acpi_device_lock);
|
||||
mutex_unlock(&acpi_device_lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
|
||||
}
|
||||
|
||||
ext_csd_struct = ext_csd[EXT_CSD_REV];
|
||||
if (ext_csd_struct > 2) {
|
||||
if (ext_csd_struct > 3) {
|
||||
printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
|
||||
"version %d\n", mmc_hostname(card->host),
|
||||
ext_csd_struct);
|
||||
|
@ -362,15 +362,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* For SPI, enable CRC as appropriate.
|
||||
*/
|
||||
if (mmc_host_is_spi(host)) {
|
||||
err = mmc_spi_set_crc(host, use_spi_crc);
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch CID from card.
|
||||
*/
|
||||
@ -457,6 +448,18 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
/*
|
||||
* For SPI, enable CRC as appropriate.
|
||||
* This CRC enable is located AFTER the reading of the
|
||||
* card registers because some SDHC cards are not able
|
||||
* to provide valid CRCs for non-512-byte blocks.
|
||||
*/
|
||||
if (mmc_host_is_spi(host)) {
|
||||
err = mmc_spi_set_crc(host, use_spi_crc);
|
||||
if (err)
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to change to high-speed (if supported)
|
||||
*/
|
||||
|
@ -307,13 +307,6 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
|
||||
|
||||
wmb();
|
||||
|
||||
if (host->actual_bus_width == MMC_BUS_WIDTH_4)
|
||||
BLR(host->dma) = 0; /* burst 64 byte read / 64 bytes write */
|
||||
else
|
||||
BLR(host->dma) = 16; /* burst 16 byte read / 16 bytes write */
|
||||
|
||||
RSSR(host->dma) = DMA_REQ_SDHC;
|
||||
|
||||
set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
|
||||
clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
|
||||
|
||||
@ -818,9 +811,11 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
if (ios->bus_width == MMC_BUS_WIDTH_4) {
|
||||
host->actual_bus_width = MMC_BUS_WIDTH_4;
|
||||
imx_gpio_mode(PB11_PF_SD_DAT3);
|
||||
BLR(host->dma) = 0; /* burst 64 byte read/write */
|
||||
} else {
|
||||
host->actual_bus_width = MMC_BUS_WIDTH_1;
|
||||
imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
|
||||
BLR(host->dma) = 16; /* burst 16 byte read/write */
|
||||
}
|
||||
|
||||
if (host->power_mode != ios->power_mode) {
|
||||
@ -938,7 +933,7 @@ static void imxmci_check_status(unsigned long data)
|
||||
mod_timer(&host->timer, jiffies + (HZ>>1));
|
||||
}
|
||||
|
||||
static int imxmci_probe(struct platform_device *pdev)
|
||||
static int __init imxmci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mmc_host *mmc;
|
||||
struct imxmci_host *host = NULL;
|
||||
@ -1034,6 +1029,7 @@ static int imxmci_probe(struct platform_device *pdev)
|
||||
}
|
||||
host->dma_allocated = 1;
|
||||
imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
|
||||
RSSR(host->dma) = DMA_REQ_SDHC;
|
||||
|
||||
tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
|
||||
host->status_reg=0;
|
||||
@ -1079,7 +1075,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imxmci_remove(struct platform_device *pdev)
|
||||
static int __exit imxmci_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mmc_host *mmc = platform_get_drvdata(pdev);
|
||||
|
||||
@ -1145,8 +1141,7 @@ static int imxmci_resume(struct platform_device *dev)
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct platform_driver imxmci_driver = {
|
||||
.probe = imxmci_probe,
|
||||
.remove = imxmci_remove,
|
||||
.remove = __exit_p(imxmci_remove),
|
||||
.suspend = imxmci_suspend,
|
||||
.resume = imxmci_resume,
|
||||
.driver = {
|
||||
@ -1157,7 +1152,7 @@ static struct platform_driver imxmci_driver = {
|
||||
|
||||
static int __init imxmci_init(void)
|
||||
{
|
||||
return platform_driver_register(&imxmci_driver);
|
||||
return platform_driver_probe(&imxmci_driver, imxmci_probe);
|
||||
}
|
||||
|
||||
static void __exit imxmci_exit(void)
|
||||
|
@ -24,7 +24,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bio.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@ -95,7 +95,7 @@
|
||||
* reads which takes nowhere near that long. Older cards may be able to use
|
||||
* shorter timeouts ... but why bother?
|
||||
*/
|
||||
#define r1b_timeout ktime_set(3, 0)
|
||||
#define r1b_timeout (HZ * 3)
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
@ -183,12 +183,11 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len)
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
|
||||
static int mmc_spi_skip(struct mmc_spi_host *host, unsigned long timeout,
|
||||
unsigned n, u8 byte)
|
||||
{
|
||||
u8 *cp = host->data->status;
|
||||
|
||||
timeout = ktime_add(timeout, ktime_get());
|
||||
unsigned long start = jiffies;
|
||||
|
||||
while (1) {
|
||||
int status;
|
||||
@ -203,22 +202,26 @@ mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
|
||||
return cp[i];
|
||||
}
|
||||
|
||||
/* REVISIT investigate msleep() to avoid busy-wait I/O
|
||||
* in at least some cases.
|
||||
*/
|
||||
if (ktime_to_ns(ktime_sub(ktime_get(), timeout)) > 0)
|
||||
if (time_is_before_jiffies(start + timeout))
|
||||
break;
|
||||
|
||||
/* If we need long timeouts, we may release the CPU.
|
||||
* We use jiffies here because we want to have a relation
|
||||
* between elapsed time and the blocking of the scheduler.
|
||||
*/
|
||||
if (time_is_before_jiffies(start+1))
|
||||
schedule();
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout)
|
||||
mmc_spi_wait_unbusy(struct mmc_spi_host *host, unsigned long timeout)
|
||||
{
|
||||
return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
|
||||
}
|
||||
|
||||
static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout)
|
||||
static int mmc_spi_readtoken(struct mmc_spi_host *host, unsigned long timeout)
|
||||
{
|
||||
return mmc_spi_skip(host, timeout, 1, 0xff);
|
||||
}
|
||||
@ -251,6 +254,10 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
||||
u8 *cp = host->data->status;
|
||||
u8 *end = cp + host->t.len;
|
||||
int value = 0;
|
||||
int bitshift;
|
||||
u8 leftover = 0;
|
||||
unsigned short rotator;
|
||||
int i;
|
||||
char tag[32];
|
||||
|
||||
snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s",
|
||||
@ -268,9 +275,8 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
||||
|
||||
/* Data block reads (R1 response types) may need more data... */
|
||||
if (cp == end) {
|
||||
unsigned i;
|
||||
|
||||
cp = host->data->status;
|
||||
end = cp+1;
|
||||
|
||||
/* Card sends N(CR) (== 1..8) bytes of all-ones then one
|
||||
* status byte ... and we already scanned 2 bytes.
|
||||
@ -295,20 +301,34 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
||||
}
|
||||
|
||||
checkstatus:
|
||||
if (*cp & 0x80) {
|
||||
dev_dbg(&host->spi->dev, "%s: INVALID RESPONSE, %02x\n",
|
||||
tag, *cp);
|
||||
value = -EBADR;
|
||||
goto done;
|
||||
bitshift = 0;
|
||||
if (*cp & 0x80) {
|
||||
/* Houston, we have an ugly card with a bit-shifted response */
|
||||
rotator = *cp++ << 8;
|
||||
/* read the next byte */
|
||||
if (cp == end) {
|
||||
value = mmc_spi_readbytes(host, 1);
|
||||
if (value < 0)
|
||||
goto done;
|
||||
cp = host->data->status;
|
||||
end = cp+1;
|
||||
}
|
||||
rotator |= *cp++;
|
||||
while (rotator & 0x8000) {
|
||||
bitshift++;
|
||||
rotator <<= 1;
|
||||
}
|
||||
cmd->resp[0] = rotator >> 8;
|
||||
leftover = rotator;
|
||||
} else {
|
||||
cmd->resp[0] = *cp++;
|
||||
}
|
||||
|
||||
cmd->resp[0] = *cp++;
|
||||
cmd->error = 0;
|
||||
|
||||
/* Status byte: the entire seven-bit R1 response. */
|
||||
if (cmd->resp[0] != 0) {
|
||||
if ((R1_SPI_PARAMETER | R1_SPI_ADDRESS
|
||||
| R1_SPI_ILLEGAL_COMMAND)
|
||||
| R1_SPI_ILLEGAL_COMMAND)
|
||||
& cmd->resp[0])
|
||||
value = -EINVAL;
|
||||
else if (R1_SPI_COM_CRC & cmd->resp[0])
|
||||
@ -336,12 +356,45 @@ checkstatus:
|
||||
* SPI R5 == R1 + data byte; IO_RW_DIRECT
|
||||
*/
|
||||
case MMC_RSP_SPI_R2:
|
||||
cmd->resp[0] |= *cp << 8;
|
||||
/* read the next byte */
|
||||
if (cp == end) {
|
||||
value = mmc_spi_readbytes(host, 1);
|
||||
if (value < 0)
|
||||
goto done;
|
||||
cp = host->data->status;
|
||||
end = cp+1;
|
||||
}
|
||||
if (bitshift) {
|
||||
rotator = leftover << 8;
|
||||
rotator |= *cp << bitshift;
|
||||
cmd->resp[0] |= (rotator & 0xFF00);
|
||||
} else {
|
||||
cmd->resp[0] |= *cp << 8;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SPI R3, R4, or R7 == R1 + 4 bytes */
|
||||
case MMC_RSP_SPI_R3:
|
||||
cmd->resp[1] = get_unaligned_be32(cp);
|
||||
rotator = leftover << 8;
|
||||
cmd->resp[1] = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
cmd->resp[1] <<= 8;
|
||||
/* read the next byte */
|
||||
if (cp == end) {
|
||||
value = mmc_spi_readbytes(host, 1);
|
||||
if (value < 0)
|
||||
goto done;
|
||||
cp = host->data->status;
|
||||
end = cp+1;
|
||||
}
|
||||
if (bitshift) {
|
||||
rotator |= *cp++ << bitshift;
|
||||
cmd->resp[1] |= (rotator >> 8);
|
||||
rotator <<= 8;
|
||||
} else {
|
||||
cmd->resp[1] |= *cp++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* SPI R1 == just one status byte */
|
||||
@ -607,7 +660,7 @@ mmc_spi_setup_data_message(
|
||||
*/
|
||||
static int
|
||||
mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
||||
ktime_t timeout)
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct spi_device *spi = host->spi;
|
||||
int status, i;
|
||||
@ -717,11 +770,13 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
||||
*/
|
||||
static int
|
||||
mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
||||
ktime_t timeout)
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct spi_device *spi = host->spi;
|
||||
int status;
|
||||
struct scratch *scratch = host->data;
|
||||
unsigned int bitshift;
|
||||
u8 leftover;
|
||||
|
||||
/* At least one SD card sends an all-zeroes byte when N(CX)
|
||||
* applies, before the all-ones bytes ... just cope with that.
|
||||
@ -733,38 +788,60 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
|
||||
if (status == 0xff || status == 0)
|
||||
status = mmc_spi_readtoken(host, timeout);
|
||||
|
||||
if (status == SPI_TOKEN_SINGLE) {
|
||||
if (host->dma_dev) {
|
||||
dma_sync_single_for_device(host->dma_dev,
|
||||
host->data_dma, sizeof(*scratch),
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_sync_single_for_device(host->dma_dev,
|
||||
t->rx_dma, t->len,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
status = spi_sync(spi, &host->m);
|
||||
|
||||
if (host->dma_dev) {
|
||||
dma_sync_single_for_cpu(host->dma_dev,
|
||||
host->data_dma, sizeof(*scratch),
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_sync_single_for_cpu(host->dma_dev,
|
||||
t->rx_dma, t->len,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (status < 0) {
|
||||
dev_dbg(&spi->dev, "read error %02x (%d)\n", status, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* we've read extra garbage, timed out, etc */
|
||||
if (status < 0)
|
||||
return status;
|
||||
/* The token may be bit-shifted...
|
||||
* the first 0-bit precedes the data stream.
|
||||
*/
|
||||
bitshift = 7;
|
||||
while (status & 0x80) {
|
||||
status <<= 1;
|
||||
bitshift--;
|
||||
}
|
||||
leftover = status << 1;
|
||||
|
||||
/* low four bits are an R2 subset, fifth seems to be
|
||||
* vendor specific ... map them all to generic error..
|
||||
if (host->dma_dev) {
|
||||
dma_sync_single_for_device(host->dma_dev,
|
||||
host->data_dma, sizeof(*scratch),
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_sync_single_for_device(host->dma_dev,
|
||||
t->rx_dma, t->len,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
status = spi_sync(spi, &host->m);
|
||||
|
||||
if (host->dma_dev) {
|
||||
dma_sync_single_for_cpu(host->dma_dev,
|
||||
host->data_dma, sizeof(*scratch),
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_sync_single_for_cpu(host->dma_dev,
|
||||
t->rx_dma, t->len,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
if (bitshift) {
|
||||
/* Walk through the data and the crc and do
|
||||
* all the magic to get byte-aligned data.
|
||||
*/
|
||||
return -EIO;
|
||||
u8 *cp = t->rx_buf;
|
||||
unsigned int len;
|
||||
unsigned int bitright = 8 - bitshift;
|
||||
u8 temp;
|
||||
for (len = t->len; len; len--) {
|
||||
temp = *cp;
|
||||
*cp++ = leftover | (temp >> bitshift);
|
||||
leftover = temp << bitright;
|
||||
}
|
||||
cp = (u8 *) &scratch->crc_val;
|
||||
temp = *cp;
|
||||
*cp++ = leftover | (temp >> bitshift);
|
||||
leftover = temp << bitright;
|
||||
temp = *cp;
|
||||
*cp = leftover | (temp >> bitshift);
|
||||
}
|
||||
|
||||
if (host->mmc->use_spi_crc) {
|
||||
@ -803,7 +880,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
unsigned n_sg;
|
||||
int multiple = (data->blocks > 1);
|
||||
u32 clock_rate;
|
||||
ktime_t timeout;
|
||||
unsigned long timeout;
|
||||
|
||||
if (data->flags & MMC_DATA_READ)
|
||||
direction = DMA_FROM_DEVICE;
|
||||
@ -817,8 +894,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
else
|
||||
clock_rate = spi->max_speed_hz;
|
||||
|
||||
timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns +
|
||||
data->timeout_clks * 1000000 / clock_rate);
|
||||
timeout = data->timeout_ns +
|
||||
data->timeout_clks * 1000000 / clock_rate;
|
||||
timeout = usecs_to_jiffies((unsigned int)(timeout / 1000)) + 1;
|
||||
|
||||
/* Handle scatterlist segments one at a time, with synch for
|
||||
* each 512-byte block
|
||||
|
@ -298,7 +298,6 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
|
||||
struct mmc_request *mrq = host->mrq;
|
||||
|
||||
host->mrq = NULL;
|
||||
mmc_omap_fclk_lazy_disable(host);
|
||||
mmc_request_done(host->mmc, mrq);
|
||||
return;
|
||||
}
|
||||
@ -434,6 +433,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
||||
if (host->mrq == NULL) {
|
||||
OMAP_HSMMC_WRITE(host->base, STAT,
|
||||
OMAP_HSMMC_READ(host->base, STAT));
|
||||
/* Flush posted write */
|
||||
OMAP_HSMMC_READ(host->base, STAT);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -489,8 +490,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
/* Flush posted write */
|
||||
OMAP_HSMMC_READ(host->base, STAT);
|
||||
|
||||
if (end_cmd || (status & CC))
|
||||
if (end_cmd || ((status & CC) && host->cmd))
|
||||
mmc_omap_cmd_done(host, host->cmd);
|
||||
if (end_trans || (status & TC))
|
||||
mmc_omap_xfer_done(host, data);
|
||||
|
@ -729,6 +729,6 @@ static void __exit sdhci_drv_exit(void)
|
||||
module_init(sdhci_drv_init);
|
||||
module_exit(sdhci_drv_exit);
|
||||
|
||||
MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
|
||||
MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
|
||||
MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -1935,7 +1935,7 @@ module_exit(sdhci_drv_exit);
|
||||
|
||||
module_param(debug_quirks, uint, 0444);
|
||||
|
||||
MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
|
||||
MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
|
||||
MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@ -2036,7 +2036,7 @@ module_param_named(irq, param_irq, uint, 0444);
|
||||
module_param_named(dma, param_dma, int, 0444);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
|
||||
MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
|
||||
MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
|
@ -977,6 +977,8 @@ config ETHOC
|
||||
depends on NET_ETHERNET && HAS_IOMEM
|
||||
select MII
|
||||
select PHYLIB
|
||||
select CRC32
|
||||
select BITREVERSE
|
||||
help
|
||||
Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
|
||||
|
||||
@ -2056,6 +2058,27 @@ config IGB_DCA
|
||||
driver. DCA is a method for warming the CPU cache before data
|
||||
is used, with the intent of lessening the impact of cache misses.
|
||||
|
||||
config IGBVF
|
||||
tristate "Intel(R) 82576 Virtual Function Ethernet support"
|
||||
depends on PCI
|
||||
---help---
|
||||
This driver supports Intel(R) 82576 virtual functions. For more
|
||||
information on how to identify your adapter, go to the Adapter &
|
||||
Driver ID Guide at:
|
||||
|
||||
<http://support.intel.com/support/network/adapter/pro100/21397.htm>
|
||||
|
||||
For general information and support, go to the Intel support
|
||||
website at:
|
||||
|
||||
<http://support.intel.com>
|
||||
|
||||
More specific information on configuring the driver is in
|
||||
<file:Documentation/networking/e1000.txt>.
|
||||
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called igbvf.
|
||||
|
||||
source "drivers/net/ixp2000/Kconfig"
|
||||
|
||||
config MYRI_SBUS
|
||||
|
@ -6,6 +6,7 @@ obj-$(CONFIG_E1000) += e1000/
|
||||
obj-$(CONFIG_E1000E) += e1000e/
|
||||
obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
|
||||
obj-$(CONFIG_IGB) += igb/
|
||||
obj-$(CONFIG_IGBVF) += igbvf/
|
||||
obj-$(CONFIG_IXGBE) += ixgbe/
|
||||
obj-$(CONFIG_IXGB) += ixgb/
|
||||
obj-$(CONFIG_IP1000) += ipg.o
|
||||
|
@ -3427,8 +3427,8 @@ static int __devinit
|
||||
bnx2_request_firmware(struct bnx2 *bp)
|
||||
{
|
||||
const char *mips_fw_file, *rv2p_fw_file;
|
||||
const struct bnx2_mips_fw_file *mips;
|
||||
const struct bnx2_rv2p_fw_file *rv2p;
|
||||
const struct bnx2_mips_fw_file *mips_fw;
|
||||
const struct bnx2_rv2p_fw_file *rv2p_fw;
|
||||
int rc;
|
||||
|
||||
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
|
||||
@ -3452,21 +3452,21 @@ bnx2_request_firmware(struct bnx2 *bp)
|
||||
rv2p_fw_file);
|
||||
return rc;
|
||||
}
|
||||
mips = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
|
||||
rv2p = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
|
||||
if (bp->mips_firmware->size < sizeof(*mips) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->com) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->cp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->rxp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->tpat) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips->txp)) {
|
||||
mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
|
||||
rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
|
||||
if (bp->mips_firmware->size < sizeof(*mips_fw) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->com) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->cp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) ||
|
||||
check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) {
|
||||
printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
|
||||
mips_fw_file);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (bp->rv2p_firmware->size < sizeof(*rv2p) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p->proc1.rv2p, 8, true) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p->proc2.rv2p, 8, true)) {
|
||||
if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) ||
|
||||
check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) {
|
||||
printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n",
|
||||
rv2p_fw_file);
|
||||
return -EINVAL;
|
||||
|
@ -542,6 +542,8 @@ static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
|
||||
}
|
||||
spin_unlock_bh(&eql->queue.lock);
|
||||
|
||||
dev_put(slave_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1240,6 +1240,7 @@ static void __inline__ fec_phy_ack_intr(void)
|
||||
icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
|
||||
*icrp = 0x0d000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_M5272
|
||||
static void __inline__ fec_get_mac(struct net_device *dev)
|
||||
|
@ -152,14 +152,13 @@ static struct notifier_block dca_notifier = {
|
||||
/* for netdump / net console */
|
||||
static void igb_netpoll(struct net_device *);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static ssize_t igb_set_num_vfs(struct device *, struct device_attribute *,
|
||||
const char *, size_t);
|
||||
static ssize_t igb_show_num_vfs(struct device *, struct device_attribute *,
|
||||
char *);
|
||||
DEVICE_ATTR(num_vfs, S_IRUGO | S_IWUSR, igb_show_num_vfs, igb_set_num_vfs);
|
||||
#endif
|
||||
static unsigned int max_vfs = 0;
|
||||
module_param(max_vfs, uint, 0);
|
||||
MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate "
|
||||
"per physical function");
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
||||
static pci_ers_result_t igb_io_error_detected(struct pci_dev *,
|
||||
pci_channel_state_t);
|
||||
static pci_ers_result_t igb_io_slot_reset(struct pci_dev *);
|
||||
@ -671,6 +670,21 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter)
|
||||
|
||||
/* If we can't do MSI-X, try MSI */
|
||||
msi_only:
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* disable SR-IOV for non MSI-X configurations */
|
||||
if (adapter->vf_data) {
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
/* disable iov and allow time for transactions to clear */
|
||||
pci_disable_sriov(adapter->pdev);
|
||||
msleep(500);
|
||||
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
|
||||
msleep(100);
|
||||
dev_info(&adapter->pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
#endif
|
||||
adapter->num_rx_queues = 1;
|
||||
adapter->num_tx_queues = 1;
|
||||
if (!pci_enable_msi(adapter->pdev))
|
||||
@ -1238,6 +1252,39 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_sw_init;
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* since iov functionality isn't critical to base device function we
|
||||
* can accept failure. If it fails we don't allow iov to be enabled */
|
||||
if (hw->mac.type == e1000_82576) {
|
||||
/* 82576 supports a maximum of 7 VFs in addition to the PF */
|
||||
unsigned int num_vfs = (max_vfs > 7) ? 7 : max_vfs;
|
||||
int i;
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
|
||||
if (num_vfs)
|
||||
adapter->vf_data = kcalloc(num_vfs,
|
||||
sizeof(struct vf_data_storage),
|
||||
GFP_KERNEL);
|
||||
if (!adapter->vf_data) {
|
||||
dev_err(&pdev->dev, "Could not allocate VF private "
|
||||
"data - IOV enable failed\n");
|
||||
} else {
|
||||
err = pci_enable_sriov(pdev, num_vfs);
|
||||
if (!err) {
|
||||
adapter->vfs_allocated_count = num_vfs;
|
||||
dev_info(&pdev->dev, "%d vfs allocated\n", num_vfs);
|
||||
for (i = 0; i < adapter->vfs_allocated_count; i++) {
|
||||
random_ether_addr(mac_addr);
|
||||
igb_set_vf_mac(adapter, i, mac_addr);
|
||||
}
|
||||
} else {
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/* setup the private structure */
|
||||
err = igb_sw_init(adapter);
|
||||
if (err)
|
||||
@ -1397,19 +1444,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_register;
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
/* since iov functionality isn't critical to base device function we
|
||||
* can accept failure. If it fails we don't allow iov to be enabled */
|
||||
if (hw->mac.type == e1000_82576) {
|
||||
err = pci_enable_sriov(pdev, 0);
|
||||
if (!err)
|
||||
err = device_create_file(&netdev->dev,
|
||||
&dev_attr_num_vfs);
|
||||
if (err)
|
||||
dev_err(&pdev->dev, "Failed to initialize IOV\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (dca_add_requester(&pdev->dev) == 0) {
|
||||
adapter->flags |= IGB_FLAG_DCA_ENABLED;
|
||||
@ -5422,89 +5456,4 @@ static void igb_vmm_control(struct igb_adapter *adapter)
|
||||
igb_vmdq_set_replication_pf(hw, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static ssize_t igb_show_num_vfs(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct igb_adapter *adapter = netdev_priv(to_net_dev(dev));
|
||||
|
||||
return sprintf(buf, "%d\n", adapter->vfs_allocated_count);
|
||||
}
|
||||
|
||||
static ssize_t igb_set_num_vfs(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct net_device *netdev = to_net_dev(dev);
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
unsigned int num_vfs, i;
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
int err;
|
||||
|
||||
sscanf(buf, "%u", &num_vfs);
|
||||
|
||||
if (num_vfs > 7)
|
||||
num_vfs = 7;
|
||||
|
||||
/* value unchanged do nothing */
|
||||
if (num_vfs == adapter->vfs_allocated_count)
|
||||
return count;
|
||||
|
||||
if (netdev->flags & IFF_UP)
|
||||
igb_close(netdev);
|
||||
|
||||
igb_reset_interrupt_capability(adapter);
|
||||
igb_free_queues(adapter);
|
||||
adapter->tx_ring = NULL;
|
||||
adapter->rx_ring = NULL;
|
||||
adapter->vfs_allocated_count = 0;
|
||||
|
||||
/* reclaim resources allocated to VFs since we are changing count */
|
||||
if (adapter->vf_data) {
|
||||
/* disable iov and allow time for transactions to clear */
|
||||
pci_disable_sriov(pdev);
|
||||
msleep(500);
|
||||
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
|
||||
msleep(100);
|
||||
dev_info(&pdev->dev, "IOV Disabled\n");
|
||||
}
|
||||
|
||||
if (num_vfs) {
|
||||
adapter->vf_data = kcalloc(num_vfs,
|
||||
sizeof(struct vf_data_storage),
|
||||
GFP_KERNEL);
|
||||
if (!adapter->vf_data) {
|
||||
dev_err(&pdev->dev, "Could not allocate VF private "
|
||||
"data - IOV enable failed\n");
|
||||
} else {
|
||||
err = pci_enable_sriov(pdev, num_vfs);
|
||||
if (!err) {
|
||||
adapter->vfs_allocated_count = num_vfs;
|
||||
dev_info(&pdev->dev, "%d vfs allocated\n", num_vfs);
|
||||
for (i = 0; i < adapter->vfs_allocated_count; i++) {
|
||||
random_ether_addr(mac_addr);
|
||||
igb_set_vf_mac(adapter, i, mac_addr);
|
||||
}
|
||||
} else {
|
||||
kfree(adapter->vf_data);
|
||||
adapter->vf_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
igb_set_interrupt_capability(adapter);
|
||||
igb_alloc_queues(adapter);
|
||||
igb_reset(adapter);
|
||||
|
||||
if (netdev->flags & IFF_UP)
|
||||
igb_open(netdev);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
/* igb_main.c */
|
||||
|
38
drivers/net/igbvf/Makefile
Normal file
38
drivers/net/igbvf/Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
################################################################################
|
||||
#
|
||||
# Intel(R) 82576 Virtual Function Linux driver
|
||||
# Copyright(c) 2009 Intel Corporation.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# The full GNU General Public License is included in this distribution in
|
||||
# the file called "COPYING".
|
||||
#
|
||||
# Contact Information:
|
||||
# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
#
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Makefile for the Intel(R) 82576 VF ethernet driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IGBVF) += igbvf.o
|
||||
|
||||
igbvf-objs := vf.o \
|
||||
mbx.o \
|
||||
ethtool.o \
|
||||
netdev.o
|
||||
|
125
drivers/net/igbvf/defines.h
Normal file
125
drivers/net/igbvf/defines.h
Normal file
@ -0,0 +1,125 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_DEFINES_H_
|
||||
#define _E1000_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
/* IVAR valid bit */
|
||||
#define E1000_IVAR_VALID 0x80
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
|
||||
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
|
||||
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
|
||||
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
|
||||
|
||||
#define E1000_RXDEXT_STATERR_CE 0x01000000
|
||||
#define E1000_RXDEXT_STATERR_SE 0x02000000
|
||||
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
|
||||
#define E1000_RXDEXT_STATERR_CXE 0x10000000
|
||||
#define E1000_RXDEXT_STATERR_TCPE 0x20000000
|
||||
#define E1000_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define E1000_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
|
||||
/* Same mask, but for extended and packet split descriptors */
|
||||
#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
|
||||
E1000_RXDEXT_STATERR_CE | \
|
||||
E1000_RXDEXT_STATERR_SE | \
|
||||
E1000_RXDEXT_STATERR_SEQ | \
|
||||
E1000_RXDEXT_STATERR_CXE | \
|
||||
E1000_RXDEXT_STATERR_RXE)
|
||||
|
||||
/* Device Control */
|
||||
#define E1000_CTRL_RST 0x04000000 /* Global reset */
|
||||
|
||||
/* Device Status */
|
||||
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
|
||||
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
|
||||
#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
|
||||
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x3F00
|
||||
|
||||
/* 802.1q VLAN Packet Size */
|
||||
#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
|
||||
|
||||
/* Error Codes */
|
||||
#define E1000_SUCCESS 0
|
||||
#define E1000_ERR_CONFIG 3
|
||||
#define E1000_ERR_MAC_INIT 5
|
||||
#define E1000_ERR_MBX 15
|
||||
|
||||
#ifndef ETH_ADDR_LEN
|
||||
#define ETH_ADDR_LEN 6
|
||||
#endif
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
|
||||
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
|
||||
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
|
||||
|
||||
/* Additional Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
|
||||
|
||||
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
|
||||
|
||||
#endif /* _E1000_DEFINES_H_ */
|
540
drivers/net/igbvf/ethtool.c
Normal file
540
drivers/net/igbvf/ethtool.c
Normal file
@ -0,0 +1,540 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/* ethtool support for igbvf */
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "igbvf.h"
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
|
||||
struct igbvf_stats {
|
||||
char stat_string[ETH_GSTRING_LEN];
|
||||
int sizeof_stat;
|
||||
int stat_offset;
|
||||
int base_stat_offset;
|
||||
};
|
||||
|
||||
#define IGBVF_STAT(current, base) \
|
||||
sizeof(((struct igbvf_adapter *)0)->current), \
|
||||
offsetof(struct igbvf_adapter, current), \
|
||||
offsetof(struct igbvf_adapter, base)
|
||||
|
||||
static const struct igbvf_stats igbvf_gstrings_stats[] = {
|
||||
{ "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
|
||||
{ "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
|
||||
{ "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
|
||||
{ "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
|
||||
{ "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
|
||||
{ "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
|
||||
{ "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
|
||||
{ "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
|
||||
{ "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) },
|
||||
{ "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
|
||||
{ "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
|
||||
{ "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
|
||||
{ "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
|
||||
};
|
||||
|
||||
#define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
|
||||
|
||||
static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
|
||||
"Link test (on/offline)"
|
||||
};
|
||||
|
||||
#define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
|
||||
|
||||
static int igbvf_get_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *ecmd)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 status;
|
||||
|
||||
ecmd->supported = SUPPORTED_1000baseT_Full;
|
||||
|
||||
ecmd->advertising = ADVERTISED_1000baseT_Full;
|
||||
|
||||
ecmd->port = -1;
|
||||
ecmd->transceiver = XCVR_DUMMY1;
|
||||
|
||||
status = er32(STATUS);
|
||||
if (status & E1000_STATUS_LU) {
|
||||
if (status & E1000_STATUS_SPEED_1000)
|
||||
ecmd->speed = 1000;
|
||||
else if (status & E1000_STATUS_SPEED_100)
|
||||
ecmd->speed = 100;
|
||||
else
|
||||
ecmd->speed = 10;
|
||||
|
||||
if (status & E1000_STATUS_FD)
|
||||
ecmd->duplex = DUPLEX_FULL;
|
||||
else
|
||||
ecmd->duplex = DUPLEX_HALF;
|
||||
} else {
|
||||
ecmd->speed = -1;
|
||||
ecmd->duplex = -1;
|
||||
}
|
||||
|
||||
ecmd->autoneg = AUTONEG_DISABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 igbvf_get_link(struct net_device *netdev)
|
||||
{
|
||||
return netif_carrier_ok(netdev);
|
||||
}
|
||||
|
||||
static int igbvf_set_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *ecmd)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void igbvf_get_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int igbvf_set_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static u32 igbvf_get_tx_csum(struct net_device *netdev)
|
||||
{
|
||||
return ((netdev->features & NETIF_F_IP_CSUM) != 0);
|
||||
}
|
||||
|
||||
static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
|
||||
{
|
||||
if (data)
|
||||
netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
|
||||
else
|
||||
netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_set_tso(struct net_device *netdev, u32 data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
struct net_device *v_netdev;
|
||||
|
||||
if (data) {
|
||||
netdev->features |= NETIF_F_TSO;
|
||||
netdev->features |= NETIF_F_TSO6;
|
||||
} else {
|
||||
netdev->features &= ~NETIF_F_TSO;
|
||||
netdev->features &= ~NETIF_F_TSO6;
|
||||
/* disable TSO on all VLANs if they're present */
|
||||
if (!adapter->vlgrp)
|
||||
goto tso_out;
|
||||
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
|
||||
v_netdev = vlan_group_get_device(adapter->vlgrp, i);
|
||||
if (!v_netdev)
|
||||
continue;
|
||||
|
||||
v_netdev->features &= ~NETIF_F_TSO;
|
||||
v_netdev->features &= ~NETIF_F_TSO6;
|
||||
vlan_group_set_device(adapter->vlgrp, i, v_netdev);
|
||||
}
|
||||
}
|
||||
|
||||
tso_out:
|
||||
dev_info(&adapter->pdev->dev, "TSO is %s\n",
|
||||
data ? "Enabled" : "Disabled");
|
||||
adapter->flags |= FLAG_TSO_FORCE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 igbvf_get_msglevel(struct net_device *netdev)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
return adapter->msg_enable;
|
||||
}
|
||||
|
||||
static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
adapter->msg_enable = data;
|
||||
}
|
||||
|
||||
static int igbvf_get_regs_len(struct net_device *netdev)
|
||||
{
|
||||
#define IGBVF_REGS_LEN 8
|
||||
return IGBVF_REGS_LEN * sizeof(u32);
|
||||
}
|
||||
|
||||
static void igbvf_get_regs(struct net_device *netdev,
|
||||
struct ethtool_regs *regs, void *p)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 *regs_buff = p;
|
||||
u8 revision_id;
|
||||
|
||||
memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
|
||||
|
||||
pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
|
||||
|
||||
regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
|
||||
|
||||
regs_buff[0] = er32(CTRL);
|
||||
regs_buff[1] = er32(STATUS);
|
||||
|
||||
regs_buff[2] = er32(RDLEN(0));
|
||||
regs_buff[3] = er32(RDH(0));
|
||||
regs_buff[4] = er32(RDT(0));
|
||||
|
||||
regs_buff[5] = er32(TDLEN(0));
|
||||
regs_buff[6] = er32(TDH(0));
|
||||
regs_buff[7] = er32(TDT(0));
|
||||
}
|
||||
|
||||
static int igbvf_get_eeprom_len(struct net_device *netdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_get_eeprom(struct net_device *netdev,
|
||||
struct ethtool_eeprom *eeprom, u8 *bytes)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int igbvf_set_eeprom(struct net_device *netdev,
|
||||
struct ethtool_eeprom *eeprom, u8 *bytes)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void igbvf_get_drvinfo(struct net_device *netdev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
char firmware_version[32] = "N/A";
|
||||
|
||||
strncpy(drvinfo->driver, igbvf_driver_name, 32);
|
||||
strncpy(drvinfo->version, igbvf_driver_version, 32);
|
||||
strncpy(drvinfo->fw_version, firmware_version, 32);
|
||||
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
|
||||
drvinfo->regdump_len = igbvf_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void igbvf_get_ringparam(struct net_device *netdev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct igbvf_ring *tx_ring = adapter->tx_ring;
|
||||
struct igbvf_ring *rx_ring = adapter->rx_ring;
|
||||
|
||||
ring->rx_max_pending = IGBVF_MAX_RXD;
|
||||
ring->tx_max_pending = IGBVF_MAX_TXD;
|
||||
ring->rx_mini_max_pending = 0;
|
||||
ring->rx_jumbo_max_pending = 0;
|
||||
ring->rx_pending = rx_ring->count;
|
||||
ring->tx_pending = tx_ring->count;
|
||||
ring->rx_mini_pending = 0;
|
||||
ring->rx_jumbo_pending = 0;
|
||||
}
|
||||
|
||||
static int igbvf_set_ringparam(struct net_device *netdev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct igbvf_ring *temp_ring;
|
||||
int err;
|
||||
u32 new_rx_count, new_tx_count;
|
||||
|
||||
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
|
||||
return -EINVAL;
|
||||
|
||||
new_rx_count = max(ring->rx_pending, (u32)IGBVF_MIN_RXD);
|
||||
new_rx_count = min(new_rx_count, (u32)IGBVF_MAX_RXD);
|
||||
new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
|
||||
new_tx_count = max(ring->tx_pending, (u32)IGBVF_MIN_TXD);
|
||||
new_tx_count = min(new_tx_count, (u32)IGBVF_MAX_TXD);
|
||||
new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
|
||||
if ((new_tx_count == adapter->tx_ring->count) &&
|
||||
(new_rx_count == adapter->rx_ring->count)) {
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp_ring = vmalloc(sizeof(struct igbvf_ring));
|
||||
if (!temp_ring)
|
||||
return -ENOMEM;
|
||||
|
||||
while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
|
||||
msleep(1);
|
||||
|
||||
if (netif_running(adapter->netdev))
|
||||
igbvf_down(adapter);
|
||||
|
||||
/*
|
||||
* We can't just free everything and then setup again,
|
||||
* because the ISRs in MSI-X mode get passed pointers
|
||||
* to the tx and rx ring structs.
|
||||
*/
|
||||
if (new_tx_count != adapter->tx_ring->count) {
|
||||
memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
|
||||
|
||||
temp_ring->count = new_tx_count;
|
||||
err = igbvf_setup_tx_resources(adapter, temp_ring);
|
||||
if (err)
|
||||
goto err_setup;
|
||||
|
||||
igbvf_free_tx_resources(adapter->tx_ring);
|
||||
|
||||
memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
|
||||
}
|
||||
|
||||
if (new_rx_count != adapter->rx_ring->count) {
|
||||
memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
|
||||
|
||||
temp_ring->count = new_rx_count;
|
||||
err = igbvf_setup_rx_resources(adapter, temp_ring);
|
||||
if (err)
|
||||
goto err_setup;
|
||||
|
||||
igbvf_free_rx_resources(adapter->rx_ring);
|
||||
|
||||
memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
|
||||
}
|
||||
|
||||
err = 0;
|
||||
err_setup:
|
||||
if (netif_running(adapter->netdev))
|
||||
igbvf_up(adapter);
|
||||
|
||||
clear_bit(__IGBVF_RESETTING, &adapter->state);
|
||||
vfree(temp_ring);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
*data = 0;
|
||||
|
||||
hw->mac.ops.check_for_link(hw);
|
||||
|
||||
if (!(er32(STATUS) & E1000_STATUS_LU))
|
||||
*data = 1;
|
||||
|
||||
return *data;
|
||||
}
|
||||
|
||||
static int igbvf_get_self_test_count(struct net_device *netdev)
|
||||
{
|
||||
return IGBVF_TEST_LEN;
|
||||
}
|
||||
|
||||
static int igbvf_get_stats_count(struct net_device *netdev)
|
||||
{
|
||||
return IGBVF_GLOBAL_STATS_LEN;
|
||||
}
|
||||
|
||||
static void igbvf_diag_test(struct net_device *netdev,
|
||||
struct ethtool_test *eth_test, u64 *data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
set_bit(__IGBVF_TESTING, &adapter->state);
|
||||
|
||||
/*
|
||||
* Link test performed before hardware reset so autoneg doesn't
|
||||
* interfere with test result
|
||||
*/
|
||||
if (igbvf_link_test(adapter, &data[0]))
|
||||
eth_test->flags |= ETH_TEST_FL_FAILED;
|
||||
|
||||
clear_bit(__IGBVF_TESTING, &adapter->state);
|
||||
msleep_interruptible(4 * 1000);
|
||||
}
|
||||
|
||||
static void igbvf_get_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int igbvf_set_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int igbvf_phys_id(struct net_device *netdev, u32 data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_get_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (adapter->itr_setting <= 3)
|
||||
ec->rx_coalesce_usecs = adapter->itr_setting;
|
||||
else
|
||||
ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_set_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) ||
|
||||
((ec->rx_coalesce_usecs > 3) &&
|
||||
(ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) ||
|
||||
(ec->rx_coalesce_usecs == 2))
|
||||
return -EINVAL;
|
||||
|
||||
/* convert to rate of irq's per second */
|
||||
if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
|
||||
adapter->itr = IGBVF_START_ITR;
|
||||
adapter->itr_setting = ec->rx_coalesce_usecs;
|
||||
} else {
|
||||
adapter->itr = ec->rx_coalesce_usecs << 2;
|
||||
adapter->itr_setting = adapter->itr;
|
||||
}
|
||||
|
||||
writel(adapter->itr,
|
||||
hw->hw_addr + adapter->rx_ring[0].itr_register);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igbvf_nway_reset(struct net_device *netdev)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
if (netif_running(netdev))
|
||||
igbvf_reinit_locked(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void igbvf_get_ethtool_stats(struct net_device *netdev,
|
||||
struct ethtool_stats *stats,
|
||||
u64 *data)
|
||||
{
|
||||
struct igbvf_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
igbvf_update_stats(adapter);
|
||||
for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
|
||||
char *p = (char *)adapter +
|
||||
igbvf_gstrings_stats[i].stat_offset;
|
||||
char *b = (char *)adapter +
|
||||
igbvf_gstrings_stats[i].base_stat_offset;
|
||||
data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
|
||||
sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
|
||||
(*(u32 *)p - *(u32 *)b));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
|
||||
u8 *data)
|
||||
{
|
||||
u8 *p = data;
|
||||
int i;
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_TEST:
|
||||
memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
|
||||
break;
|
||||
case ETH_SS_STATS:
|
||||
for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
|
||||
memcpy(p, igbvf_gstrings_stats[i].stat_string,
|
||||
ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ethtool_ops igbvf_ethtool_ops = {
|
||||
.get_settings = igbvf_get_settings,
|
||||
.set_settings = igbvf_set_settings,
|
||||
.get_drvinfo = igbvf_get_drvinfo,
|
||||
.get_regs_len = igbvf_get_regs_len,
|
||||
.get_regs = igbvf_get_regs,
|
||||
.get_wol = igbvf_get_wol,
|
||||
.set_wol = igbvf_set_wol,
|
||||
.get_msglevel = igbvf_get_msglevel,
|
||||
.set_msglevel = igbvf_set_msglevel,
|
||||
.nway_reset = igbvf_nway_reset,
|
||||
.get_link = igbvf_get_link,
|
||||
.get_eeprom_len = igbvf_get_eeprom_len,
|
||||
.get_eeprom = igbvf_get_eeprom,
|
||||
.set_eeprom = igbvf_set_eeprom,
|
||||
.get_ringparam = igbvf_get_ringparam,
|
||||
.set_ringparam = igbvf_set_ringparam,
|
||||
.get_pauseparam = igbvf_get_pauseparam,
|
||||
.set_pauseparam = igbvf_set_pauseparam,
|
||||
.get_tx_csum = igbvf_get_tx_csum,
|
||||
.set_tx_csum = igbvf_set_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.set_sg = ethtool_op_set_sg,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = igbvf_set_tso,
|
||||
.self_test = igbvf_diag_test,
|
||||
.get_strings = igbvf_get_strings,
|
||||
.phys_id = igbvf_phys_id,
|
||||
.get_ethtool_stats = igbvf_get_ethtool_stats,
|
||||
.self_test_count = igbvf_get_self_test_count,
|
||||
.get_stats_count = igbvf_get_stats_count,
|
||||
.get_coalesce = igbvf_get_coalesce,
|
||||
.set_coalesce = igbvf_set_coalesce,
|
||||
};
|
||||
|
||||
void igbvf_set_ethtool_ops(struct net_device *netdev)
|
||||
{
|
||||
/* have to "undeclare" const on this struct to remove warnings */
|
||||
SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
|
||||
}
|
335
drivers/net/igbvf/igbvf.h
Normal file
335
drivers/net/igbvf/igbvf.h
Normal file
@ -0,0 +1,335 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _IGBVF_H_
|
||||
#define _IGBVF_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
|
||||
#include "vf.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct igbvf_info;
|
||||
struct igbvf_adapter;
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGBVF_START_ITR 648 /* ~6000 ints/sec */
|
||||
|
||||
/* Interrupt modes, as used by the IntMode paramter */
|
||||
#define IGBVF_INT_MODE_LEGACY 0
|
||||
#define IGBVF_INT_MODE_MSI 1
|
||||
#define IGBVF_INT_MODE_MSIX 2
|
||||
|
||||
/* Tx/Rx descriptor defines */
|
||||
#define IGBVF_DEFAULT_TXD 256
|
||||
#define IGBVF_MAX_TXD 4096
|
||||
#define IGBVF_MIN_TXD 80
|
||||
|
||||
#define IGBVF_DEFAULT_RXD 256
|
||||
#define IGBVF_MAX_RXD 4096
|
||||
#define IGBVF_MIN_RXD 80
|
||||
|
||||
#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* RX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGBVF_RX_PTHRESH 16
|
||||
#define IGBVF_RX_HTHRESH 8
|
||||
#define IGBVF_RX_WTHRESH 1
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
#define IGBVF_FC_PAUSE_TIME 0x0680 /* 858 usec */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define IGBVF_TX_QUEUE_WAKE 32
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGBVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGBVF_EEPROM_APME 0x0400
|
||||
|
||||
#define IGBVF_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* Number of packet split data buffers (not including the header buffer) */
|
||||
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
|
||||
|
||||
enum igbvf_boards {
|
||||
board_vf,
|
||||
};
|
||||
|
||||
struct igbvf_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
* wrappers around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igbvf_buffer {
|
||||
dma_addr_t dma;
|
||||
struct sk_buff *skb;
|
||||
union {
|
||||
/* Tx */
|
||||
struct {
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
};
|
||||
/* Rx */
|
||||
struct {
|
||||
struct page *page;
|
||||
u64 page_dma;
|
||||
unsigned int page_offset;
|
||||
};
|
||||
};
|
||||
struct page *page;
|
||||
};
|
||||
|
||||
union igbvf_desc {
|
||||
union e1000_adv_rx_desc rx_desc;
|
||||
union e1000_adv_tx_desc tx_desc;
|
||||
struct e1000_adv_tx_context_desc tx_context_desc;
|
||||
};
|
||||
|
||||
struct igbvf_ring {
|
||||
struct igbvf_adapter *adapter; /* backlink */
|
||||
union igbvf_desc *desc; /* pointer to ring memory */
|
||||
dma_addr_t dma; /* phys address of ring */
|
||||
unsigned int size; /* length of ring in bytes */
|
||||
unsigned int count; /* number of desc. in ring */
|
||||
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
u16 head;
|
||||
u16 tail;
|
||||
|
||||
/* array of buffer information structs */
|
||||
struct igbvf_buffer *buffer_info;
|
||||
struct napi_struct napi;
|
||||
|
||||
char name[IFNAMSIZ + 5];
|
||||
u32 eims_value;
|
||||
u32 itr_val;
|
||||
u16 itr_register;
|
||||
int set_itr;
|
||||
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
struct igbvf_queue_stats stats;
|
||||
};
|
||||
|
||||
/* board specific private data structure */
|
||||
struct igbvf_adapter {
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list blink_timer;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
|
||||
const struct igbvf_info *ei;
|
||||
|
||||
struct vlan_group *vlgrp;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 polling_interval;
|
||||
u16 mng_vlan_id;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
|
||||
|
||||
/* track device up/down/testing state */
|
||||
unsigned long state;
|
||||
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
/*
|
||||
* Tx
|
||||
*/
|
||||
struct igbvf_ring *tx_ring /* One per active queue */
|
||||
____cacheline_aligned_in_smp;
|
||||
|
||||
unsigned long tx_queue_len;
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
|
||||
bool detect_tx_hung;
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
|
||||
/* Tx stats */
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u32 tx_dma_failed;
|
||||
|
||||
/*
|
||||
* Rx
|
||||
*/
|
||||
struct igbvf_ring *rx_ring;
|
||||
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
|
||||
/* Rx stats */
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u64 rx_hdr_split;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_dma_failed;
|
||||
|
||||
unsigned int rx_ps_hdr_size;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
spinlock_t stats_lock; /* prevent concurrent stats updates */
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
|
||||
/* The VF counters don't clear on read so we have to get a base
|
||||
* count on driver start up and always subtract that base on
|
||||
* on the first update, thus the flag..
|
||||
*/
|
||||
struct e1000_vf_stats stats;
|
||||
u64 zero_base;
|
||||
|
||||
struct igbvf_ring test_tx_ring;
|
||||
struct igbvf_ring test_rx_ring;
|
||||
u32 test_icr;
|
||||
|
||||
u32 msg_enable;
|
||||
struct msix_entry *msix_entries;
|
||||
int int_mode;
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
u32 int_counter0;
|
||||
u32 int_counter1;
|
||||
|
||||
u32 eeprom_wol;
|
||||
u32 wol;
|
||||
u32 pba;
|
||||
|
||||
bool fc_autoneg;
|
||||
|
||||
unsigned long led_status;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct igbvf_info {
|
||||
enum e1000_mac_type mac;
|
||||
unsigned int flags;
|
||||
u32 pba;
|
||||
void (*init_ops)(struct e1000_hw *);
|
||||
s32 (*get_variants)(struct igbvf_adapter *);
|
||||
};
|
||||
|
||||
/* hardware capability, feature, and workaround flags */
|
||||
#define FLAG_HAS_HW_VLAN_FILTER (1 << 0)
|
||||
#define FLAG_HAS_JUMBO_FRAMES (1 << 1)
|
||||
#define FLAG_MSI_ENABLED (1 << 2)
|
||||
#define FLAG_RX_CSUM_ENABLED (1 << 3)
|
||||
#define FLAG_TSO_FORCE (1 << 4)
|
||||
|
||||
#define IGBVF_RX_DESC_ADV(R, i) \
|
||||
(&((((R).desc))[i].rx_desc))
|
||||
#define IGBVF_TX_DESC_ADV(R, i) \
|
||||
(&((((R).desc))[i].tx_desc))
|
||||
#define IGBVF_TX_CTXTDESC_ADV(R, i) \
|
||||
(&((((R).desc))[i].tx_context_desc))
|
||||
|
||||
enum igbvf_state_t {
|
||||
__IGBVF_TESTING,
|
||||
__IGBVF_RESETTING,
|
||||
__IGBVF_DOWN
|
||||
};
|
||||
|
||||
enum latency_range {
|
||||
lowest_latency = 0,
|
||||
low_latency = 1,
|
||||
bulk_latency = 2,
|
||||
latency_invalid = 255
|
||||
};
|
||||
|
||||
extern char igbvf_driver_name[];
|
||||
extern const char igbvf_driver_version[];
|
||||
|
||||
extern void igbvf_check_options(struct igbvf_adapter *);
|
||||
extern void igbvf_set_ethtool_ops(struct net_device *);
|
||||
|
||||
extern int igbvf_up(struct igbvf_adapter *);
|
||||
extern void igbvf_down(struct igbvf_adapter *);
|
||||
extern void igbvf_reinit_locked(struct igbvf_adapter *);
|
||||
extern void igbvf_reset(struct igbvf_adapter *);
|
||||
extern int igbvf_setup_rx_resources(struct igbvf_adapter *, struct igbvf_ring *);
|
||||
extern int igbvf_setup_tx_resources(struct igbvf_adapter *, struct igbvf_ring *);
|
||||
extern void igbvf_free_rx_resources(struct igbvf_ring *);
|
||||
extern void igbvf_free_tx_resources(struct igbvf_ring *);
|
||||
extern void igbvf_update_stats(struct igbvf_adapter *);
|
||||
extern void igbvf_set_interrupt_capability(struct igbvf_adapter *);
|
||||
extern void igbvf_reset_interrupt_capability(struct igbvf_adapter *);
|
||||
|
||||
extern unsigned int copybreak;
|
||||
|
||||
#endif /* _IGBVF_H_ */
|
350
drivers/net/igbvf/mbx.c
Normal file
350
drivers/net/igbvf/mbx.c
Normal file
@ -0,0 +1,350 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "mbx.h"
|
||||
|
||||
/**
|
||||
* e1000_poll_for_msg - Wait for message notification
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification
|
||||
**/
|
||||
static s32 e1000_poll_for_msg(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!mbx->ops.check_for_msg)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_msg(hw)) {
|
||||
countdown--;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_poll_for_ack - Wait for message acknowledgement
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message acknowledgement
|
||||
**/
|
||||
static s32 e1000_poll_for_ack(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
int countdown = mbx->timeout;
|
||||
|
||||
if (!mbx->ops.check_for_ack)
|
||||
goto out;
|
||||
|
||||
while (countdown && mbx->ops.check_for_ack(hw)) {
|
||||
countdown--;
|
||||
udelay(mbx->usec_delay);
|
||||
}
|
||||
|
||||
/* if we failed, all future posted messages fail until reset */
|
||||
if (!countdown)
|
||||
mbx->timeout = 0;
|
||||
out:
|
||||
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_posted_mbx - Wait for message notification and receive message
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
*
|
||||
* returns SUCCESS if it successfully received a message notification and
|
||||
* copied it into the receive buffer.
|
||||
**/
|
||||
static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!mbx->ops.read)
|
||||
goto out;
|
||||
|
||||
ret_val = e1000_poll_for_msg(hw);
|
||||
|
||||
/* if ack received read message, otherwise we timed out */
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read(hw, msg, size);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer and
|
||||
* received an ack to that message within delay * timeout period
|
||||
**/
|
||||
static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* exit if we either can't write or there isn't a defined timeout */
|
||||
if (!mbx->ops.write || !mbx->timeout)
|
||||
goto out;
|
||||
|
||||
/* send msg*/
|
||||
ret_val = mbx->ops.write(hw, msg, size);
|
||||
|
||||
/* if msg sent wait until we receive an ack */
|
||||
if (!ret_val)
|
||||
ret_val = e1000_poll_for_ack(hw);
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_v2p_mailbox - read v2p mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function is used to read the v2p mailbox without losing the read to
|
||||
* clear status bits.
|
||||
**/
|
||||
static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
|
||||
{
|
||||
u32 v2p_mailbox = er32(V2PMAILBOX(0));
|
||||
|
||||
v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
|
||||
hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
|
||||
|
||||
return v2p_mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_bit_vf - Determine if a status bit was set
|
||||
* @hw: pointer to the HW structure
|
||||
* @mask: bitmask for bits to be tested and cleared
|
||||
*
|
||||
* This function is used to check for the read to clear bits within
|
||||
* the V2P mailbox.
|
||||
**/
|
||||
static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
|
||||
{
|
||||
u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (v2p_mailbox & mask)
|
||||
ret_val = E1000_SUCCESS;
|
||||
|
||||
hw->dev_spec.vf.v2p_mailbox &= ~mask;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_msg_vf - checks to see if the PF has sent mail
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if the PF has set the Status bit or else ERR_MBX
|
||||
**/
|
||||
static s32 e1000_check_for_msg_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.reqs++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_ack_vf - checks to see if the PF has ACK'd
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
|
||||
**/
|
||||
static s32 e1000_check_for_ack_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.acks++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_rst_vf - checks to see if the PF has reset
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* returns true if the PF has set the reset done bit or else false
|
||||
**/
|
||||
static s32 e1000_check_for_rst_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
|
||||
E1000_V2PMAILBOX_RSTI))) {
|
||||
ret_val = E1000_SUCCESS;
|
||||
hw->mbx.stats.rsts++;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_obtain_mbx_lock_vf - obtain mailbox lock
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* return SUCCESS if we obtained the mailbox lock
|
||||
**/
|
||||
static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
|
||||
{
|
||||
s32 ret_val = -E1000_ERR_MBX;
|
||||
|
||||
/* Take ownership of the buffer */
|
||||
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
|
||||
|
||||
/* reserve mailbox for vf use */
|
||||
if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
|
||||
ret_val = E1000_SUCCESS;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_write_mbx_vf - Write a message to the mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
*
|
||||
* returns SUCCESS if it successfully copied message into the buffer
|
||||
**/
|
||||
static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
s32 err;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
err = e1000_obtain_mbx_lock_vf(hw);
|
||||
if (err)
|
||||
goto out_no_write;
|
||||
|
||||
/* flush any ack or msg as we are going to overwrite mailbox */
|
||||
e1000_check_for_ack_vf(hw);
|
||||
e1000_check_for_msg_vf(hw);
|
||||
|
||||
/* copy the caller specified message to the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
array_ew32(VMBMEM(0), i, msg[i]);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_tx++;
|
||||
|
||||
/* Drop VFU and interrupt the PF to tell it a message has been sent */
|
||||
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
|
||||
|
||||
out_no_write:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_mbx_vf - Reads a message from the inbox intended for vf
|
||||
* @hw: pointer to the HW structure
|
||||
* @msg: The message buffer
|
||||
* @size: Length of buffer
|
||||
*
|
||||
* returns SUCCESS if it successfuly read message from buffer
|
||||
**/
|
||||
static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
|
||||
{
|
||||
s32 err;
|
||||
u16 i;
|
||||
|
||||
/* lock the mailbox to prevent pf/vf race condition */
|
||||
err = e1000_obtain_mbx_lock_vf(hw);
|
||||
if (err)
|
||||
goto out_no_read;
|
||||
|
||||
/* copy the message from the mailbox memory buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
msg[i] = array_er32(VMBMEM(0), i);
|
||||
|
||||
/* Acknowledge receipt and release mailbox, then we're done */
|
||||
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
|
||||
|
||||
/* update stats */
|
||||
hw->mbx.stats.msgs_rx++;
|
||||
|
||||
out_no_read:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_mbx_params_vf - set initial values for vf mailbox
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Initializes the hw->mbx struct to correct values for vf mailbox
|
||||
*/
|
||||
s32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
|
||||
/* start mailbox as timed out and let the reset_hw call set the timeout
|
||||
* value to being communications */
|
||||
mbx->timeout = 0;
|
||||
mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
|
||||
|
||||
mbx->size = E1000_VFMAILBOX_SIZE;
|
||||
|
||||
mbx->ops.read = e1000_read_mbx_vf;
|
||||
mbx->ops.write = e1000_write_mbx_vf;
|
||||
mbx->ops.read_posted = e1000_read_posted_mbx;
|
||||
mbx->ops.write_posted = e1000_write_posted_mbx;
|
||||
mbx->ops.check_for_msg = e1000_check_for_msg_vf;
|
||||
mbx->ops.check_for_ack = e1000_check_for_ack_vf;
|
||||
mbx->ops.check_for_rst = e1000_check_for_rst_vf;
|
||||
|
||||
mbx->stats.msgs_tx = 0;
|
||||
mbx->stats.msgs_rx = 0;
|
||||
mbx->stats.reqs = 0;
|
||||
mbx->stats.acks = 0;
|
||||
mbx->stats.rsts = 0;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
75
drivers/net/igbvf/mbx.h
Normal file
75
drivers/net/igbvf/mbx.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 1999 - 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_MBX_H_
|
||||
#define _E1000_MBX_H_
|
||||
|
||||
#include "vf.h"
|
||||
|
||||
#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
|
||||
#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
|
||||
#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
|
||||
#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
|
||||
#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
|
||||
#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
|
||||
#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
|
||||
#define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
|
||||
#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
|
||||
|
||||
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
|
||||
|
||||
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
|
||||
* PF. The reverse is true if it is E1000_PF_*.
|
||||
* Message ACK's are the value or'd with 0xF0000000
|
||||
*/
|
||||
#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
|
||||
* this are the ACK */
|
||||
#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
|
||||
* this are the NACK */
|
||||
#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
|
||||
clear to send requests */
|
||||
|
||||
/* We have a total wait time of 1s for vf mailbox posted messages */
|
||||
#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* retry count for mailbox timeout */
|
||||
#define E1000_VF_MBX_INIT_DELAY 500 /* usec delay between retries */
|
||||
|
||||
#define E1000_VT_MSGINFO_SHIFT 16
|
||||
/* bits 23:16 are used for exra info for certain messages */
|
||||
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
|
||||
|
||||
#define E1000_VF_RESET 0x01 /* VF requests reset */
|
||||
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */
|
||||
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */
|
||||
#define E1000_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */
|
||||
#define E1000_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
|
||||
|
||||
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
|
||||
|
||||
void e1000_init_mbx_ops_generic(struct e1000_hw *hw);
|
||||
s32 e1000_init_mbx_params_vf(struct e1000_hw *);
|
||||
|
||||
#endif /* _E1000_MBX_H_ */
|
2919
drivers/net/igbvf/netdev.c
Normal file
2919
drivers/net/igbvf/netdev.c
Normal file
File diff suppressed because it is too large
Load Diff
108
drivers/net/igbvf/regs.h
Normal file
108
drivers/net/igbvf/regs.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_REGS_H_
|
||||
#define _E1000_REGS_H_
|
||||
|
||||
#define E1000_CTRL 0x00000 /* Device Control - RW */
|
||||
#define E1000_STATUS 0x00008 /* Device Status - RO */
|
||||
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
|
||||
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
|
||||
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
|
||||
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
|
||||
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
|
||||
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
|
||||
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
|
||||
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
|
||||
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
|
||||
/*
|
||||
* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* E1000_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
|
||||
(0x0C000 + ((_n) * 0x40)))
|
||||
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
|
||||
(0x0C004 + ((_n) * 0x40)))
|
||||
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
|
||||
(0x0C008 + ((_n) * 0x40)))
|
||||
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
|
||||
(0x0C00C + ((_n) * 0x40)))
|
||||
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
|
||||
(0x0C010 + ((_n) * 0x40)))
|
||||
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
|
||||
(0x0C018 + ((_n) * 0x40)))
|
||||
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
|
||||
(0x0C028 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
|
||||
(0x0E000 + ((_n) * 0x40)))
|
||||
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
|
||||
(0x0E004 + ((_n) * 0x40)))
|
||||
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
|
||||
(0x0E008 + ((_n) * 0x40)))
|
||||
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
|
||||
(0x0E010 + ((_n) * 0x40)))
|
||||
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
|
||||
(0x0E018 + ((_n) * 0x40)))
|
||||
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
|
||||
(0x0E028 + ((_n) * 0x40)))
|
||||
#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
|
||||
#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
|
||||
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
|
||||
/* Statistics registers */
|
||||
#define E1000_VFGPRC 0x00F10
|
||||
#define E1000_VFGORC 0x00F18
|
||||
#define E1000_VFMPRC 0x00F3C
|
||||
#define E1000_VFGPTC 0x00F14
|
||||
#define E1000_VFGOTC 0x00F34
|
||||
#define E1000_VFGOTLBC 0x00F50
|
||||
#define E1000_VFGPTLBC 0x00F44
|
||||
#define E1000_VFGORLBC 0x00F48
|
||||
#define E1000_VFGPRLBC 0x00F40
|
||||
|
||||
/* These act per VF so an array friendly macro is used */
|
||||
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
|
||||
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
|
||||
|
||||
/* Define macros for handling registers */
|
||||
#define er32(reg) readl(hw->hw_addr + E1000_##reg)
|
||||
#define ew32(reg, val) writel((val), hw->hw_addr + E1000_##reg)
|
||||
#define array_er32(reg, offset) \
|
||||
readl(hw->hw_addr + E1000_##reg + (offset << 2))
|
||||
#define array_ew32(reg, offset, val) \
|
||||
writel((val), hw->hw_addr + E1000_##reg + (offset << 2))
|
||||
#define e1e_flush() er32(STATUS)
|
||||
|
||||
#endif
|
398
drivers/net/igbvf/vf.c
Normal file
398
drivers/net/igbvf/vf.c
Normal file
@ -0,0 +1,398 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#include "vf.h"
|
||||
|
||||
static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
|
||||
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
static s32 e1000_init_hw_vf(struct e1000_hw *hw);
|
||||
static s32 e1000_reset_hw_vf(struct e1000_hw *hw);
|
||||
|
||||
static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *,
|
||||
u32, u32, u32);
|
||||
static void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32);
|
||||
static s32 e1000_read_mac_addr_vf(struct e1000_hw *);
|
||||
static s32 e1000_set_vfta_vf(struct e1000_hw *, u16, bool);
|
||||
|
||||
/**
|
||||
* e1000_init_mac_params_vf - Inits MAC params
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
s32 e1000_init_mac_params_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
|
||||
/* VF's have no MTA Registers - PF feature only */
|
||||
mac->mta_reg_count = 128;
|
||||
/* VF's have no access to RAR entries */
|
||||
mac->rar_entry_count = 1;
|
||||
|
||||
/* Function pointers */
|
||||
/* reset */
|
||||
mac->ops.reset_hw = e1000_reset_hw_vf;
|
||||
/* hw initialization */
|
||||
mac->ops.init_hw = e1000_init_hw_vf;
|
||||
/* check for link */
|
||||
mac->ops.check_for_link = e1000_check_for_link_vf;
|
||||
/* link info */
|
||||
mac->ops.get_link_up_info = e1000_get_link_up_info_vf;
|
||||
/* multicast address update */
|
||||
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_vf;
|
||||
/* set mac address */
|
||||
mac->ops.rar_set = e1000_rar_set_vf;
|
||||
/* read mac address */
|
||||
mac->ops.read_mac_addr = e1000_read_mac_addr_vf;
|
||||
/* set vlan filter table array */
|
||||
mac->ops.set_vfta = e1000_set_vfta_vf;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_function_pointers_vf - Inits function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
void e1000_init_function_pointers_vf(struct e1000_hw *hw)
|
||||
{
|
||||
hw->mac.ops.init_params = e1000_init_mac_params_vf;
|
||||
hw->mbx.ops.init_params = e1000_init_mbx_params_vf;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_get_link_up_info_vf - Gets link info.
|
||||
* @hw: pointer to the HW structure
|
||||
* @speed: pointer to 16 bit value to store link speed.
|
||||
* @duplex: pointer to 16 bit value to store duplex.
|
||||
*
|
||||
* Since we cannot read the PHY and get accurate link info, we must rely upon
|
||||
* the status register's data which is often stale and inaccurate.
|
||||
**/
|
||||
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
|
||||
u16 *duplex)
|
||||
{
|
||||
s32 status;
|
||||
|
||||
status = er32(STATUS);
|
||||
if (status & E1000_STATUS_SPEED_1000)
|
||||
*speed = SPEED_1000;
|
||||
else if (status & E1000_STATUS_SPEED_100)
|
||||
*speed = SPEED_100;
|
||||
else
|
||||
*speed = SPEED_10;
|
||||
|
||||
if (status & E1000_STATUS_FD)
|
||||
*duplex = FULL_DUPLEX;
|
||||
else
|
||||
*duplex = HALF_DUPLEX;
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_reset_hw_vf - Resets the HW
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
|
||||
* This is all the reset we can perform on a VF.
|
||||
**/
|
||||
static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 timeout = E1000_VF_INIT_TIMEOUT;
|
||||
u32 ret_val = -E1000_ERR_MAC_INIT;
|
||||
u32 msgbuf[3];
|
||||
u8 *addr = (u8 *)(&msgbuf[1]);
|
||||
u32 ctrl;
|
||||
|
||||
/* assert vf queue/interrupt reset */
|
||||
ctrl = er32(CTRL);
|
||||
ew32(CTRL, ctrl | E1000_CTRL_RST);
|
||||
|
||||
/* we cannot initialize while the RSTI / RSTD bits are asserted */
|
||||
while (!mbx->ops.check_for_rst(hw) && timeout) {
|
||||
timeout--;
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
/* mailbox timeout can now become active */
|
||||
mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
|
||||
|
||||
/* notify pf of vf reset completion */
|
||||
msgbuf[0] = E1000_VF_RESET;
|
||||
mbx->ops.write_posted(hw, msgbuf, 1);
|
||||
|
||||
msleep(10);
|
||||
|
||||
/* set our "perm_addr" based on info provided by PF */
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
|
||||
if (!ret_val) {
|
||||
if (msgbuf[0] == (E1000_VF_RESET | E1000_VT_MSGTYPE_ACK))
|
||||
memcpy(hw->mac.perm_addr, addr, 6);
|
||||
else
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_init_hw_vf - Inits the HW
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Not much to do here except clear the PF Reset indication if there is one.
|
||||
**/
|
||||
static s32 e1000_init_hw_vf(struct e1000_hw *hw)
|
||||
{
|
||||
/* attempt to set and restore our mac address */
|
||||
e1000_rar_set_vf(hw, hw->mac.addr, 0);
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_hash_mc_addr_vf - Generate a multicast hash value
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr: pointer to a multicast address
|
||||
*
|
||||
* Generates a multicast address hash value which is used to determine
|
||||
* the multicast filter table array address and new table value. See
|
||||
* e1000_mta_set_generic()
|
||||
**/
|
||||
static u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
|
||||
{
|
||||
u32 hash_value, hash_mask;
|
||||
u8 bit_shift = 0;
|
||||
|
||||
/* Register count multiplied by bits per register */
|
||||
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
|
||||
|
||||
/*
|
||||
* The bit_shift is the number of left-shifts
|
||||
* where 0xFF would still fall within the hash mask.
|
||||
*/
|
||||
while (hash_mask >> bit_shift != 0xFF)
|
||||
bit_shift++;
|
||||
|
||||
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
|
||||
(((u16) mc_addr[5]) << bit_shift)));
|
||||
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_update_mc_addr_list_vf - Update Multicast addresses
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr_list: array of multicast addresses to program
|
||||
* @mc_addr_count: number of multicast addresses to program
|
||||
* @rar_used_count: the first RAR register free to program
|
||||
* @rar_count: total number of supported Receive Address Registers
|
||||
*
|
||||
* Updates the Receive Address Registers and Multicast Table Array.
|
||||
* The caller must have a packed mc_addr_list of multicast addresses.
|
||||
* The parameter rar_count will usually be hw->mac.rar_entry_count
|
||||
* unless there are workarounds that change this.
|
||||
**/
|
||||
void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count,
|
||||
u32 rar_used_count, u32 rar_count)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[E1000_VFMAILBOX_SIZE];
|
||||
u16 *hash_list = (u16 *)&msgbuf[1];
|
||||
u32 hash_value;
|
||||
u32 cnt, i;
|
||||
|
||||
/* Each entry in the list uses 1 16 bit word. We have 30
|
||||
* 16 bit words available in our HW msg buffer (minus 1 for the
|
||||
* msg type). That's 30 hash values if we pack 'em right. If
|
||||
* there are more than 30 MC addresses to add then punt the
|
||||
* extras for now and then add code to handle more than 30 later.
|
||||
* It would be unusual for a server to request that many multi-cast
|
||||
* addresses except for in large enterprise network environments.
|
||||
*/
|
||||
|
||||
cnt = (mc_addr_count > 30) ? 30 : mc_addr_count;
|
||||
msgbuf[0] = E1000_VF_SET_MULTICAST;
|
||||
msgbuf[0] |= cnt << E1000_VT_MSGINFO_SHIFT;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
hash_value = e1000_hash_mc_addr_vf(hw, mc_addr_list);
|
||||
hash_list[i] = hash_value & 0x0FFFF;
|
||||
mc_addr_list += ETH_ADDR_LEN;
|
||||
}
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_set_vfta_vf - Set/Unset vlan filter table address
|
||||
* @hw: pointer to the HW structure
|
||||
* @vid: determines the vfta register and bit to set/unset
|
||||
* @set: if true then set bit, else clear bit
|
||||
**/
|
||||
static s32 e1000_set_vfta_vf(struct e1000_hw *hw, u16 vid, bool set)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[2];
|
||||
s32 err;
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_VLAN;
|
||||
msgbuf[1] = vid;
|
||||
/* Setting the 8 bit field MSG INFO to true indicates "add" */
|
||||
if (set)
|
||||
msgbuf[0] |= 1 << E1000_VT_MSGINFO_SHIFT;
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, 2);
|
||||
|
||||
err = mbx->ops.read_posted(hw, msgbuf, 2);
|
||||
|
||||
/* if nacked the vlan was rejected */
|
||||
if (!err && (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK)))
|
||||
err = -E1000_ERR_MAC_INIT;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/** e1000_rlpml_set_vf - Set the maximum receive packet length
|
||||
* @hw: pointer to the HW structure
|
||||
* @max_size: value to assign to max frame size
|
||||
**/
|
||||
void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[2];
|
||||
|
||||
msgbuf[0] = E1000_VF_SET_LPE;
|
||||
msgbuf[1] = max_size;
|
||||
|
||||
mbx->ops.write_posted(hw, msgbuf, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_rar_set_vf - set device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: pointer to the receive address
|
||||
* @index receive address array register
|
||||
**/
|
||||
static void e1000_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
u32 msgbuf[3];
|
||||
u8 *msg_addr = (u8 *)(&msgbuf[1]);
|
||||
s32 ret_val;
|
||||
|
||||
memset(msgbuf, 0, 12);
|
||||
msgbuf[0] = E1000_VF_SET_MAC_ADDR;
|
||||
memcpy(msg_addr, addr, 6);
|
||||
ret_val = mbx->ops.write_posted(hw, msgbuf, 3);
|
||||
|
||||
if (!ret_val)
|
||||
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
|
||||
|
||||
/* if nacked the address was rejected, use "perm_addr" */
|
||||
if (!ret_val &&
|
||||
(msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
|
||||
e1000_read_mac_addr_vf(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_read_mac_addr_vf - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
static s32 e1000_read_mac_addr_vf(struct e1000_hw *hw)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return E1000_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_for_link_vf - Check for link for a virtual interface
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Checks to see if the underlying PF is still talking to the VF and
|
||||
* if it is then it reports the link state to the hardware, otherwise
|
||||
* it reports link down and returns an error.
|
||||
**/
|
||||
static s32 e1000_check_for_link_vf(struct e1000_hw *hw)
|
||||
{
|
||||
struct e1000_mbx_info *mbx = &hw->mbx;
|
||||
struct e1000_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = E1000_SUCCESS;
|
||||
u32 in_msg = 0;
|
||||
|
||||
/*
|
||||
* We only want to run this if there has been a rst asserted.
|
||||
* in this case that could mean a link change, device reset,
|
||||
* or a virtual function reset
|
||||
*/
|
||||
|
||||
/* If we were hit with a reset drop the link */
|
||||
if (!mbx->ops.check_for_rst(hw))
|
||||
mac->get_link_status = true;
|
||||
|
||||
if (!mac->get_link_status)
|
||||
goto out;
|
||||
|
||||
/* if link status is down no point in checking to see if pf is up */
|
||||
if (!(er32(STATUS) & E1000_STATUS_LU))
|
||||
goto out;
|
||||
|
||||
/* if the read failed it could just be a mailbox collision, best wait
|
||||
* until we are called again and don't report an error */
|
||||
if (mbx->ops.read(hw, &in_msg, 1))
|
||||
goto out;
|
||||
|
||||
/* if incoming message isn't clear to send we are waiting on response */
|
||||
if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
|
||||
/* message is not CTS and is NACK we must have lost CTS status */
|
||||
if (in_msg & E1000_VT_MSGTYPE_NACK)
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* the pf is talking, if we timed out in the past we reinit */
|
||||
if (!mbx->timeout) {
|
||||
ret_val = -E1000_ERR_MAC_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if we passed all the tests above then the link is up and we no
|
||||
* longer need to check for link */
|
||||
mac->get_link_status = false;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
265
drivers/net/igbvf/vf.h
Normal file
265
drivers/net/igbvf/vf.h
Normal file
@ -0,0 +1,265 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Intel(R) 82576 Virtual Function Linux driver
|
||||
Copyright(c) 2009 Intel Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in
|
||||
the file called "COPYING".
|
||||
|
||||
Contact Information:
|
||||
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _E1000_VF_H_
|
||||
#define _E1000_VF_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "regs.h"
|
||||
#include "defines.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82576_VF 0x10CA
|
||||
#define E1000_REVISION_0 0
|
||||
#define E1000_REVISION_1 1
|
||||
#define E1000_REVISION_2 2
|
||||
#define E1000_REVISION_3 3
|
||||
#define E1000_REVISION_4 4
|
||||
|
||||
#define E1000_FUNC_0 0
|
||||
#define E1000_FUNC_1 1
|
||||
|
||||
/*
|
||||
* Receive Address Register Count
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* These entries are also used for MAC-based filtering.
|
||||
*/
|
||||
#define E1000_RAR_ENTRIES_VF 1
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
u64 pkt_addr; /* Packet buffer address */
|
||||
u64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
u32 data;
|
||||
struct {
|
||||
u16 pkt_info; /* RSS/Packet type */
|
||||
u16 hdr_info; /* Split Header,
|
||||
* hdr buffer length */
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
u32 rss; /* RSS Hash */
|
||||
struct {
|
||||
u16 ip_id; /* IP id */
|
||||
u16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
u32 status_error; /* ext status/error */
|
||||
u16 length; /* Packet length */
|
||||
u16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
u64 buffer_addr; /* Address of descriptor's data buf */
|
||||
u32 cmd_type_len;
|
||||
u32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
u64 rsvd; /* Reserved */
|
||||
u32 nxtseq_seed;
|
||||
u32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
u32 vlan_macip_lens;
|
||||
u32 seqnum_seed;
|
||||
u32 type_tucmd_mlhl;
|
||||
u32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_vfadapt,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
struct e1000_vf_stats {
|
||||
u64 base_gprc;
|
||||
u64 base_gptc;
|
||||
u64 base_gorc;
|
||||
u64 base_gotc;
|
||||
u64 base_mprc;
|
||||
u64 base_gotlbc;
|
||||
u64 base_gptlbc;
|
||||
u64 base_gorlbc;
|
||||
u64 base_gprlbc;
|
||||
|
||||
u32 last_gprc;
|
||||
u32 last_gptc;
|
||||
u32 last_gorc;
|
||||
u32 last_gotc;
|
||||
u32 last_mprc;
|
||||
u32 last_gotlbc;
|
||||
u32 last_gptlbc;
|
||||
u32 last_gorlbc;
|
||||
u32 last_gprlbc;
|
||||
|
||||
u64 gprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 mprc;
|
||||
u64 gotlbc;
|
||||
u64 gptlbc;
|
||||
u64 gorlbc;
|
||||
u64 gprlbc;
|
||||
};
|
||||
|
||||
#include "mbx.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
/* Function pointers for the MAC. */
|
||||
s32 (*init_params)(struct e1000_hw *);
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
void (*clear_vfta)(struct e1000_hw *);
|
||||
s32 (*get_bus_info)(struct e1000_hw *);
|
||||
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
|
||||
void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
s32 (*setup_link)(struct e1000_hw *);
|
||||
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||
void (*mta_set)(struct e1000_hw *, u32);
|
||||
void (*rar_set)(struct e1000_hw *, u8*, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
s32 (*set_vfta)(struct e1000_hw *, u16, bool);
|
||||
};
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 rar_entry_count;
|
||||
|
||||
bool get_link_status;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*write)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*read_posted)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*write_posted)(struct e1000_hw *, u32 *, u16);
|
||||
s32 (*check_for_msg)(struct e1000_hw *);
|
||||
s32 (*check_for_ack)(struct e1000_hw *);
|
||||
s32 (*check_for_rst)(struct e1000_hw *);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_vf {
|
||||
u32 vf_number;
|
||||
u32 v2p_mailbox;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_mbx_info mbx;
|
||||
|
||||
union {
|
||||
struct e1000_dev_spec_vf vf;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
|
||||
void e1000_init_function_pointers_vf(struct e1000_hw *hw);
|
||||
s32 e1000_init_mac_params_vf(struct e1000_hw *hw);
|
||||
|
||||
|
||||
#endif /* _E1000_VF_H_ */
|
@ -2274,8 +2274,6 @@ static void port_start(struct mv643xx_eth_private *mp)
|
||||
pscr |= FORCE_LINK_PASS;
|
||||
wrlp(mp, PORT_SERIAL_CONTROL, pscr);
|
||||
|
||||
wrlp(mp, SDMA_CONFIG, PORT_SDMA_CONFIG_DEFAULT_VALUE);
|
||||
|
||||
/*
|
||||
* Configure TX path and queues.
|
||||
*/
|
||||
@ -2957,6 +2955,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
|
||||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
wrlp(mp, SDMA_CONFIG, PORT_SDMA_CONFIG_DEFAULT_VALUE);
|
||||
|
||||
set_rx_coal(mp, 250);
|
||||
set_tx_coal(mp, 0);
|
||||
|
||||
|
@ -4834,6 +4834,7 @@ static int niu_compute_rbr_cfig_b(struct rx_ring_info *rp, u64 *ret)
|
||||
{
|
||||
u64 val = 0;
|
||||
|
||||
*ret = 0;
|
||||
switch (rp->rbr_block_size) {
|
||||
case 4 * 1024:
|
||||
val |= (RBR_BLKSIZE_4K << RBR_CFIG_B_BLKSIZE_SHIFT);
|
||||
@ -9542,7 +9543,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np,
|
||||
|
||||
plat_dev = platform_device_register_simple("niu", niu_parent_index,
|
||||
NULL, 0);
|
||||
if (!plat_dev)
|
||||
if (IS_ERR(plat_dev))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; attr_name(niu_parent_attributes[i]); i++) {
|
||||
|
@ -160,6 +160,7 @@ MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>,"
|
||||
"Florian Fainelli <florian@openwrt.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver");
|
||||
MODULE_VERSION(DRV_VERSION " " DRV_RELDATE);
|
||||
|
||||
/* RX and TX interrupts that we handle */
|
||||
#define RX_INTS (RX_FIFO_FULL | RX_NO_DESC | RX_FINISH)
|
||||
|
@ -317,7 +317,7 @@ static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
|
||||
goto out;
|
||||
}
|
||||
|
||||
SMSC_WARNING(HW, "Timed out waiting for MII write to finish");
|
||||
SMSC_WARNING(HW, "Timed out waiting for MII read to finish");
|
||||
reg = -EIO;
|
||||
|
||||
out:
|
||||
|
@ -174,8 +174,7 @@ struct fujitsu_hotkey_t {
|
||||
|
||||
static struct fujitsu_hotkey_t *fujitsu_hotkey;
|
||||
|
||||
static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
|
||||
void *data);
|
||||
static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
#ifdef CONFIG_LEDS_CLASS
|
||||
static enum led_brightness logolamp_get(struct led_classdev *cdev);
|
||||
@ -203,7 +202,7 @@ struct led_classdev kblamps_led = {
|
||||
static u32 dbg_level = 0x03;
|
||||
#endif
|
||||
|
||||
static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data);
|
||||
static void acpi_fujitsu_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
/* Fujitsu ACPI interface function */
|
||||
|
||||
@ -658,7 +657,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = {
|
||||
|
||||
static int acpi_fujitsu_add(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
int result = 0;
|
||||
int state = 0;
|
||||
@ -673,20 +671,10 @@ static int acpi_fujitsu_add(struct acpi_device *device)
|
||||
sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
|
||||
device->driver_data = fujitsu;
|
||||
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_fujitsu_notify, fujitsu);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR "Error installing notify handler\n");
|
||||
error = -ENODEV;
|
||||
goto err_stop;
|
||||
}
|
||||
|
||||
fujitsu->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_uninstall_notify;
|
||||
goto err_stop;
|
||||
}
|
||||
|
||||
snprintf(fujitsu->phys, sizeof(fujitsu->phys),
|
||||
@ -743,9 +731,6 @@ static int acpi_fujitsu_add(struct acpi_device *device)
|
||||
end:
|
||||
err_free_input_dev:
|
||||
input_free_device(input);
|
||||
err_uninstall_notify:
|
||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_fujitsu_notify);
|
||||
err_stop:
|
||||
|
||||
return result;
|
||||
@ -753,7 +738,6 @@ err_stop:
|
||||
|
||||
static int acpi_fujitsu_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status;
|
||||
struct fujitsu_t *fujitsu = NULL;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
@ -761,10 +745,6 @@ static int acpi_fujitsu_remove(struct acpi_device *device, int type)
|
||||
|
||||
fujitsu = acpi_driver_data(device);
|
||||
|
||||
status = acpi_remove_notify_handler(fujitsu->acpi_handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_fujitsu_notify);
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
@ -775,7 +755,7 @@ static int acpi_fujitsu_remove(struct acpi_device *device, int type)
|
||||
|
||||
/* Brightness notify */
|
||||
|
||||
static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
|
||||
static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct input_dev *input;
|
||||
int keycode;
|
||||
@ -829,15 +809,12 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
|
||||
input_report_key(input, keycode, 0);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ACPI device for hotkey handling */
|
||||
|
||||
static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle handle;
|
||||
int result = 0;
|
||||
int state = 0;
|
||||
@ -854,17 +831,6 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
|
||||
sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
|
||||
device->driver_data = fujitsu_hotkey;
|
||||
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_fujitsu_hotkey_notify,
|
||||
fujitsu_hotkey);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR "Error installing notify handler\n");
|
||||
error = -ENODEV;
|
||||
goto err_stop;
|
||||
}
|
||||
|
||||
/* kfifo */
|
||||
spin_lock_init(&fujitsu_hotkey->fifo_lock);
|
||||
fujitsu_hotkey->fifo =
|
||||
@ -879,7 +845,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
|
||||
fujitsu_hotkey->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_uninstall_notify;
|
||||
goto err_free_fifo;
|
||||
}
|
||||
|
||||
snprintf(fujitsu_hotkey->phys, sizeof(fujitsu_hotkey->phys),
|
||||
@ -975,9 +941,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
|
||||
end:
|
||||
err_free_input_dev:
|
||||
input_free_device(input);
|
||||
err_uninstall_notify:
|
||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_fujitsu_hotkey_notify);
|
||||
err_free_fifo:
|
||||
kfifo_free(fujitsu_hotkey->fifo);
|
||||
err_stop:
|
||||
|
||||
@ -986,7 +950,6 @@ err_stop:
|
||||
|
||||
static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status;
|
||||
struct fujitsu_hotkey_t *fujitsu_hotkey = NULL;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
@ -994,10 +957,6 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
|
||||
|
||||
fujitsu_hotkey = acpi_driver_data(device);
|
||||
|
||||
status = acpi_remove_notify_handler(fujitsu_hotkey->acpi_handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_fujitsu_hotkey_notify);
|
||||
|
||||
fujitsu_hotkey->acpi_handle = NULL;
|
||||
|
||||
kfifo_free(fujitsu_hotkey->fifo);
|
||||
@ -1005,8 +964,7 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
|
||||
void *data)
|
||||
static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct input_dev *input;
|
||||
int keycode, keycode_r;
|
||||
@ -1089,8 +1047,6 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
|
||||
input_sync(input);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialization */
|
||||
@ -1107,6 +1063,7 @@ static struct acpi_driver acpi_fujitsu_driver = {
|
||||
.ops = {
|
||||
.add = acpi_fujitsu_add,
|
||||
.remove = acpi_fujitsu_remove,
|
||||
.notify = acpi_fujitsu_notify,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1122,6 +1079,7 @@ static struct acpi_driver acpi_fujitsu_hotkey_driver = {
|
||||
.ops = {
|
||||
.add = acpi_fujitsu_hotkey_add,
|
||||
.remove = acpi_fujitsu_hotkey_remove,
|
||||
.notify = acpi_fujitsu_hotkey_notify,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -176,6 +176,7 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
|
||||
static int acpi_pcc_hotkey_add(struct acpi_device *device);
|
||||
static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
|
||||
static int acpi_pcc_hotkey_resume(struct acpi_device *device);
|
||||
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id pcc_device_ids[] = {
|
||||
{ "MAT0012", 0},
|
||||
@ -194,6 +195,7 @@ static struct acpi_driver acpi_pcc_driver = {
|
||||
.add = acpi_pcc_hotkey_add,
|
||||
.remove = acpi_pcc_hotkey_remove,
|
||||
.resume = acpi_pcc_hotkey_resume,
|
||||
.notify = acpi_pcc_hotkey_notify,
|
||||
},
|
||||
};
|
||||
|
||||
@ -271,7 +273,7 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
|
||||
union acpi_object *hkey = NULL;
|
||||
int i;
|
||||
|
||||
status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, 0,
|
||||
status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, NULL,
|
||||
&buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
@ -527,9 +529,9 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
|
||||
return;
|
||||
}
|
||||
|
||||
static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
|
||||
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct pcc_acpi *pcc = (struct pcc_acpi *) data;
|
||||
struct pcc_acpi *pcc = acpi_driver_data(device);
|
||||
|
||||
switch (event) {
|
||||
case HKEY_NOTIFY:
|
||||
@ -599,7 +601,6 @@ static int acpi_pcc_hotkey_resume(struct acpi_device *device)
|
||||
|
||||
static int acpi_pcc_hotkey_add(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
struct pcc_acpi *pcc;
|
||||
int num_sifr, result;
|
||||
|
||||
@ -640,22 +641,11 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
|
||||
goto out_sinf;
|
||||
}
|
||||
|
||||
/* initialize hotkey input device */
|
||||
status = acpi_install_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_pcc_hotkey_notify, pcc);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Error installing notify handler\n"));
|
||||
result = -ENODEV;
|
||||
goto out_input;
|
||||
}
|
||||
|
||||
/* initialize backlight */
|
||||
pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
|
||||
&pcc_backlight_ops);
|
||||
if (IS_ERR(pcc->backlight))
|
||||
goto out_notify;
|
||||
goto out_input;
|
||||
|
||||
if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
@ -680,9 +670,6 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
|
||||
|
||||
out_backlight:
|
||||
backlight_device_unregister(pcc->backlight);
|
||||
out_notify:
|
||||
acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_pcc_hotkey_notify);
|
||||
out_input:
|
||||
input_unregister_device(pcc->input_dev);
|
||||
/* no need to input_free_device() since core input API refcount and
|
||||
@ -723,9 +710,6 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
|
||||
|
||||
backlight_device_unregister(pcc->backlight);
|
||||
|
||||
acpi_remove_notify_handler(pcc->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_pcc_hotkey_notify);
|
||||
|
||||
input_unregister_device(pcc->input_dev);
|
||||
/* no need to input_free_device() since core input API refcount and
|
||||
* free()s the device */
|
||||
|
@ -914,7 +914,7 @@ static struct sony_nc_event sony_127_events[] = {
|
||||
/*
|
||||
* ACPI callbacks
|
||||
*/
|
||||
static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
|
||||
static void sony_nc_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
u32 ev = event;
|
||||
|
||||
@ -933,7 +933,7 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
|
||||
struct sony_nc_event *key_event;
|
||||
|
||||
if (sony_call_snc_handle(key_handle, 0x200, &result)) {
|
||||
dprintk("sony_acpi_notify, unable to decode"
|
||||
dprintk("sony_nc_notify, unable to decode"
|
||||
" event 0x%.2x 0x%.2x\n", key_handle,
|
||||
ev);
|
||||
/* restore the original event */
|
||||
@ -968,7 +968,7 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
|
||||
} else
|
||||
sony_laptop_report_input_event(ev);
|
||||
|
||||
dprintk("sony_acpi_notify, event: 0x%.2x\n", ev);
|
||||
dprintk("sony_nc_notify, event: 0x%.2x\n", ev);
|
||||
acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
|
||||
}
|
||||
|
||||
@ -1276,15 +1276,6 @@ static int sony_nc_add(struct acpi_device *device)
|
||||
goto outwalk;
|
||||
}
|
||||
|
||||
status = acpi_install_notify_handler(sony_nc_acpi_handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
sony_acpi_notify, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status);
|
||||
result = -ENODEV;
|
||||
goto outinput;
|
||||
}
|
||||
|
||||
if (acpi_video_backlight_support()) {
|
||||
printk(KERN_INFO DRV_PFX "brightness ignored, must be "
|
||||
"controlled by ACPI video driver\n");
|
||||
@ -1362,13 +1353,6 @@ static int sony_nc_add(struct acpi_device *device)
|
||||
if (sony_backlight_device)
|
||||
backlight_device_unregister(sony_backlight_device);
|
||||
|
||||
status = acpi_remove_notify_handler(sony_nc_acpi_handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
sony_acpi_notify);
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n");
|
||||
|
||||
outinput:
|
||||
sony_laptop_remove_input();
|
||||
|
||||
outwalk:
|
||||
@ -1378,7 +1362,6 @@ static int sony_nc_add(struct acpi_device *device)
|
||||
|
||||
static int sony_nc_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status;
|
||||
struct sony_nc_value *item;
|
||||
|
||||
if (sony_backlight_device)
|
||||
@ -1386,12 +1369,6 @@ static int sony_nc_remove(struct acpi_device *device, int type)
|
||||
|
||||
sony_nc_acpi_device = NULL;
|
||||
|
||||
status = acpi_remove_notify_handler(sony_nc_acpi_handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
sony_acpi_notify);
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n");
|
||||
|
||||
for (item = sony_nc_values; item->name; ++item) {
|
||||
device_remove_file(&sony_pf_device->dev, &item->devattr);
|
||||
}
|
||||
@ -1425,6 +1402,7 @@ static struct acpi_driver sony_nc_driver = {
|
||||
.add = sony_nc_add,
|
||||
.remove = sony_nc_remove,
|
||||
.resume = sony_nc_resume,
|
||||
.notify = sony_nc_notify,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -81,6 +81,7 @@ static struct wmi_block wmi_blocks;
|
||||
|
||||
static int acpi_wmi_remove(struct acpi_device *device, int type);
|
||||
static int acpi_wmi_add(struct acpi_device *device);
|
||||
static void acpi_wmi_notify(struct acpi_device *device, u32 event);
|
||||
|
||||
static const struct acpi_device_id wmi_device_ids[] = {
|
||||
{"PNP0C14", 0},
|
||||
@ -96,6 +97,7 @@ static struct acpi_driver acpi_wmi_driver = {
|
||||
.ops = {
|
||||
.add = acpi_wmi_add,
|
||||
.remove = acpi_wmi_remove,
|
||||
.notify = acpi_wmi_notify,
|
||||
},
|
||||
};
|
||||
|
||||
@ -643,12 +645,11 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data)
|
||||
static void acpi_wmi_notify(struct acpi_device *device, u32 event)
|
||||
{
|
||||
struct guid_block *block;
|
||||
struct wmi_block *wblock;
|
||||
struct list_head *p;
|
||||
struct acpi_device *device = data;
|
||||
|
||||
list_for_each(p, &wmi_blocks.list) {
|
||||
wblock = list_entry(p, struct wmi_block, list);
|
||||
@ -669,9 +670,6 @@ static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data)
|
||||
|
||||
static int acpi_wmi_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_wmi_notify);
|
||||
|
||||
acpi_remove_address_space_handler(device->handle,
|
||||
ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
|
||||
|
||||
@ -683,13 +681,6 @@ static int __init acpi_wmi_add(struct acpi_device *device)
|
||||
acpi_status status;
|
||||
int result = 0;
|
||||
|
||||
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_wmi_notify, device);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX "Error installing notify handler\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
status = acpi_install_address_space_handler(device->handle,
|
||||
ACPI_ADR_SPACE_EC,
|
||||
&acpi_wmi_ec_space_handler,
|
||||
|
@ -36,6 +36,8 @@ struct pcf50633_mbc {
|
||||
|
||||
struct power_supply usb;
|
||||
struct power_supply adapter;
|
||||
|
||||
struct delayed_work charging_restart_work;
|
||||
};
|
||||
|
||||
int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
|
||||
@ -43,6 +45,8 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
|
||||
struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
|
||||
int ret = 0;
|
||||
u8 bits;
|
||||
int charging_start = 1;
|
||||
u8 mbcs2, chgmod;
|
||||
|
||||
if (ma >= 1000)
|
||||
bits = PCF50633_MBCC7_USB_1000mA;
|
||||
@ -50,8 +54,10 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
|
||||
bits = PCF50633_MBCC7_USB_500mA;
|
||||
else if (ma >= 100)
|
||||
bits = PCF50633_MBCC7_USB_100mA;
|
||||
else
|
||||
else {
|
||||
bits = PCF50633_MBCC7_USB_SUSPEND;
|
||||
charging_start = 0;
|
||||
}
|
||||
|
||||
ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
|
||||
PCF50633_MBCC7_USB_MASK, bits);
|
||||
@ -60,6 +66,22 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
|
||||
else
|
||||
dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
|
||||
|
||||
/* Manual charging start */
|
||||
mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
|
||||
chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
|
||||
|
||||
/* If chgmod == BATFULL, setting chgena has no effect.
|
||||
* We need to set resume instead.
|
||||
*/
|
||||
if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
|
||||
pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
|
||||
PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
|
||||
else
|
||||
pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
|
||||
PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
|
||||
|
||||
mbc->usb_active = charging_start;
|
||||
|
||||
power_supply_changed(&mbc->usb);
|
||||
|
||||
return ret;
|
||||
@ -84,21 +106,6 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
|
||||
|
||||
void pcf50633_mbc_set_status(struct pcf50633 *pcf, int what, int status)
|
||||
{
|
||||
struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
|
||||
|
||||
if (what & PCF50633_MBC_USB_ONLINE)
|
||||
mbc->usb_online = !!status;
|
||||
if (what & PCF50633_MBC_USB_ACTIVE)
|
||||
mbc->usb_active = !!status;
|
||||
if (what & PCF50633_MBC_ADAPTER_ONLINE)
|
||||
mbc->adapter_online = !!status;
|
||||
if (what & PCF50633_MBC_ADAPTER_ACTIVE)
|
||||
mbc->adapter_active = !!status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pcf50633_mbc_set_status);
|
||||
|
||||
static ssize_t
|
||||
show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@ -160,10 +167,44 @@ static struct attribute_group mbc_attr_group = {
|
||||
.attrs = pcf50633_mbc_sysfs_entries,
|
||||
};
|
||||
|
||||
/* MBC state machine switches into charging mode when the battery voltage
|
||||
* falls below 96% of a battery float voltage. But the voltage drop in Li-ion
|
||||
* batteries is marginal(1~2 %) till about 80% of its capacity - which means,
|
||||
* after a BATFULL, charging won't be restarted until 80%.
|
||||
*
|
||||
* This work_struct function restarts charging at regular intervals to make
|
||||
* sure we don't discharge too much
|
||||
*/
|
||||
|
||||
static void pcf50633_mbc_charging_restart(struct work_struct *work)
|
||||
{
|
||||
struct pcf50633_mbc *mbc;
|
||||
u8 mbcs2, chgmod;
|
||||
|
||||
mbc = container_of(work, struct pcf50633_mbc,
|
||||
charging_restart_work.work);
|
||||
|
||||
mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
|
||||
chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
|
||||
|
||||
if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
|
||||
return;
|
||||
|
||||
/* Restart charging */
|
||||
pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1,
|
||||
PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
|
||||
mbc->usb_active = 1;
|
||||
power_supply_changed(&mbc->usb);
|
||||
|
||||
dev_info(mbc->pcf->dev, "Charging restarted\n");
|
||||
}
|
||||
|
||||
static void
|
||||
pcf50633_mbc_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct pcf50633_mbc *mbc = data;
|
||||
int chg_restart_interval =
|
||||
mbc->pcf->pdata->charging_restart_interval;
|
||||
|
||||
/* USB */
|
||||
if (irq == PCF50633_IRQ_USBINS) {
|
||||
@ -172,6 +213,7 @@ pcf50633_mbc_irq_handler(int irq, void *data)
|
||||
mbc->usb_online = 0;
|
||||
mbc->usb_active = 0;
|
||||
pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
|
||||
cancel_delayed_work_sync(&mbc->charging_restart_work);
|
||||
}
|
||||
|
||||
/* Adapter */
|
||||
@ -186,7 +228,14 @@ pcf50633_mbc_irq_handler(int irq, void *data)
|
||||
if (irq == PCF50633_IRQ_BATFULL) {
|
||||
mbc->usb_active = 0;
|
||||
mbc->adapter_active = 0;
|
||||
}
|
||||
|
||||
if (chg_restart_interval > 0)
|
||||
schedule_delayed_work(&mbc->charging_restart_work,
|
||||
chg_restart_interval);
|
||||
} else if (irq == PCF50633_IRQ_USBLIMON)
|
||||
mbc->usb_active = 0;
|
||||
else if (irq == PCF50633_IRQ_USBLIMOFF)
|
||||
mbc->usb_active = 1;
|
||||
|
||||
power_supply_changed(&mbc->usb);
|
||||
power_supply_changed(&mbc->adapter);
|
||||
@ -303,6 +352,9 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&mbc->charging_restart_work,
|
||||
pcf50633_mbc_charging_restart);
|
||||
|
||||
ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
|
||||
if (ret)
|
||||
dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
|
||||
@ -328,6 +380,8 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(&mbc->usb);
|
||||
power_supply_unregister(&mbc->adapter);
|
||||
|
||||
cancel_delayed_work_sync(&mbc->charging_restart_work);
|
||||
|
||||
kfree(mbc);
|
||||
|
||||
return 0;
|
||||
|
@ -12,11 +12,14 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
static inline unsigned int get_irq_flags(struct resource *res)
|
||||
{
|
||||
@ -35,6 +38,11 @@ static struct timer_list supply_timer;
|
||||
static struct timer_list polling_timer;
|
||||
static int polling;
|
||||
|
||||
#ifdef CONFIG_USB_OTG_UTILS
|
||||
static struct otg_transceiver *transceiver;
|
||||
#endif
|
||||
static struct regulator *ac_draw;
|
||||
|
||||
enum {
|
||||
PDA_PSY_OFFLINE = 0,
|
||||
PDA_PSY_ONLINE = 1,
|
||||
@ -104,18 +112,35 @@ static void update_status(void)
|
||||
|
||||
static void update_charger(void)
|
||||
{
|
||||
if (!pdata->set_charge)
|
||||
return;
|
||||
static int regulator_enabled;
|
||||
int max_uA = pdata->ac_max_uA;
|
||||
|
||||
if (new_ac_status > 0) {
|
||||
dev_dbg(dev, "charger on (AC)\n");
|
||||
pdata->set_charge(PDA_POWER_CHARGE_AC);
|
||||
} else if (new_usb_status > 0) {
|
||||
dev_dbg(dev, "charger on (USB)\n");
|
||||
pdata->set_charge(PDA_POWER_CHARGE_USB);
|
||||
} else {
|
||||
dev_dbg(dev, "charger off\n");
|
||||
pdata->set_charge(0);
|
||||
if (pdata->set_charge) {
|
||||
if (new_ac_status > 0) {
|
||||
dev_dbg(dev, "charger on (AC)\n");
|
||||
pdata->set_charge(PDA_POWER_CHARGE_AC);
|
||||
} else if (new_usb_status > 0) {
|
||||
dev_dbg(dev, "charger on (USB)\n");
|
||||
pdata->set_charge(PDA_POWER_CHARGE_USB);
|
||||
} else {
|
||||
dev_dbg(dev, "charger off\n");
|
||||
pdata->set_charge(0);
|
||||
}
|
||||
} else if (ac_draw) {
|
||||
if (new_ac_status > 0) {
|
||||
regulator_set_current_limit(ac_draw, max_uA, max_uA);
|
||||
if (!regulator_enabled) {
|
||||
dev_dbg(dev, "charger on (AC)\n");
|
||||
regulator_enable(ac_draw);
|
||||
regulator_enabled = 1;
|
||||
}
|
||||
} else {
|
||||
if (regulator_enabled) {
|
||||
dev_dbg(dev, "charger off\n");
|
||||
regulator_disable(ac_draw);
|
||||
regulator_enabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,6 +219,13 @@ static void polling_timer_func(unsigned long unused)
|
||||
jiffies + msecs_to_jiffies(pdata->polling_interval));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_OTG_UTILS
|
||||
static int otg_is_usb_online(void)
|
||||
{
|
||||
return (transceiver->state == OTG_STATE_B_PERIPHERAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pda_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -227,6 +259,9 @@ static int pda_power_probe(struct platform_device *pdev)
|
||||
if (!pdata->polling_interval)
|
||||
pdata->polling_interval = 2000;
|
||||
|
||||
if (!pdata->ac_max_uA)
|
||||
pdata->ac_max_uA = 500000;
|
||||
|
||||
setup_timer(&charger_timer, charger_timer_func, 0);
|
||||
setup_timer(&supply_timer, supply_timer_func, 0);
|
||||
|
||||
@ -240,6 +275,13 @@ static int pda_power_probe(struct platform_device *pdev)
|
||||
pda_psy_usb.num_supplicants = pdata->num_supplicants;
|
||||
}
|
||||
|
||||
ac_draw = regulator_get(dev, "ac_draw");
|
||||
if (IS_ERR(ac_draw)) {
|
||||
dev_dbg(dev, "couldn't get ac_draw regulator\n");
|
||||
ac_draw = NULL;
|
||||
ret = PTR_ERR(ac_draw);
|
||||
}
|
||||
|
||||
if (pdata->is_ac_online) {
|
||||
ret = power_supply_register(&pdev->dev, &pda_psy_ac);
|
||||
if (ret) {
|
||||
@ -261,6 +303,13 @@ static int pda_power_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_OTG_UTILS
|
||||
transceiver = otg_get_transceiver();
|
||||
if (transceiver && !pdata->is_usb_online) {
|
||||
pdata->is_usb_online = otg_is_usb_online;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pdata->is_usb_online) {
|
||||
ret = power_supply_register(&pdev->dev, &pda_psy_usb);
|
||||
if (ret) {
|
||||
@ -300,10 +349,18 @@ usb_irq_failed:
|
||||
usb_supply_failed:
|
||||
if (pdata->is_ac_online && ac_irq)
|
||||
free_irq(ac_irq->start, &pda_psy_ac);
|
||||
#ifdef CONFIG_USB_OTG_UTILS
|
||||
if (transceiver)
|
||||
otg_put_transceiver(transceiver);
|
||||
#endif
|
||||
ac_irq_failed:
|
||||
if (pdata->is_ac_online)
|
||||
power_supply_unregister(&pda_psy_ac);
|
||||
ac_supply_failed:
|
||||
if (ac_draw) {
|
||||
regulator_put(ac_draw);
|
||||
ac_draw = NULL;
|
||||
}
|
||||
if (pdata->exit)
|
||||
pdata->exit(dev);
|
||||
init_failed:
|
||||
@ -327,6 +384,14 @@ static int pda_power_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(&pda_psy_usb);
|
||||
if (pdata->is_ac_online)
|
||||
power_supply_unregister(&pda_psy_ac);
|
||||
#ifdef CONFIG_USB_OTG_UTILS
|
||||
if (transceiver)
|
||||
otg_put_transceiver(transceiver);
|
||||
#endif
|
||||
if (ac_draw) {
|
||||
regulator_put(ac_draw);
|
||||
ac_draw = NULL;
|
||||
}
|
||||
if (pdata->exit)
|
||||
pdata->exit(dev);
|
||||
|
||||
|
927
drivers/serial/max3100.c
Normal file
927
drivers/serial/max3100.c
Normal file
@ -0,0 +1,927 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2008 Christian Pellegrin <chripell@evolware.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* Notes: the MAX3100 doesn't provide an interrupt on CTS so we have
|
||||
* to use polling for flow control. TX empty IRQ is unusable, since
|
||||
* writing conf clears FIFO buffer and we cannot have this interrupt
|
||||
* always asking us for attention.
|
||||
*
|
||||
* Example platform data:
|
||||
|
||||
static struct plat_max3100 max3100_plat_data = {
|
||||
.loopback = 0,
|
||||
.crystal = 0,
|
||||
.poll_time = 100,
|
||||
};
|
||||
|
||||
static struct spi_board_info spi_board_info[] = {
|
||||
{
|
||||
.modalias = "max3100",
|
||||
.platform_data = &max3100_plat_data,
|
||||
.irq = IRQ_EINT12,
|
||||
.max_speed_hz = 5*1000*1000,
|
||||
.chip_select = 0,
|
||||
},
|
||||
};
|
||||
|
||||
* The initial minor number is 209 in the low-density serial port:
|
||||
* mknod /dev/ttyMAX0 c 204 209
|
||||
*/
|
||||
|
||||
#define MAX3100_MAJOR 204
|
||||
#define MAX3100_MINOR 209
|
||||
/* 4 MAX3100s should be enough for everyone */
|
||||
#define MAX_MAX3100 4
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <linux/serial_max3100.h>
|
||||
|
||||
#define MAX3100_C (1<<14)
|
||||
#define MAX3100_D (0<<14)
|
||||
#define MAX3100_W (1<<15)
|
||||
#define MAX3100_RX (0<<15)
|
||||
|
||||
#define MAX3100_WC (MAX3100_W | MAX3100_C)
|
||||
#define MAX3100_RC (MAX3100_RX | MAX3100_C)
|
||||
#define MAX3100_WD (MAX3100_W | MAX3100_D)
|
||||
#define MAX3100_RD (MAX3100_RX | MAX3100_D)
|
||||
#define MAX3100_CMD (3 << 14)
|
||||
|
||||
#define MAX3100_T (1<<14)
|
||||
#define MAX3100_R (1<<15)
|
||||
|
||||
#define MAX3100_FEN (1<<13)
|
||||
#define MAX3100_SHDN (1<<12)
|
||||
#define MAX3100_TM (1<<11)
|
||||
#define MAX3100_RM (1<<10)
|
||||
#define MAX3100_PM (1<<9)
|
||||
#define MAX3100_RAM (1<<8)
|
||||
#define MAX3100_IR (1<<7)
|
||||
#define MAX3100_ST (1<<6)
|
||||
#define MAX3100_PE (1<<5)
|
||||
#define MAX3100_L (1<<4)
|
||||
#define MAX3100_BAUD (0xf)
|
||||
|
||||
#define MAX3100_TE (1<<10)
|
||||
#define MAX3100_RAFE (1<<10)
|
||||
#define MAX3100_RTS (1<<9)
|
||||
#define MAX3100_CTS (1<<9)
|
||||
#define MAX3100_PT (1<<8)
|
||||
#define MAX3100_DATA (0xff)
|
||||
|
||||
#define MAX3100_RT (MAX3100_R | MAX3100_T)
|
||||
#define MAX3100_RTC (MAX3100_RT | MAX3100_CTS | MAX3100_RAFE)
|
||||
|
||||
/* the following simulate a status reg for ignore_status_mask */
|
||||
#define MAX3100_STATUS_PE 1
|
||||
#define MAX3100_STATUS_FE 2
|
||||
#define MAX3100_STATUS_OE 4
|
||||
|
||||
struct max3100_port {
|
||||
struct uart_port port;
|
||||
struct spi_device *spi;
|
||||
|
||||
int cts; /* last CTS received for flow ctrl */
|
||||
int tx_empty; /* last TX empty bit */
|
||||
|
||||
spinlock_t conf_lock; /* shared data */
|
||||
int conf_commit; /* need to make changes */
|
||||
int conf; /* configuration for the MAX31000
|
||||
* (bits 0-7, bits 8-11 are irqs) */
|
||||
int rts_commit; /* need to change rts */
|
||||
int rts; /* rts status */
|
||||
int baud; /* current baud rate */
|
||||
|
||||
int parity; /* keeps track if we should send parity */
|
||||
#define MAX3100_PARITY_ON 1
|
||||
#define MAX3100_PARITY_ODD 2
|
||||
#define MAX3100_7BIT 4
|
||||
int rx_enabled; /* if we should rx chars */
|
||||
|
||||
int irq; /* irq assigned to the max3100 */
|
||||
|
||||
int minor; /* minor number */
|
||||
int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */
|
||||
int loopback; /* 1 if we are in loopback mode */
|
||||
|
||||
/* for handling irqs: need workqueue since we do spi_sync */
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct work;
|
||||
/* set to 1 to make the workhandler exit as soon as possible */
|
||||
int force_end_work;
|
||||
/* need to know we are suspending to avoid deadlock on workqueue */
|
||||
int suspending;
|
||||
|
||||
/* hook for suspending MAX3100 via dedicated pin */
|
||||
void (*max3100_hw_suspend) (int suspend);
|
||||
|
||||
/* poll time (in ms) for ctrl lines */
|
||||
int poll_time;
|
||||
/* and its timer */
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
static struct max3100_port *max3100s[MAX_MAX3100]; /* the chips */
|
||||
static DEFINE_MUTEX(max3100s_lock); /* race on probe */
|
||||
|
||||
static int max3100_do_parity(struct max3100_port *s, u16 c)
|
||||
{
|
||||
int parity;
|
||||
|
||||
if (s->parity & MAX3100_PARITY_ODD)
|
||||
parity = 1;
|
||||
else
|
||||
parity = 0;
|
||||
|
||||
if (s->parity & MAX3100_7BIT)
|
||||
c &= 0x7f;
|
||||
else
|
||||
c &= 0xff;
|
||||
|
||||
parity = parity ^ (hweight8(c) & 1);
|
||||
return parity;
|
||||
}
|
||||
|
||||
static int max3100_check_parity(struct max3100_port *s, u16 c)
|
||||
{
|
||||
return max3100_do_parity(s, c) == ((c >> 8) & 1);
|
||||
}
|
||||
|
||||
static void max3100_calc_parity(struct max3100_port *s, u16 *c)
|
||||
{
|
||||
if (s->parity & MAX3100_7BIT)
|
||||
*c &= 0x7f;
|
||||
else
|
||||
*c &= 0xff;
|
||||
|
||||
if (s->parity & MAX3100_PARITY_ON)
|
||||
*c |= max3100_do_parity(s, *c) << 8;
|
||||
}
|
||||
|
||||
static void max3100_work(struct work_struct *w);
|
||||
|
||||
static void max3100_dowork(struct max3100_port *s)
|
||||
{
|
||||
if (!s->force_end_work && !work_pending(&s->work) &&
|
||||
!freezing(current) && !s->suspending)
|
||||
queue_work(s->workqueue, &s->work);
|
||||
}
|
||||
|
||||
static void max3100_timeout(unsigned long data)
|
||||
{
|
||||
struct max3100_port *s = (struct max3100_port *)data;
|
||||
|
||||
if (s->port.info) {
|
||||
max3100_dowork(s);
|
||||
mod_timer(&s->timer, jiffies + s->poll_time);
|
||||
}
|
||||
}
|
||||
|
||||
static int max3100_sr(struct max3100_port *s, u16 tx, u16 *rx)
|
||||
{
|
||||
struct spi_message message;
|
||||
u16 etx, erx;
|
||||
int status;
|
||||
struct spi_transfer tran = {
|
||||
.tx_buf = &etx,
|
||||
.rx_buf = &erx,
|
||||
.len = 2,
|
||||
};
|
||||
|
||||
etx = cpu_to_be16(tx);
|
||||
spi_message_init(&message);
|
||||
spi_message_add_tail(&tran, &message);
|
||||
status = spi_sync(s->spi, &message);
|
||||
if (status) {
|
||||
dev_warn(&s->spi->dev, "error while calling spi_sync\n");
|
||||
return -EIO;
|
||||
}
|
||||
*rx = be16_to_cpu(erx);
|
||||
s->tx_empty = (*rx & MAX3100_T) > 0;
|
||||
dev_dbg(&s->spi->dev, "%04x - %04x\n", tx, *rx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max3100_handlerx(struct max3100_port *s, u16 rx)
|
||||
{
|
||||
unsigned int ch, flg, status = 0;
|
||||
int ret = 0, cts;
|
||||
|
||||
if (rx & MAX3100_R && s->rx_enabled) {
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff);
|
||||
if (rx & MAX3100_RAFE) {
|
||||
s->port.icount.frame++;
|
||||
flg = TTY_FRAME;
|
||||
status |= MAX3100_STATUS_FE;
|
||||
} else {
|
||||
if (s->parity & MAX3100_PARITY_ON) {
|
||||
if (max3100_check_parity(s, rx)) {
|
||||
s->port.icount.rx++;
|
||||
flg = TTY_NORMAL;
|
||||
} else {
|
||||
s->port.icount.parity++;
|
||||
flg = TTY_PARITY;
|
||||
status |= MAX3100_STATUS_PE;
|
||||
}
|
||||
} else {
|
||||
s->port.icount.rx++;
|
||||
flg = TTY_NORMAL;
|
||||
}
|
||||
}
|
||||
uart_insert_char(&s->port, status, MAX3100_STATUS_OE, ch, flg);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
cts = (rx & MAX3100_CTS) > 0;
|
||||
if (s->cts != cts) {
|
||||
s->cts = cts;
|
||||
uart_handle_cts_change(&s->port, cts ? TIOCM_CTS : 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void max3100_work(struct work_struct *w)
|
||||
{
|
||||
struct max3100_port *s = container_of(w, struct max3100_port, work);
|
||||
int rxchars;
|
||||
u16 tx, rx;
|
||||
int conf, cconf, rts, crts;
|
||||
struct circ_buf *xmit = &s->port.info->xmit;
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
rxchars = 0;
|
||||
do {
|
||||
spin_lock(&s->conf_lock);
|
||||
conf = s->conf;
|
||||
cconf = s->conf_commit;
|
||||
s->conf_commit = 0;
|
||||
rts = s->rts;
|
||||
crts = s->rts_commit;
|
||||
s->rts_commit = 0;
|
||||
spin_unlock(&s->conf_lock);
|
||||
if (cconf)
|
||||
max3100_sr(s, MAX3100_WC | conf, &rx);
|
||||
if (crts) {
|
||||
max3100_sr(s, MAX3100_WD | MAX3100_TE |
|
||||
(s->rts ? MAX3100_RTS : 0), &rx);
|
||||
rxchars += max3100_handlerx(s, rx);
|
||||
}
|
||||
|
||||
max3100_sr(s, MAX3100_RD, &rx);
|
||||
rxchars += max3100_handlerx(s, rx);
|
||||
|
||||
if (rx & MAX3100_T) {
|
||||
tx = 0xffff;
|
||||
if (s->port.x_char) {
|
||||
tx = s->port.x_char;
|
||||
s->port.icount.tx++;
|
||||
s->port.x_char = 0;
|
||||
} else if (!uart_circ_empty(xmit) &&
|
||||
!uart_tx_stopped(&s->port)) {
|
||||
tx = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
s->port.icount.tx++;
|
||||
}
|
||||
if (tx != 0xffff) {
|
||||
max3100_calc_parity(s, &tx);
|
||||
tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0);
|
||||
max3100_sr(s, tx, &rx);
|
||||
rxchars += max3100_handlerx(s, rx);
|
||||
}
|
||||
}
|
||||
|
||||
if (rxchars > 16 && s->port.info->port.tty != NULL) {
|
||||
tty_flip_buffer_push(s->port.info->port.tty);
|
||||
rxchars = 0;
|
||||
}
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&s->port);
|
||||
|
||||
} while (!s->force_end_work &&
|
||||
!freezing(current) &&
|
||||
((rx & MAX3100_R) ||
|
||||
(!uart_circ_empty(xmit) &&
|
||||
!uart_tx_stopped(&s->port))));
|
||||
|
||||
if (rxchars > 0 && s->port.info->port.tty != NULL)
|
||||
tty_flip_buffer_push(s->port.info->port.tty);
|
||||
}
|
||||
|
||||
static irqreturn_t max3100_irq(int irqno, void *dev_id)
|
||||
{
|
||||
struct max3100_port *s = dev_id;
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
max3100_dowork(s);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void max3100_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
if (s->poll_time > 0)
|
||||
mod_timer(&s->timer, jiffies);
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static void max3100_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
max3100_dowork(s);
|
||||
}
|
||||
|
||||
static void max3100_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
s->rx_enabled = 0;
|
||||
spin_lock(&s->conf_lock);
|
||||
s->conf &= ~MAX3100_RM;
|
||||
s->conf_commit = 1;
|
||||
spin_unlock(&s->conf_lock);
|
||||
max3100_dowork(s);
|
||||
}
|
||||
|
||||
static unsigned int max3100_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
/* may not be truly up-to-date */
|
||||
max3100_dowork(s);
|
||||
return s->tx_empty;
|
||||
}
|
||||
|
||||
static unsigned int max3100_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
/* may not be truly up-to-date */
|
||||
max3100_dowork(s);
|
||||
/* always assert DCD and DSR since these lines are not wired */
|
||||
return (s->cts ? TIOCM_CTS : 0) | TIOCM_DSR | TIOCM_CAR;
|
||||
}
|
||||
|
||||
static void max3100_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
int rts;
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
rts = (mctrl & TIOCM_RTS) > 0;
|
||||
|
||||
spin_lock(&s->conf_lock);
|
||||
if (s->rts != rts) {
|
||||
s->rts = rts;
|
||||
s->rts_commit = 1;
|
||||
max3100_dowork(s);
|
||||
}
|
||||
spin_unlock(&s->conf_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
max3100_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
int baud = 0;
|
||||
unsigned cflag;
|
||||
u32 param_new, param_mask, parity = 0;
|
||||
struct tty_struct *tty = s->port.info->port.tty;
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
cflag = termios->c_cflag;
|
||||
param_new = 0;
|
||||
param_mask = 0;
|
||||
|
||||
baud = tty_get_baud_rate(tty);
|
||||
param_new = s->conf & MAX3100_BAUD;
|
||||
switch (baud) {
|
||||
case 300:
|
||||
if (s->crystal)
|
||||
baud = s->baud;
|
||||
else
|
||||
param_new = 15;
|
||||
break;
|
||||
case 600:
|
||||
param_new = 14 + s->crystal;
|
||||
break;
|
||||
case 1200:
|
||||
param_new = 13 + s->crystal;
|
||||
break;
|
||||
case 2400:
|
||||
param_new = 12 + s->crystal;
|
||||
break;
|
||||
case 4800:
|
||||
param_new = 11 + s->crystal;
|
||||
break;
|
||||
case 9600:
|
||||
param_new = 10 + s->crystal;
|
||||
break;
|
||||
case 19200:
|
||||
param_new = 9 + s->crystal;
|
||||
break;
|
||||
case 38400:
|
||||
param_new = 8 + s->crystal;
|
||||
break;
|
||||
case 57600:
|
||||
param_new = 1 + s->crystal;
|
||||
break;
|
||||
case 115200:
|
||||
param_new = 0 + s->crystal;
|
||||
break;
|
||||
case 230400:
|
||||
if (s->crystal)
|
||||
param_new = 0;
|
||||
else
|
||||
baud = s->baud;
|
||||
break;
|
||||
default:
|
||||
baud = s->baud;
|
||||
}
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
s->baud = baud;
|
||||
param_mask |= MAX3100_BAUD;
|
||||
|
||||
if ((cflag & CSIZE) == CS8) {
|
||||
param_new &= ~MAX3100_L;
|
||||
parity &= ~MAX3100_7BIT;
|
||||
} else {
|
||||
param_new |= MAX3100_L;
|
||||
parity |= MAX3100_7BIT;
|
||||
cflag = (cflag & ~CSIZE) | CS7;
|
||||
}
|
||||
param_mask |= MAX3100_L;
|
||||
|
||||
if (cflag & CSTOPB)
|
||||
param_new |= MAX3100_ST;
|
||||
else
|
||||
param_new &= ~MAX3100_ST;
|
||||
param_mask |= MAX3100_ST;
|
||||
|
||||
if (cflag & PARENB) {
|
||||
param_new |= MAX3100_PE;
|
||||
parity |= MAX3100_PARITY_ON;
|
||||
} else {
|
||||
param_new &= ~MAX3100_PE;
|
||||
parity &= ~MAX3100_PARITY_ON;
|
||||
}
|
||||
param_mask |= MAX3100_PE;
|
||||
|
||||
if (cflag & PARODD)
|
||||
parity |= MAX3100_PARITY_ODD;
|
||||
else
|
||||
parity &= ~MAX3100_PARITY_ODD;
|
||||
|
||||
/* mask termios capabilities we don't support */
|
||||
cflag &= ~CMSPAR;
|
||||
termios->c_cflag = cflag;
|
||||
|
||||
s->port.ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
s->port.ignore_status_mask |=
|
||||
MAX3100_STATUS_PE | MAX3100_STATUS_FE |
|
||||
MAX3100_STATUS_OE;
|
||||
|
||||
/* we are sending char from a workqueue so enable */
|
||||
s->port.info->port.tty->low_latency = 1;
|
||||
|
||||
if (s->poll_time > 0)
|
||||
del_timer_sync(&s->timer);
|
||||
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
spin_lock(&s->conf_lock);
|
||||
s->conf = (s->conf & ~param_mask) | (param_new & param_mask);
|
||||
s->conf_commit = 1;
|
||||
s->parity = parity;
|
||||
spin_unlock(&s->conf_lock);
|
||||
max3100_dowork(s);
|
||||
|
||||
if (UART_ENABLE_MS(&s->port, termios->c_cflag))
|
||||
max3100_enable_ms(&s->port);
|
||||
}
|
||||
|
||||
static void max3100_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
if (s->suspending)
|
||||
return;
|
||||
|
||||
s->force_end_work = 1;
|
||||
|
||||
if (s->poll_time > 0)
|
||||
del_timer_sync(&s->timer);
|
||||
|
||||
if (s->workqueue) {
|
||||
flush_workqueue(s->workqueue);
|
||||
destroy_workqueue(s->workqueue);
|
||||
s->workqueue = NULL;
|
||||
}
|
||||
if (s->irq)
|
||||
free_irq(s->irq, s);
|
||||
|
||||
/* set shutdown mode to save power */
|
||||
if (s->max3100_hw_suspend)
|
||||
s->max3100_hw_suspend(1);
|
||||
else {
|
||||
u16 tx, rx;
|
||||
|
||||
tx = MAX3100_WC | MAX3100_SHDN;
|
||||
max3100_sr(s, tx, &rx);
|
||||
}
|
||||
}
|
||||
|
||||
static int max3100_startup(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
char b[12];
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
s->conf = MAX3100_RM;
|
||||
s->baud = s->crystal ? 230400 : 115200;
|
||||
s->rx_enabled = 1;
|
||||
|
||||
if (s->suspending)
|
||||
return 0;
|
||||
|
||||
s->force_end_work = 0;
|
||||
s->parity = 0;
|
||||
s->rts = 0;
|
||||
|
||||
sprintf(b, "max3100-%d", s->minor);
|
||||
s->workqueue = create_freezeable_workqueue(b);
|
||||
if (!s->workqueue) {
|
||||
dev_warn(&s->spi->dev, "cannot create workqueue\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
INIT_WORK(&s->work, max3100_work);
|
||||
|
||||
if (request_irq(s->irq, max3100_irq,
|
||||
IRQF_TRIGGER_FALLING, "max3100", s) < 0) {
|
||||
dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq);
|
||||
s->irq = 0;
|
||||
destroy_workqueue(s->workqueue);
|
||||
s->workqueue = NULL;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (s->loopback) {
|
||||
u16 tx, rx;
|
||||
tx = 0x4001;
|
||||
max3100_sr(s, tx, &rx);
|
||||
}
|
||||
|
||||
if (s->max3100_hw_suspend)
|
||||
s->max3100_hw_suspend(0);
|
||||
s->conf_commit = 1;
|
||||
max3100_dowork(s);
|
||||
/* wait for clock to settle */
|
||||
msleep(50);
|
||||
|
||||
max3100_enable_ms(&s->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *max3100_type(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
return s->port.type == PORT_MAX3100 ? "MAX3100" : NULL;
|
||||
}
|
||||
|
||||
static void max3100_release_port(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static void max3100_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
s->port.type = PORT_MAX3100;
|
||||
}
|
||||
|
||||
static int max3100_verify_port(struct uart_port *port,
|
||||
struct serial_struct *ser)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
int ret = -EINVAL;
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void max3100_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static int max3100_request_port(struct uart_port *port)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void max3100_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct max3100_port *s = container_of(port,
|
||||
struct max3100_port,
|
||||
port);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static struct uart_ops max3100_ops = {
|
||||
.tx_empty = max3100_tx_empty,
|
||||
.set_mctrl = max3100_set_mctrl,
|
||||
.get_mctrl = max3100_get_mctrl,
|
||||
.stop_tx = max3100_stop_tx,
|
||||
.start_tx = max3100_start_tx,
|
||||
.stop_rx = max3100_stop_rx,
|
||||
.enable_ms = max3100_enable_ms,
|
||||
.break_ctl = max3100_break_ctl,
|
||||
.startup = max3100_startup,
|
||||
.shutdown = max3100_shutdown,
|
||||
.set_termios = max3100_set_termios,
|
||||
.type = max3100_type,
|
||||
.release_port = max3100_release_port,
|
||||
.request_port = max3100_request_port,
|
||||
.config_port = max3100_config_port,
|
||||
.verify_port = max3100_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_driver max3100_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyMAX",
|
||||
.dev_name = "ttyMAX",
|
||||
.major = MAX3100_MAJOR,
|
||||
.minor = MAX3100_MINOR,
|
||||
.nr = MAX_MAX3100,
|
||||
};
|
||||
static int uart_driver_registered;
|
||||
|
||||
static int __devinit max3100_probe(struct spi_device *spi)
|
||||
{
|
||||
int i, retval;
|
||||
struct plat_max3100 *pdata;
|
||||
u16 tx, rx;
|
||||
|
||||
mutex_lock(&max3100s_lock);
|
||||
|
||||
if (!uart_driver_registered) {
|
||||
uart_driver_registered = 1;
|
||||
retval = uart_register_driver(&max3100_uart_driver);
|
||||
if (retval) {
|
||||
printk(KERN_ERR "Couldn't register max3100 uart driver\n");
|
||||
mutex_unlock(&max3100s_lock);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_MAX3100; i++)
|
||||
if (!max3100s[i])
|
||||
break;
|
||||
if (i == MAX_MAX3100) {
|
||||
dev_warn(&spi->dev, "too many MAX3100 chips\n");
|
||||
mutex_unlock(&max3100s_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
max3100s[i] = kzalloc(sizeof(struct max3100_port), GFP_KERNEL);
|
||||
if (!max3100s[i]) {
|
||||
dev_warn(&spi->dev,
|
||||
"kmalloc for max3100 structure %d failed!\n", i);
|
||||
mutex_unlock(&max3100s_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
max3100s[i]->spi = spi;
|
||||
max3100s[i]->irq = spi->irq;
|
||||
spin_lock_init(&max3100s[i]->conf_lock);
|
||||
dev_set_drvdata(&spi->dev, max3100s[i]);
|
||||
pdata = spi->dev.platform_data;
|
||||
max3100s[i]->crystal = pdata->crystal;
|
||||
max3100s[i]->loopback = pdata->loopback;
|
||||
max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
|
||||
if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
|
||||
max3100s[i]->poll_time = 1;
|
||||
max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;
|
||||
max3100s[i]->minor = i;
|
||||
init_timer(&max3100s[i]->timer);
|
||||
max3100s[i]->timer.function = max3100_timeout;
|
||||
max3100s[i]->timer.data = (unsigned long) max3100s[i];
|
||||
|
||||
dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i);
|
||||
max3100s[i]->port.irq = max3100s[i]->irq;
|
||||
max3100s[i]->port.uartclk = max3100s[i]->crystal ? 3686400 : 1843200;
|
||||
max3100s[i]->port.fifosize = 16;
|
||||
max3100s[i]->port.ops = &max3100_ops;
|
||||
max3100s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
|
||||
max3100s[i]->port.line = i;
|
||||
max3100s[i]->port.type = PORT_MAX3100;
|
||||
max3100s[i]->port.dev = &spi->dev;
|
||||
retval = uart_add_one_port(&max3100_uart_driver, &max3100s[i]->port);
|
||||
if (retval < 0)
|
||||
dev_warn(&spi->dev,
|
||||
"uart_add_one_port failed for line %d with error %d\n",
|
||||
i, retval);
|
||||
|
||||
/* set shutdown mode to save power. Will be woken-up on open */
|
||||
if (max3100s[i]->max3100_hw_suspend)
|
||||
max3100s[i]->max3100_hw_suspend(1);
|
||||
else {
|
||||
tx = MAX3100_WC | MAX3100_SHDN;
|
||||
max3100_sr(max3100s[i], tx, &rx);
|
||||
}
|
||||
mutex_unlock(&max3100s_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max3100_remove(struct spi_device *spi)
|
||||
{
|
||||
struct max3100_port *s = dev_get_drvdata(&spi->dev);
|
||||
int i;
|
||||
|
||||
mutex_lock(&max3100s_lock);
|
||||
|
||||
/* find out the index for the chip we are removing */
|
||||
for (i = 0; i < MAX_MAX3100; i++)
|
||||
if (max3100s[i] == s)
|
||||
break;
|
||||
|
||||
dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i);
|
||||
uart_remove_one_port(&max3100_uart_driver, &max3100s[i]->port);
|
||||
kfree(max3100s[i]);
|
||||
max3100s[i] = NULL;
|
||||
|
||||
/* check if this is the last chip we have */
|
||||
for (i = 0; i < MAX_MAX3100; i++)
|
||||
if (max3100s[i]) {
|
||||
mutex_unlock(&max3100s_lock);
|
||||
return 0;
|
||||
}
|
||||
pr_debug("removing max3100 driver\n");
|
||||
uart_unregister_driver(&max3100_uart_driver);
|
||||
|
||||
mutex_unlock(&max3100s_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int max3100_suspend(struct spi_device *spi, pm_message_t state)
|
||||
{
|
||||
struct max3100_port *s = dev_get_drvdata(&spi->dev);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
disable_irq(s->irq);
|
||||
|
||||
s->suspending = 1;
|
||||
uart_suspend_port(&max3100_uart_driver, &s->port);
|
||||
|
||||
if (s->max3100_hw_suspend)
|
||||
s->max3100_hw_suspend(1);
|
||||
else {
|
||||
/* no HW suspend, so do SW one */
|
||||
u16 tx, rx;
|
||||
|
||||
tx = MAX3100_WC | MAX3100_SHDN;
|
||||
max3100_sr(s, tx, &rx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max3100_resume(struct spi_device *spi)
|
||||
{
|
||||
struct max3100_port *s = dev_get_drvdata(&spi->dev);
|
||||
|
||||
dev_dbg(&s->spi->dev, "%s\n", __func__);
|
||||
|
||||
if (s->max3100_hw_suspend)
|
||||
s->max3100_hw_suspend(0);
|
||||
uart_resume_port(&max3100_uart_driver, &s->port);
|
||||
s->suspending = 0;
|
||||
|
||||
enable_irq(s->irq);
|
||||
|
||||
s->conf_commit = 1;
|
||||
if (s->workqueue)
|
||||
max3100_dowork(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define max3100_suspend NULL
|
||||
#define max3100_resume NULL
|
||||
#endif
|
||||
|
||||
static struct spi_driver max3100_driver = {
|
||||
.driver = {
|
||||
.name = "max3100",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
.probe = max3100_probe,
|
||||
.remove = __devexit_p(max3100_remove),
|
||||
.suspend = max3100_suspend,
|
||||
.resume = max3100_resume,
|
||||
};
|
||||
|
||||
static int __init max3100_init(void)
|
||||
{
|
||||
return spi_register_driver(&max3100_driver);
|
||||
}
|
||||
module_init(max3100_init);
|
||||
|
||||
static void __exit max3100_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&max3100_driver);
|
||||
}
|
||||
module_exit(max3100_exit);
|
||||
|
||||
MODULE_DESCRIPTION("MAX3100 driver");
|
||||
MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1178,7 +1178,7 @@ static struct uart_driver sunsu_reg = {
|
||||
.major = TTY_MAJOR,
|
||||
};
|
||||
|
||||
static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up)
|
||||
static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up)
|
||||
{
|
||||
int quot, baud;
|
||||
#ifdef CONFIG_SERIO
|
||||
|
@ -280,7 +280,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
|
||||
* are always powered while this driver is active, and use
|
||||
* active-low power switches.
|
||||
*/
|
||||
for (i = 0; i < pdata->ports; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
|
||||
if (pdata->vbus_pin[i] <= 0)
|
||||
continue;
|
||||
gpio_request(pdata->vbus_pin[i], "ohci_vbus");
|
||||
@ -298,7 +298,7 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
|
||||
int i;
|
||||
|
||||
if (pdata) {
|
||||
for (i = 0; i < pdata->ports; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
|
||||
if (pdata->vbus_pin[i] <= 0)
|
||||
continue;
|
||||
gpio_direction_output(pdata->vbus_pin[i], 1);
|
||||
|
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <asm/page.h> /* for PAGE_SIZE */
|
||||
|
||||
#include "befs.h"
|
||||
#include "super.h"
|
||||
|
13
fs/buffer.c
13
fs/buffer.c
@ -1596,6 +1596,16 @@ EXPORT_SYMBOL(unmap_underlying_metadata);
|
||||
* locked buffer. This only can happen if someone has written the buffer
|
||||
* directly, with submit_bh(). At the address_space level PageWriteback
|
||||
* prevents this contention from occurring.
|
||||
*
|
||||
* If block_write_full_page() is called with wbc->sync_mode ==
|
||||
* WB_SYNC_ALL, the writes are posted using WRITE_SYNC_PLUG; this
|
||||
* causes the writes to be flagged as synchronous writes, but the
|
||||
* block device queue will NOT be unplugged, since usually many pages
|
||||
* will be pushed to the out before the higher-level caller actually
|
||||
* waits for the writes to be completed. The various wait functions,
|
||||
* such as wait_on_writeback_range() will ultimately call sync_page()
|
||||
* which will ultimately call blk_run_backing_dev(), which will end up
|
||||
* unplugging the device queue.
|
||||
*/
|
||||
static int __block_write_full_page(struct inode *inode, struct page *page,
|
||||
get_block_t *get_block, struct writeback_control *wbc)
|
||||
@ -1606,7 +1616,8 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
|
||||
struct buffer_head *bh, *head;
|
||||
const unsigned blocksize = 1 << inode->i_blkbits;
|
||||
int nr_underway = 0;
|
||||
int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);
|
||||
int write_op = (wbc->sync_mode == WB_SYNC_ALL ?
|
||||
WRITE_SYNC_PLUG : WRITE);
|
||||
|
||||
BUG_ON(!PageLocked(page));
|
||||
|
||||
|
@ -1521,12 +1521,16 @@ static int ext3_ordered_writepage(struct page *page,
|
||||
if (!page_has_buffers(page)) {
|
||||
create_empty_buffers(page, inode->i_sb->s_blocksize,
|
||||
(1 << BH_Dirty)|(1 << BH_Uptodate));
|
||||
} else if (!walk_page_buffers(NULL, page_buffers(page), 0, PAGE_CACHE_SIZE, NULL, buffer_unmapped)) {
|
||||
/* Provide NULL instead of get_block so that we catch bugs if buffers weren't really mapped */
|
||||
return block_write_full_page(page, NULL, wbc);
|
||||
page_bufs = page_buffers(page);
|
||||
} else {
|
||||
page_bufs = page_buffers(page);
|
||||
if (!walk_page_buffers(NULL, page_bufs, 0, PAGE_CACHE_SIZE,
|
||||
NULL, buffer_unmapped)) {
|
||||
/* Provide NULL get_block() to catch bugs if buffers
|
||||
* weren't really mapped */
|
||||
return block_write_full_page(page, NULL, wbc);
|
||||
}
|
||||
}
|
||||
page_bufs = page_buffers(page);
|
||||
|
||||
handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
|
||||
|
||||
if (IS_ERR(handle)) {
|
||||
@ -1581,6 +1585,15 @@ static int ext3_writeback_writepage(struct page *page,
|
||||
if (ext3_journal_current_handle())
|
||||
goto out_fail;
|
||||
|
||||
if (page_has_buffers(page)) {
|
||||
if (!walk_page_buffers(NULL, page_buffers(page), 0,
|
||||
PAGE_CACHE_SIZE, NULL, buffer_unmapped)) {
|
||||
/* Provide NULL get_block() to catch bugs if buffers
|
||||
* weren't really mapped */
|
||||
return block_write_full_page(page, NULL, wbc);
|
||||
}
|
||||
}
|
||||
|
||||
handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
|
||||
if (IS_ERR(handle)) {
|
||||
ret = PTR_ERR(handle);
|
||||
|
@ -135,7 +135,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
|
||||
struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
|
||||
dev = inode->i_sb->s_dev;
|
||||
ino = inode->i_ino;
|
||||
pgoff = (loff_t)vma->pg_off << PAGE_SHIFT;
|
||||
pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
seq_printf(m,
|
||||
|
@ -270,7 +270,6 @@ struct acpi_device {
|
||||
struct list_head children;
|
||||
struct list_head node;
|
||||
struct list_head wakeup_list;
|
||||
struct list_head g_list;
|
||||
struct acpi_device_status status;
|
||||
struct acpi_device_flags flags;
|
||||
struct acpi_device_pnp pnp;
|
||||
|
@ -29,6 +29,8 @@ struct pcf50633_platform_data {
|
||||
char **batteries;
|
||||
int num_batteries;
|
||||
|
||||
int charging_restart_interval;
|
||||
|
||||
/* Callbacks */
|
||||
void (*probe_done)(struct pcf50633 *);
|
||||
void (*mbc_event_callback)(struct pcf50633 *, int);
|
||||
|
@ -128,7 +128,6 @@ enum pcf50633_reg_mbcs3 {
|
||||
int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma);
|
||||
|
||||
int pcf50633_mbc_get_status(struct pcf50633 *);
|
||||
void pcf50633_mbc_set_status(struct pcf50633 *, int what, int status);
|
||||
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user