Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6

This commit is contained in:
Wim Van Sebroeck 2009-04-09 05:51:57 +00:00
commit 3230e8cd80
111 changed files with 7677 additions and 700 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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,
};

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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")

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View 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

View File

@ -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 */

View File

@ -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,

View File

@ -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));

View File

@ -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
******************************************************************************/

View File

@ -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
View 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

View File

@ -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
******************************************************************************/

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -431,6 +431,12 @@ static void __cpuinit setup_APIC_timer(void)
{
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
if (cpu_has(&current_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());

View File

@ -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 }
};

View File

@ -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;

View File

@ -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>

View File

@ -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},

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 @@ static int acpi_thermal_add(struct acpi_device *device)
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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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)
*/

View File

@ -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 @@ static int imxmci_probe(struct platform_device *pdev)
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)

View File

@ -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 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
* 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

View File

@ -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);

View File

@ -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");

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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 */

View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

108
drivers/net/igbvf/regs.h Normal file
View 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
View 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
View 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_ */

View File

@ -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);

View File

@ -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++) {

View File

@ -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)

View File

@ -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:

View File

@ -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 @@ static int acpi_fujitsu_add(struct acpi_device *device)
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 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
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,
},
};

View File

@ -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 */

View File

@ -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,
},
};

View File

@ -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,

View File

@ -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;

View File

@ -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 @@ static int pda_power_probe(struct platform_device *pdev)
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
View 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");

View File

@ -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

View File

@ -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);

View File

@ -8,6 +8,7 @@
*/
#include <linux/fs.h>
#include <asm/page.h> /* for PAGE_SIZE */
#include "befs.h"
#include "super.h"

View File

@ -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));

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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