Merge branch 'rmobile/mmcif' into rmobile-latest
This commit is contained in:
commit
1ad2096c4e
@ -79,10 +79,6 @@
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
||||
<chapter id="clk">
|
||||
<title>Clock Framework Extensions</title>
|
||||
!Iinclude/linux/sh_clk.h
|
||||
</chapter>
|
||||
<chapter id="mach">
|
||||
<title>Machine Specific Interfaces</title>
|
||||
<sect1 id="dreamcast">
|
||||
|
@ -4,33 +4,41 @@ please mail me.
|
||||
Geert Uytterhoeven <geert@linux-m68k.org>
|
||||
|
||||
00-INDEX
|
||||
- this file
|
||||
- this file.
|
||||
arkfb.txt
|
||||
- info on the fbdev driver for ARK Logic chips.
|
||||
aty128fb.txt
|
||||
- info on the ATI Rage128 frame buffer driver.
|
||||
cirrusfb.txt
|
||||
- info on the driver for Cirrus Logic chipsets.
|
||||
cmap_xfbdev.txt
|
||||
- an introduction to fbdev's cmap structures.
|
||||
deferred_io.txt
|
||||
- an introduction to deferred IO.
|
||||
efifb.txt
|
||||
- info on the EFI platform driver for Intel based Apple computers.
|
||||
ep93xx-fb.txt
|
||||
- info on the driver for EP93xx LCD controller.
|
||||
fbcon.txt
|
||||
- intro to and usage guide for the framebuffer console (fbcon).
|
||||
framebuffer.txt
|
||||
- introduction to frame buffer devices.
|
||||
imacfb.txt
|
||||
- info on the generic EFI platform driver for Intel based Macs.
|
||||
gxfb.txt
|
||||
- info on the framebuffer driver for AMD Geode GX2 based processors.
|
||||
intel810.txt
|
||||
- documentation for the Intel 810/815 framebuffer driver.
|
||||
intelfb.txt
|
||||
- docs for Intel 830M/845G/852GM/855GM/865G/915G/945G fb driver.
|
||||
internals.txt
|
||||
- quick overview of frame buffer device internals.
|
||||
lxfb.txt
|
||||
- info on the framebuffer driver for AMD Geode LX based processors.
|
||||
matroxfb.txt
|
||||
- info on the Matrox framebuffer driver for Alpha, Intel and PPC.
|
||||
metronomefb.txt
|
||||
- info on the driver for the Metronome display controller.
|
||||
modedb.txt
|
||||
- info on the video mode database.
|
||||
matroxfb.txt
|
||||
- info on the Matrox frame buffer driver.
|
||||
pvr2fb.txt
|
||||
- info on the PowerVR 2 frame buffer driver.
|
||||
pxafb.txt
|
||||
@ -39,13 +47,23 @@ s3fb.txt
|
||||
- info on the fbdev driver for S3 Trio/Virge chips.
|
||||
sa1100fb.txt
|
||||
- information about the driver for the SA-1100 LCD controller.
|
||||
sh7760fb.txt
|
||||
- info on the SH7760/SH7763 integrated LCDC Framebuffer driver.
|
||||
sisfb.txt
|
||||
- info on the framebuffer device driver for various SiS chips.
|
||||
sstfb.txt
|
||||
- info on the frame buffer driver for 3dfx' Voodoo Graphics boards.
|
||||
tgafb.txt
|
||||
- info on the TGA (DECChip 21030) frame buffer driver
|
||||
- info on the TGA (DECChip 21030) frame buffer driver.
|
||||
tridentfb.txt
|
||||
info on the framebuffer driver for some Trident chip based cards.
|
||||
uvesafb.txt
|
||||
- info on the userspace VESA (VBE2+ compliant) frame buffer device.
|
||||
vesafb.txt
|
||||
- info on the VESA frame buffer device
|
||||
- info on the VESA frame buffer device.
|
||||
viafb.modes
|
||||
- list of modes for VIA Integration Graphic Chip.
|
||||
viafb.txt
|
||||
- info on the VIA Integration Graphic Chip console framebuffer driver.
|
||||
vt8623fb.txt
|
||||
- info on the fb driver for the graphics core in VIA VT8623 chipsets.
|
||||
|
@ -2385,6 +2385,11 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
improve throughput, but will also increase the
|
||||
amount of memory reserved for use by the client.
|
||||
|
||||
swapaccount[=0|1]
|
||||
[KNL] Enable accounting of swap in memory resource
|
||||
controller if no parameter or 1 is given or disable
|
||||
it if 0 is given (See Documentation/cgroups/memory.txt)
|
||||
|
||||
swiotlb= [IA-64] Number of I/O TLB slabs
|
||||
|
||||
switches= [HW,M68k]
|
||||
|
@ -1,32 +0,0 @@
|
||||
Clock framework on SuperH architecture
|
||||
|
||||
The framework on SH extends existing API by the function clk_set_rate_ex,
|
||||
which prototype is as follows:
|
||||
|
||||
clk_set_rate_ex (struct clk *clk, unsigned long rate, int algo_id)
|
||||
|
||||
The algo_id parameter is used to specify algorithm used to recalculate clocks,
|
||||
adjanced to clock, specified as first argument. It is assumed that algo_id==0
|
||||
means no changes to adjanced clock
|
||||
|
||||
Internally, the clk_set_rate_ex forwards request to clk->ops->set_rate method,
|
||||
if it is present in ops structure. The method should set the clock rate and adjust
|
||||
all needed clocks according to the passed algo_id.
|
||||
Exact values for algo_id are machine-dependent. For the sh7722, the following
|
||||
values are defined:
|
||||
|
||||
NO_CHANGE = 0,
|
||||
IUS_N1_N1, /* I:U = N:1, U:Sh = N:1 */
|
||||
IUS_322, /* I:U:Sh = 3:2:2 */
|
||||
IUS_522, /* I:U:Sh = 5:2:2 */
|
||||
IUS_N11, /* I:U:Sh = N:1:1 */
|
||||
SB_N1, /* Sh:B = N:1 */
|
||||
SB3_N1, /* Sh:B3 = N:1 */
|
||||
SB3_32, /* Sh:B3 = 3:2 */
|
||||
SB3_43, /* Sh:B3 = 4:3 */
|
||||
SB3_54, /* Sh:B3 = 5:4 */
|
||||
BP_N1, /* B:P = N:1 */
|
||||
IP_N1 /* I:P = N:1 */
|
||||
|
||||
Each of these constants means relation between clocks that can be set via the FRQCR
|
||||
register
|
@ -2444,10 +2444,12 @@ F: drivers/net/wan/sdla.c
|
||||
FRAMEBUFFER LAYER
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
W: http://linux-fbdev.sourceforge.net/
|
||||
Q: http://patchwork.kernel.org/project/linux-fbdev/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git
|
||||
S: Orphan
|
||||
F: Documentation/fb/
|
||||
F: drivers/video/fb*
|
||||
F: drivers/video/
|
||||
F: include/video/
|
||||
F: include/linux/fb.h
|
||||
|
||||
FREESCALE DMA DRIVER
|
||||
@ -5837,6 +5839,8 @@ M: Chris Metcalf <cmetcalf@tilera.com>
|
||||
W: http://www.tilera.com/scm/
|
||||
S: Supported
|
||||
F: arch/tile/
|
||||
F: drivers/char/hvc_tile.c
|
||||
F: drivers/net/tile/
|
||||
|
||||
TLAN NETWORK DRIVER
|
||||
M: Samuel Chessman <chessman@tux.org>
|
||||
|
@ -1084,6 +1084,6 @@ memdump: mov r12, r0
|
||||
reloc_end:
|
||||
|
||||
.align
|
||||
.section ".stack", "w"
|
||||
.section ".stack", "aw", %nobits
|
||||
user_stack: .space 4096
|
||||
user_stack_end:
|
||||
|
@ -57,7 +57,7 @@ SECTIONS
|
||||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
|
||||
.stack (NOLOAD) : { *(.stack) }
|
||||
.stack : { *(.stack) }
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
|
@ -238,7 +238,7 @@
|
||||
@ Slightly optimised to avoid incrementing the pointer twice
|
||||
usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
|
||||
.if \rept == 2
|
||||
usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort
|
||||
usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
|
||||
.endif
|
||||
|
||||
add\cond \ptr, #\rept * \inc
|
||||
|
@ -13,6 +13,10 @@ typedef struct {
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_ASID
|
||||
#define ASID(mm) ((mm)->context.id & 255)
|
||||
|
||||
/* init_mm.context.id_lock should be initialized. */
|
||||
#define INIT_MM_CONTEXT(name) \
|
||||
.context.id_lock = __SPIN_LOCK_UNLOCKED(name.context.id_lock),
|
||||
#else
|
||||
#define ASID(mm) (0)
|
||||
#endif
|
||||
|
@ -374,6 +374,9 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
|
||||
|
||||
#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
|
||||
|
||||
/* we don't need complex calculations here as the pmd is folded into the pgd */
|
||||
#define pmd_addr_end(addr,end) (end)
|
||||
|
||||
/*
|
||||
* Conversion functions: convert a page and protection to a page entry,
|
||||
* and a page entry and page directory to the page they refer to.
|
||||
|
@ -174,8 +174,8 @@ ENDPROC(_find_next_bit_be)
|
||||
*/
|
||||
.L_found:
|
||||
#if __LINUX_ARM_ARCH__ >= 5
|
||||
rsb r1, r3, #0
|
||||
and r3, r3, r1
|
||||
rsb r0, r3, #0
|
||||
and r3, r3, r0
|
||||
clz r3, r3
|
||||
rsb r3, r3, #31
|
||||
add r0, r2, r3
|
||||
@ -190,5 +190,7 @@ ENDPROC(_find_next_bit_be)
|
||||
addeq r2, r2, #1
|
||||
mov r0, r2
|
||||
#endif
|
||||
cmp r1, r0 @ Clamp to maxbit
|
||||
movlo r0, r1
|
||||
mov pc, lr
|
||||
|
||||
|
@ -11,6 +11,6 @@
|
||||
#ifndef __ASM_ARCH_VMALLOC_H
|
||||
#define __ASM_ARCH_VMALLOC_H
|
||||
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
||||
#endif /* __ASM_ARCH_VMALLOC_H */
|
||||
|
@ -22,4 +22,4 @@
|
||||
* 0xe0000000 to 0xefffffff. This gives us 256 MB of vm space and handles
|
||||
* larger physical memory designs better.
|
||||
*/
|
||||
#define VMALLOC_END 0xf0000000
|
||||
#define VMALLOC_END 0xf0000000UL
|
||||
|
@ -17,4 +17,4 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
@ -7,4 +7,4 @@
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#define VMALLOC_END 0xdf000000
|
||||
#define VMALLOC_END 0xdf000000UL
|
||||
|
@ -7,4 +7,4 @@
|
||||
*/
|
||||
|
||||
|
||||
#define VMALLOC_END 0xf0000000
|
||||
#define VMALLOC_END 0xf0000000UL
|
||||
|
@ -5,6 +5,6 @@
|
||||
#ifndef __ARCH_ARM_VMALLOC_H
|
||||
#define __ARCH_ARM_VMALLOC_H
|
||||
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
||||
#endif
|
||||
|
@ -250,9 +250,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
|
||||
.flags = IMXUART_HAVE_RTSCTS,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_TOUCHSCREEN_ADS7846) \
|
||||
|| defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
|
||||
|
||||
#define ADS7846_PENDOWN (GPIO_PORTD | 25)
|
||||
|
||||
static void ads7846_dev_init(void)
|
||||
@ -273,9 +270,7 @@ static struct ads7846_platform_data ads7846_config __initdata = {
|
||||
.get_pendown_state = ads7846_get_pendown_state,
|
||||
.keep_vref_on = 1,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
|
||||
static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = {
|
||||
[0] = {
|
||||
.modalias = "ads7846",
|
||||
@ -294,7 +289,6 @@ static const struct spi_imx_master eukrea_mbimx27_spi0_data __initconst = {
|
||||
.chipselect = eukrea_mbimx27_spi_cs,
|
||||
.num_chipselect = ARRAY_SIZE(eukrea_mbimx27_spi_cs),
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct i2c_board_info eukrea_mbimx27_i2c_devices[] = {
|
||||
{
|
||||
|
@ -17,4 +17,4 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
@ -16,7 +16,7 @@
|
||||
#ifndef __ASM_ARCH_MSM_VMALLOC_H
|
||||
#define __ASM_ARCH_MSM_VMALLOC_H
|
||||
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -42,9 +42,9 @@ extern const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst;
|
||||
#define imx25_add_mxc_nand(pdata) \
|
||||
imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
|
||||
|
||||
extern const struct imx_spi_imx_data imx25_spi_imx_data[] __initconst;
|
||||
extern const struct imx_spi_imx_data imx25_cspi_data[] __initconst;
|
||||
#define imx25_add_spi_imx(id, pdata) \
|
||||
imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
|
||||
imx_add_spi_imx(&imx25_cspi_data[id], pdata)
|
||||
#define imx25_add_spi_imx0(pdata) imx25_add_spi_imx(0, pdata)
|
||||
#define imx25_add_spi_imx1(pdata) imx25_add_spi_imx(1, pdata)
|
||||
#define imx25_add_spi_imx2(pdata) imx25_add_spi_imx(2, pdata)
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <mach/common.h>
|
||||
#include <mach/iomux-mx3.h>
|
||||
#include <mach/spi.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
@ -59,14 +60,12 @@ static struct spi_board_info pcm037_spi_dev[] = {
|
||||
};
|
||||
|
||||
/* Platform Data for MXC CSPI */
|
||||
#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
|
||||
static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)};
|
||||
|
||||
static const struct spi_imx_master pcm037_spi1_pdata __initconst = {
|
||||
.chipselect = pcm037_spi1_cs,
|
||||
.num_chipselect = ARRAY_SIZE(pcm037_spi1_cs),
|
||||
};
|
||||
#endif
|
||||
|
||||
/* GPIO-keys input device */
|
||||
static struct gpio_keys_button pcm037_gpio_keys[] = {
|
||||
@ -171,7 +170,7 @@ static struct platform_device pcm037_gpio_keys_device = {
|
||||
},
|
||||
};
|
||||
|
||||
static int eet_init_devices(void)
|
||||
static int __init eet_init_devices(void)
|
||||
{
|
||||
if (!machine_is_pcm037() || pcm037_variant() != PCM037_EET)
|
||||
return 0;
|
||||
|
@ -16,4 +16,4 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
@ -17,4 +17,4 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define VMALLOC_END 0xd8000000
|
||||
#define VMALLOC_END 0xd8000000UL
|
||||
|
@ -17,4 +17,4 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define VMALLOC_END 0xf8000000
|
||||
#define VMALLOC_END 0xf8000000UL
|
||||
|
@ -17,4 +17,4 @@
|
||||
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
|
||||
* area for the same reason. ;)
|
||||
*/
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
@ -7,4 +7,4 @@
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#define VMALLOC_END 0xdc000000
|
||||
#define VMALLOC_END 0xdc000000UL
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
* arch/arm/mach-shark/include/mach/vmalloc.h
|
||||
*/
|
||||
#define VMALLOC_END 0xd0000000
|
||||
#define VMALLOC_END 0xd0000000UL
|
||||
|
@ -272,6 +272,15 @@ static struct resource sh_mmcif_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct sh_mmcif_dma sh_mmcif_dma = {
|
||||
.chan_priv_rx = {
|
||||
.slave_id = SHDMA_SLAVE_MMCIF_RX,
|
||||
},
|
||||
.chan_priv_tx = {
|
||||
.slave_id = SHDMA_SLAVE_MMCIF_TX,
|
||||
},
|
||||
};
|
||||
|
||||
static struct sh_mmcif_plat_data sh_mmcif_plat = {
|
||||
.sup_pclk = 0,
|
||||
.ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
@ -279,6 +288,7 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
|
||||
MMC_CAP_8_BIT_DATA |
|
||||
MMC_CAP_NEEDS_POLL,
|
||||
.get_cd = slot_cn7_get_cd,
|
||||
.dma = &sh_mmcif_dma,
|
||||
};
|
||||
|
||||
static struct platform_device sh_mmcif_device = {
|
||||
|
@ -220,8 +220,7 @@ static void pllc2_disable(struct clk *clk)
|
||||
__raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR);
|
||||
}
|
||||
|
||||
static int pllc2_set_rate(struct clk *clk,
|
||||
unsigned long rate, int algo_id)
|
||||
static int pllc2_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long value;
|
||||
int idx;
|
||||
@ -453,8 +452,7 @@ static int fsidiv_enable(struct clk *clk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsidiv_set_rate(struct clk *clk,
|
||||
unsigned long rate, int algo_id)
|
||||
static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
int idx;
|
||||
|
||||
|
@ -455,6 +455,8 @@ enum {
|
||||
SHDMA_SLAVE_SDHI1_TX,
|
||||
SHDMA_SLAVE_SDHI2_RX,
|
||||
SHDMA_SLAVE_SDHI2_TX,
|
||||
SHDMA_SLAVE_MMCIF_RX,
|
||||
SHDMA_SLAVE_MMCIF_TX,
|
||||
};
|
||||
|
||||
extern struct clk sh7372_extal1_clk;
|
||||
|
@ -416,6 +416,16 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
|
||||
.addr = 0xe6870030,
|
||||
.chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
|
||||
.mid_rid = 0xce,
|
||||
}, {
|
||||
.slave_id = SHDMA_SLAVE_MMCIF_TX,
|
||||
.addr = 0xe6bd0034,
|
||||
.chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
|
||||
.mid_rid = 0xd1,
|
||||
}, {
|
||||
.slave_id = SHDMA_SLAVE_MMCIF_RX,
|
||||
.addr = 0xe6bd0034,
|
||||
.chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
|
||||
.mid_rid = 0xd2,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -75,14 +75,14 @@ void __init ux500_init_irq(void)
|
||||
static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
|
||||
{
|
||||
/* wait for the operation to complete */
|
||||
while (readl(reg) & mask)
|
||||
while (readl_relaxed(reg) & mask)
|
||||
;
|
||||
}
|
||||
|
||||
static inline void ux500_cache_sync(void)
|
||||
{
|
||||
void __iomem *base = __io_address(UX500_L2CC_BASE);
|
||||
writel(0, base + L2X0_CACHE_SYNC);
|
||||
writel_relaxed(0, base + L2X0_CACHE_SYNC);
|
||||
ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ static void ux500_l2x0_inv_all(void)
|
||||
uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
|
||||
|
||||
/* invalidate all ways */
|
||||
writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
|
||||
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
|
||||
ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
|
||||
ux500_cache_sync();
|
||||
}
|
||||
|
@ -18,4 +18,4 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#define VMALLOC_END 0xd8000000
|
||||
#define VMALLOC_END 0xd8000000UL
|
||||
|
@ -206,8 +206,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
||||
*/
|
||||
if (pfn_valid(pfn)) {
|
||||
printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leads\n"
|
||||
KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
|
||||
KERN_WARNING "will fail in the next kernel release. Please fix your driver.\n");
|
||||
"to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
|
||||
"will fail in the next kernel release. Please fix your driver.\n");
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
|
@ -12,15 +12,7 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/devices-common.h>
|
||||
#ifdef SDMA_IS_MERGED
|
||||
#include <mach/sdma.h>
|
||||
#else
|
||||
struct sdma_platform_data {
|
||||
int sdma_version;
|
||||
char *cpu_name;
|
||||
int to_version;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct imx_imx_sdma_data {
|
||||
resource_size_t iobase;
|
||||
|
@ -27,6 +27,7 @@ const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
|
||||
imx_spi_imx_data_entry(MX21, CSPI, "imx21-cspi", _id, _hwid, SZ_4K)
|
||||
imx21_cspi_data_entry(0, 1),
|
||||
imx21_cspi_data_entry(1, 2),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_MX25
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2008 STMicroelectronics
|
||||
* Copyright (C) 2010 Alessandro Rubini
|
||||
* Copyright (C) 2010 Linus Walleij for ST-Ericsson
|
||||
*
|
||||
* 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
|
||||
@ -16,11 +17,13 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/cnt32_to_63.h>
|
||||
#include <linux/timer.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include <plat/mtu.h>
|
||||
|
||||
void __iomem *mtu_base; /* ssigned by machine code */
|
||||
void __iomem *mtu_base; /* Assigned by machine code */
|
||||
|
||||
/*
|
||||
* Kernel assumes that sched_clock can be called early
|
||||
@ -48,16 +51,82 @@ static struct clocksource nmdk_clksrc = {
|
||||
/*
|
||||
* Override the global weak sched_clock symbol with this
|
||||
* local implementation which uses the clocksource to get some
|
||||
* better resolution when scheduling the kernel. We accept that
|
||||
* this wraps around for now, since it is just a relative time
|
||||
* stamp. (Inspired by OMAP implementation.)
|
||||
* better resolution when scheduling the kernel.
|
||||
*
|
||||
* Because the hardware timer period may be quite short
|
||||
* (32.3 secs on the 133 MHz MTU timer selection on ux500)
|
||||
* and because cnt32_to_63() needs to be called at least once per
|
||||
* half period to work properly, a kernel keepwarm() timer is set up
|
||||
* to ensure this requirement is always met.
|
||||
*
|
||||
* Also the sched_clock timer will wrap around at some point,
|
||||
* here we set it to run continously for a year.
|
||||
*/
|
||||
#define SCHED_CLOCK_MIN_WRAP 3600*24*365
|
||||
static struct timer_list cnt32_to_63_keepwarm_timer;
|
||||
static u32 sched_mult;
|
||||
static u32 sched_shift;
|
||||
|
||||
unsigned long long notrace sched_clock(void)
|
||||
{
|
||||
return clocksource_cyc2ns(nmdk_clksrc.read(
|
||||
&nmdk_clksrc),
|
||||
nmdk_clksrc.mult,
|
||||
nmdk_clksrc.shift);
|
||||
u64 cycles;
|
||||
|
||||
if (unlikely(!mtu_base))
|
||||
return 0;
|
||||
|
||||
cycles = cnt32_to_63(-readl(mtu_base + MTU_VAL(0)));
|
||||
/*
|
||||
* sched_mult is guaranteed to be even so will
|
||||
* shift out bit 63
|
||||
*/
|
||||
return (cycles * sched_mult) >> sched_shift;
|
||||
}
|
||||
|
||||
/* Just kick sched_clock every so often */
|
||||
static void cnt32_to_63_keepwarm(unsigned long data)
|
||||
{
|
||||
mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
|
||||
(void) sched_clock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a timer to keep sched_clock():s 32_to_63 algorithm warm
|
||||
* once in half a 32bit timer wrap interval.
|
||||
*/
|
||||
static void __init nmdk_sched_clock_init(unsigned long rate)
|
||||
{
|
||||
u32 v;
|
||||
unsigned long delta;
|
||||
u64 days;
|
||||
|
||||
/* Find the apropriate mult and shift factors */
|
||||
clocks_calc_mult_shift(&sched_mult, &sched_shift,
|
||||
rate, NSEC_PER_SEC, SCHED_CLOCK_MIN_WRAP);
|
||||
/* We need to multiply by an even number to get rid of bit 63 */
|
||||
if (sched_mult & 1)
|
||||
sched_mult++;
|
||||
|
||||
/* Let's see what we get, take max counter and scale it */
|
||||
days = (0xFFFFFFFFFFFFFFFFLLU * sched_mult) >> sched_shift;
|
||||
do_div(days, NSEC_PER_SEC);
|
||||
do_div(days, (3600*24));
|
||||
|
||||
pr_info("sched_clock: using %d bits @ %lu Hz wrap in %lu days\n",
|
||||
(64 - sched_shift), rate, (unsigned long) days);
|
||||
|
||||
/*
|
||||
* Program a timer to kick us at half 32bit wraparound
|
||||
* Formula: seconds per wrap = (2^32) / f
|
||||
*/
|
||||
v = 0xFFFFFFFFUL / rate;
|
||||
/* We want half of the wrap time to keep cnt32_to_63 warm */
|
||||
v /= 2;
|
||||
pr_debug("sched_clock: prescaled timer rate: %lu Hz, "
|
||||
"initialize keepwarm timer every %d seconds\n", rate, v);
|
||||
/* Convert seconds to jiffies */
|
||||
delta = msecs_to_jiffies(v*1000);
|
||||
setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, delta);
|
||||
mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + delta));
|
||||
}
|
||||
|
||||
/* Clockevent device: use one-shot mode */
|
||||
@ -161,13 +230,15 @@ void __init nmdk_timer_init(void)
|
||||
writel(0, mtu_base + MTU_BGLR(0));
|
||||
writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
|
||||
|
||||
/* Now the scheduling clock is ready */
|
||||
/* Now the clock source is ready */
|
||||
nmdk_clksrc.read = nmdk_read_timer;
|
||||
|
||||
if (clocksource_register(&nmdk_clksrc))
|
||||
pr_err("timer: failed to initialize clock source %s\n",
|
||||
nmdk_clksrc.name);
|
||||
|
||||
nmdk_sched_clock_init(rate);
|
||||
|
||||
/* Timer 1 is used for events */
|
||||
|
||||
clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
|
||||
|
@ -199,10 +199,13 @@ extern unsigned long get_wchan(struct task_struct *p);
|
||||
#define ARCH_HAS_PREFETCHW
|
||||
static inline void prefetch(void *x)
|
||||
{
|
||||
__asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory");
|
||||
__builtin_prefetch(x, 0, 3);
|
||||
}
|
||||
|
||||
#define prefetchw(x) prefetch(x)
|
||||
static inline void prefetchw(void *x)
|
||||
{
|
||||
__builtin_prefetch(x, 1, 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
@ -110,7 +110,7 @@ static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
|
||||
static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long frqcr3;
|
||||
unsigned int tmp;
|
||||
|
@ -88,7 +88,7 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
|
||||
}
|
||||
|
||||
if (op & CACHEFLUSH_I)
|
||||
flush_cache_all();
|
||||
flush_icache_range(addr, addr+len);
|
||||
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
return 0;
|
||||
|
@ -8,9 +8,9 @@ __kernel_vsyscall:
|
||||
* fill out .eh_frame -- PFM. */
|
||||
.LEND_vsyscall:
|
||||
.size __kernel_vsyscall,.-.LSTART_vsyscall
|
||||
.previous
|
||||
|
||||
.section .eh_frame,"a",@progbits
|
||||
.previous
|
||||
.LCIE:
|
||||
.ualong .LCIE_end - .LCIE_start
|
||||
.LCIE_start:
|
||||
|
@ -329,6 +329,18 @@ endmenu # Tilera-specific configuration
|
||||
|
||||
menu "Bus options"
|
||||
|
||||
config PCI
|
||||
bool "PCI support"
|
||||
default y
|
||||
select PCI_DOMAINS
|
||||
---help---
|
||||
Enable PCI root complex support, so PCIe endpoint devices can
|
||||
be attached to the Tile chip. Many, but not all, PCI devices
|
||||
are supported under Tilera's root complex driver.
|
||||
|
||||
config PCI_DOMAINS
|
||||
bool
|
||||
|
||||
config NO_IOMEM
|
||||
def_bool !PCI
|
||||
|
||||
|
@ -137,4 +137,56 @@ static inline void finv_buffer(void *buffer, size_t size)
|
||||
mb_incoherent();
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush & invalidate a VA range that is homed remotely on a single core,
|
||||
* waiting until the memory controller holds the flushed values.
|
||||
*/
|
||||
static inline void finv_buffer_remote(void *buffer, size_t size)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Flush and invalidate the buffer out of the local L1/L2
|
||||
* and request the home cache to flush and invalidate as well.
|
||||
*/
|
||||
__finv_buffer(buffer, size);
|
||||
|
||||
/*
|
||||
* Wait for the home cache to acknowledge that it has processed
|
||||
* all the flush-and-invalidate requests. This does not mean
|
||||
* that the flushed data has reached the memory controller yet,
|
||||
* but it does mean the home cache is processing the flushes.
|
||||
*/
|
||||
__insn_mf();
|
||||
|
||||
/*
|
||||
* Issue a load to the last cache line, which can't complete
|
||||
* until all the previously-issued flushes to the same memory
|
||||
* controller have also completed. If we weren't striping
|
||||
* memory, that one load would be sufficient, but since we may
|
||||
* be, we also need to back up to the last load issued to
|
||||
* another memory controller, which would be the point where
|
||||
* we crossed an 8KB boundary (the granularity of striping
|
||||
* across memory controllers). Keep backing up and doing this
|
||||
* until we are before the beginning of the buffer, or have
|
||||
* hit all the controllers.
|
||||
*/
|
||||
for (i = 0, p = (char *)buffer + size - 1;
|
||||
i < (1 << CHIP_LOG_NUM_MSHIMS()) && p >= (char *)buffer;
|
||||
++i) {
|
||||
const unsigned long STRIPE_WIDTH = 8192;
|
||||
|
||||
/* Force a load instruction to issue. */
|
||||
*(volatile char *)p;
|
||||
|
||||
/* Jump to end of previous stripe. */
|
||||
p -= STRIPE_WIDTH;
|
||||
p = (char *)((unsigned long)p | (STRIPE_WIDTH - 1));
|
||||
}
|
||||
|
||||
/* Wait for the loads (and thus flushes) to have completed. */
|
||||
__insn_mf();
|
||||
}
|
||||
|
||||
#endif /* _ASM_TILE_CACHEFLUSH_H */
|
||||
|
@ -55,9 +55,6 @@ extern void iounmap(volatile void __iomem *addr);
|
||||
#define ioremap_writethrough(physaddr, size) ioremap(physaddr, size)
|
||||
#define ioremap_fullcache(physaddr, size) ioremap(physaddr, size)
|
||||
|
||||
void __iomem *ioport_map(unsigned long port, unsigned int len);
|
||||
extern inline void ioport_unmap(void __iomem *addr) {}
|
||||
|
||||
#define mmiowb()
|
||||
|
||||
/* Conversion between virtual and physical mappings. */
|
||||
@ -189,12 +186,22 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
|
||||
* we never run, uses them unconditionally.
|
||||
*/
|
||||
|
||||
static inline int ioport_panic(void)
|
||||
static inline long ioport_panic(void)
|
||||
{
|
||||
panic("inb/outb and friends do not exist on tile");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __iomem *ioport_map(unsigned long port, unsigned int len)
|
||||
{
|
||||
return (void __iomem *) ioport_panic();
|
||||
}
|
||||
|
||||
static inline void ioport_unmap(void __iomem *addr)
|
||||
{
|
||||
ioport_panic();
|
||||
}
|
||||
|
||||
static inline u8 inb(unsigned long addr)
|
||||
{
|
||||
return ioport_panic();
|
||||
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_TILE_PCI_BRIDGE_H
|
||||
#define _ASM_TILE_PCI_BRIDGE_H
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
struct device_node;
|
||||
struct pci_controller;
|
||||
|
||||
/*
|
||||
* pci_io_base returns the memory address at which you can access
|
||||
* the I/O space for PCI bus number `bus' (or NULL on error).
|
||||
*/
|
||||
extern void __iomem *pci_bus_io_base(unsigned int bus);
|
||||
extern unsigned long pci_bus_io_base_phys(unsigned int bus);
|
||||
extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
|
||||
|
||||
/* Allocate a new PCI host bridge structure */
|
||||
extern struct pci_controller *pcibios_alloc_controller(void);
|
||||
|
||||
/* Helper function for setting up resources */
|
||||
extern void pci_init_resource(struct resource *res, unsigned long start,
|
||||
unsigned long end, int flags, char *name);
|
||||
|
||||
/* Get the PCI host controller for a bus */
|
||||
extern struct pci_controller *pci_bus_to_hose(int bus);
|
||||
|
||||
/*
|
||||
* Structure of a PCI controller (host bridge)
|
||||
*/
|
||||
struct pci_controller {
|
||||
int index; /* PCI domain number */
|
||||
struct pci_bus *root_bus;
|
||||
|
||||
int first_busno;
|
||||
int last_busno;
|
||||
|
||||
int hv_cfg_fd[2]; /* config{0,1} fds for this PCIe controller */
|
||||
int hv_mem_fd; /* fd to Hypervisor for MMIO operations */
|
||||
|
||||
struct pci_ops *ops;
|
||||
|
||||
int irq_base; /* Base IRQ from the Hypervisor */
|
||||
int plx_gen1; /* flag for PLX Gen 1 configuration */
|
||||
|
||||
/* Address ranges that are routed to this controller/bridge. */
|
||||
struct resource mem_resources[3];
|
||||
};
|
||||
|
||||
static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
|
||||
{
|
||||
return bus->sysdata;
|
||||
}
|
||||
|
||||
extern void setup_indirect_pci_nomap(struct pci_controller *hose,
|
||||
void __iomem *cfg_addr, void __iomem *cfg_data);
|
||||
extern void setup_indirect_pci(struct pci_controller *hose,
|
||||
u32 cfg_addr, u32 cfg_data);
|
||||
extern void setup_grackle(struct pci_controller *hose);
|
||||
|
||||
extern unsigned char common_swizzle(struct pci_dev *, unsigned char *);
|
||||
|
||||
/*
|
||||
* The following code swizzles for exactly one bridge. The routine
|
||||
* common_swizzle below handles multiple bridges. But there are a
|
||||
* some boards that don't follow the PCI spec's suggestion so we
|
||||
* break this piece out separately.
|
||||
*/
|
||||
static inline unsigned char bridge_swizzle(unsigned char pin,
|
||||
unsigned char idsel)
|
||||
{
|
||||
return (((pin-1) + idsel) % 4) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following macro is used to lookup irqs in a standard table
|
||||
* format for those PPC systems that do not already have PCI
|
||||
* interrupts properly routed.
|
||||
*/
|
||||
/* FIXME - double check this */
|
||||
#define PCI_IRQ_TABLE_LOOKUP ({ \
|
||||
long _ctl_ = -1; \
|
||||
if (idsel >= min_idsel && idsel <= max_idsel && pin <= irqs_per_slot) \
|
||||
_ctl_ = pci_irq_table[idsel - min_idsel][pin-1]; \
|
||||
_ctl_; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Scan the buses below a given PCI host bridge and assign suitable
|
||||
* resources to all devices found.
|
||||
*/
|
||||
extern int pciauto_bus_scan(struct pci_controller *, int);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern unsigned long pci_address_to_pio(phys_addr_t address);
|
||||
#else
|
||||
static inline unsigned long pci_address_to_pio(phys_addr_t address)
|
||||
{
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_TILE_PCI_BRIDGE_H */
|
@ -15,7 +15,29 @@
|
||||
#ifndef _ASM_TILE_PCI_H
|
||||
#define _ASM_TILE_PCI_H
|
||||
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
/*
|
||||
* Structure of a PCI controller (host bridge)
|
||||
*/
|
||||
struct pci_controller {
|
||||
int index; /* PCI domain number */
|
||||
struct pci_bus *root_bus;
|
||||
|
||||
int first_busno;
|
||||
int last_busno;
|
||||
|
||||
int hv_cfg_fd[2]; /* config{0,1} fds for this PCIe controller */
|
||||
int hv_mem_fd; /* fd to Hypervisor for MMIO operations */
|
||||
|
||||
struct pci_ops *ops;
|
||||
|
||||
int irq_base; /* Base IRQ from the Hypervisor */
|
||||
int plx_gen1; /* flag for PLX Gen 1 configuration */
|
||||
|
||||
/* Address ranges that are routed to this controller/bridge. */
|
||||
struct resource mem_resources[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* The hypervisor maps the entirety of CPA-space as bus addresses, so
|
||||
@ -24,57 +46,13 @@
|
||||
*/
|
||||
#define PCI_DMA_BUS_IS_PHYS 1
|
||||
|
||||
struct pci_controller *pci_bus_to_hose(int bus);
|
||||
unsigned char __init common_swizzle(struct pci_dev *dev, unsigned char *pinp);
|
||||
int __init tile_pci_init(void);
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
|
||||
static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
|
||||
|
||||
void __devinit pcibios_fixup_bus(struct pci_bus *bus);
|
||||
|
||||
int __devinit _tile_cfg_read(struct pci_controller *hose,
|
||||
int bus,
|
||||
int slot,
|
||||
int function,
|
||||
int offset,
|
||||
int size,
|
||||
u32 *val);
|
||||
int __devinit _tile_cfg_write(struct pci_controller *hose,
|
||||
int bus,
|
||||
int slot,
|
||||
int function,
|
||||
int offset,
|
||||
int size,
|
||||
u32 val);
|
||||
|
||||
/*
|
||||
* These are used to to config reads and writes in the early stages of
|
||||
* setup before the driver infrastructure has been set up enough to be
|
||||
* able to do config reads and writes.
|
||||
*/
|
||||
#define early_cfg_read(where, size, value) \
|
||||
_tile_cfg_read(controller, \
|
||||
current_bus, \
|
||||
pci_slot, \
|
||||
pci_fn, \
|
||||
where, \
|
||||
size, \
|
||||
value)
|
||||
|
||||
#define early_cfg_write(where, size, value) \
|
||||
_tile_cfg_write(controller, \
|
||||
current_bus, \
|
||||
pci_slot, \
|
||||
pci_fn, \
|
||||
where, \
|
||||
size, \
|
||||
value)
|
||||
|
||||
|
||||
|
||||
#define PCICFG_BYTE 1
|
||||
#define PCICFG_WORD 2
|
||||
#define PCICFG_DWORD 4
|
||||
|
||||
#define TILE_NUM_PCIE 2
|
||||
|
||||
#define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
|
||||
@ -88,33 +66,33 @@ static inline int pci_proc_domain(struct pci_bus *bus)
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O space is currently not supported.
|
||||
* pcibios_assign_all_busses() tells whether or not the bus numbers
|
||||
* should be reassigned, in case the BIOS didn't do it correctly, or
|
||||
* in case we don't have a BIOS and we want to let Linux do it.
|
||||
*/
|
||||
static inline int pcibios_assign_all_busses(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TILE_PCIE_LOWER_IO 0x0
|
||||
#define TILE_PCIE_UPPER_IO 0x10000
|
||||
#define TILE_PCIE_PCIE_IO_SIZE 0x0000FFFF
|
||||
|
||||
#define _PAGE_NO_CACHE 0
|
||||
#define _PAGE_GUARDED 0
|
||||
|
||||
|
||||
#define pcibios_assign_all_busses() pci_assign_all_buses
|
||||
extern int pci_assign_all_buses;
|
||||
|
||||
/*
|
||||
* No special bus mastering setup handling.
|
||||
*/
|
||||
static inline void pcibios_set_master(struct pci_dev *dev)
|
||||
{
|
||||
/* No special bus mastering setup handling */
|
||||
}
|
||||
|
||||
#define PCIBIOS_MIN_MEM 0
|
||||
#define PCIBIOS_MIN_IO TILE_PCIE_LOWER_IO
|
||||
#define PCIBIOS_MIN_IO 0
|
||||
|
||||
/*
|
||||
* This flag tells if the platform is TILEmpower that needs
|
||||
* special configuration for the PLX switch chip.
|
||||
*/
|
||||
extern int blade_pci;
|
||||
extern int tile_plx_gen1;
|
||||
|
||||
/* Use any cpu for PCI. */
|
||||
#define cpumask_of_pcibus(bus) cpu_online_mask
|
||||
|
||||
/* implement the pci_ DMA API in terms of the generic device dma_ one */
|
||||
#include <asm-generic/pci-dma-compat.h>
|
||||
@ -122,7 +100,4 @@ extern int blade_pci;
|
||||
/* generic pci stuff */
|
||||
#include <asm-generic/pci.h>
|
||||
|
||||
/* Use any cpu for PCI. */
|
||||
#define cpumask_of_pcibus(bus) cpu_online_mask
|
||||
|
||||
#endif /* _ASM_TILE_PCI_H */
|
||||
|
@ -292,8 +292,18 @@ extern int kstack_hash;
|
||||
/* Are we using huge pages in the TLB for kernel data? */
|
||||
extern int kdata_huge;
|
||||
|
||||
/* Support standard Linux prefetching. */
|
||||
#define ARCH_HAS_PREFETCH
|
||||
#define prefetch(x) __builtin_prefetch(x)
|
||||
#define PREFETCH_STRIDE CHIP_L2_LINE_SIZE()
|
||||
|
||||
/* Bring a value into the L1D, faulting the TLB if necessary. */
|
||||
#ifdef __tilegx__
|
||||
#define prefetch_L1(x) __insn_prefetch_l1_fault((void *)(x))
|
||||
#else
|
||||
#define prefetch_L1(x) __insn_prefetch_L1((void *)(x))
|
||||
#endif
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
/* Do some slow action (e.g. read a slow SPR). */
|
||||
|
300
arch/tile/include/hv/drv_xgbe_impl.h
Normal file
300
arch/tile/include/hv/drv_xgbe_impl.h
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drivers/xgbe/impl.h
|
||||
* Implementation details for the NetIO library.
|
||||
*/
|
||||
|
||||
#ifndef __DRV_XGBE_IMPL_H__
|
||||
#define __DRV_XGBE_IMPL_H__
|
||||
|
||||
#include <hv/netio_errors.h>
|
||||
#include <hv/netio_intf.h>
|
||||
#include <hv/drv_xgbe_intf.h>
|
||||
|
||||
|
||||
/** How many groups we have (log2). */
|
||||
#define LOG2_NUM_GROUPS (12)
|
||||
/** How many groups we have. */
|
||||
#define NUM_GROUPS (1 << LOG2_NUM_GROUPS)
|
||||
|
||||
/** Number of output requests we'll buffer per tile. */
|
||||
#define EPP_REQS_PER_TILE (32)
|
||||
|
||||
/** Words used in an eDMA command without checksum acceleration. */
|
||||
#define EDMA_WDS_NO_CSUM 8
|
||||
/** Words used in an eDMA command with checksum acceleration. */
|
||||
#define EDMA_WDS_CSUM 10
|
||||
/** Total available words in the eDMA command FIFO. */
|
||||
#define EDMA_WDS_TOTAL 128
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: These definitions are internal and should have underscores!
|
||||
* NOTE: The actual numeric values here are intentional and allow us to
|
||||
* optimize the concept "if small ... else if large ... else ...", by
|
||||
* checking for the low bit being set, and then for non-zero.
|
||||
* These are used as array indices, so they must have the values (0, 1, 2)
|
||||
* in some order.
|
||||
*/
|
||||
#define SIZE_SMALL (1) /**< Small packet queue. */
|
||||
#define SIZE_LARGE (2) /**< Large packet queue. */
|
||||
#define SIZE_JUMBO (0) /**< Jumbo packet queue. */
|
||||
|
||||
/** The number of "SIZE_xxx" values. */
|
||||
#define NETIO_NUM_SIZES 3
|
||||
|
||||
|
||||
/*
|
||||
* Default numbers of packets for IPP drivers. These values are chosen
|
||||
* such that CIPP1 will not overflow its L2 cache.
|
||||
*/
|
||||
|
||||
/** The default number of small packets. */
|
||||
#define NETIO_DEFAULT_SMALL_PACKETS 2750
|
||||
/** The default number of large packets. */
|
||||
#define NETIO_DEFAULT_LARGE_PACKETS 2500
|
||||
/** The default number of jumbo packets. */
|
||||
#define NETIO_DEFAULT_JUMBO_PACKETS 250
|
||||
|
||||
|
||||
/** Log2 of the size of a memory arena. */
|
||||
#define NETIO_ARENA_SHIFT 24 /* 16 MB */
|
||||
/** Size of a memory arena. */
|
||||
#define NETIO_ARENA_SIZE (1 << NETIO_ARENA_SHIFT)
|
||||
|
||||
|
||||
/** A queue of packets.
|
||||
*
|
||||
* This structure partially defines a queue of packets waiting to be
|
||||
* processed. The queue as a whole is written to by an interrupt handler and
|
||||
* read by non-interrupt code; this data structure is what's touched by the
|
||||
* interrupt handler. The other part of the queue state, the read offset, is
|
||||
* kept in user space, not in hypervisor space, so it is in a separate data
|
||||
* structure.
|
||||
*
|
||||
* The read offset (__packet_receive_read in the user part of the queue
|
||||
* structure) points to the next packet to be read. When the read offset is
|
||||
* equal to the write offset, the queue is empty; therefore the queue must
|
||||
* contain one more slot than the required maximum queue size.
|
||||
*
|
||||
* Here's an example of all 3 state variables and what they mean. All
|
||||
* pointers move left to right.
|
||||
*
|
||||
* @code
|
||||
* I I V V V V I I I I
|
||||
* 0 1 2 3 4 5 6 7 8 9 10
|
||||
* ^ ^ ^ ^
|
||||
* | | |
|
||||
* | | __last_packet_plus_one
|
||||
* | __buffer_write
|
||||
* __packet_receive_read
|
||||
* @endcode
|
||||
*
|
||||
* This queue has 10 slots, and thus can hold 9 packets (_last_packet_plus_one
|
||||
* = 10). The read pointer is at 2, and the write pointer is at 6; thus,
|
||||
* there are valid, unread packets in slots 2, 3, 4, and 5. The remaining
|
||||
* slots are invalid (do not contain a packet).
|
||||
*/
|
||||
typedef struct {
|
||||
/** Byte offset of the next notify packet to be written: zero for the first
|
||||
* packet on the queue, sizeof (netio_pkt_t) for the second packet on the
|
||||
* queue, etc. */
|
||||
volatile uint32_t __packet_write;
|
||||
|
||||
/** Offset of the packet after the last valid packet (i.e., when any
|
||||
* pointer is incremented to this value, it wraps back to zero). */
|
||||
uint32_t __last_packet_plus_one;
|
||||
}
|
||||
__netio_packet_queue_t;
|
||||
|
||||
|
||||
/** A queue of buffers.
|
||||
*
|
||||
* This structure partially defines a queue of empty buffers which have been
|
||||
* obtained via requests to the IPP. (The elements of the queue are packet
|
||||
* handles, which are transformed into a full netio_pkt_t when the buffer is
|
||||
* retrieved.) The queue as a whole is written to by an interrupt handler and
|
||||
* read by non-interrupt code; this data structure is what's touched by the
|
||||
* interrupt handler. The other parts of the queue state, the read offset and
|
||||
* requested write offset, are kept in user space, not in hypervisor space, so
|
||||
* they are in a separate data structure.
|
||||
*
|
||||
* The read offset (__buffer_read in the user part of the queue structure)
|
||||
* points to the next buffer to be read. When the read offset is equal to the
|
||||
* write offset, the queue is empty; therefore the queue must contain one more
|
||||
* slot than the required maximum queue size.
|
||||
*
|
||||
* The requested write offset (__buffer_requested_write in the user part of
|
||||
* the queue structure) points to the slot which will hold the next buffer we
|
||||
* request from the IPP, once we get around to sending such a request. When
|
||||
* the requested write offset is equal to the write offset, no requests for
|
||||
* new buffers are outstanding; when the requested write offset is one greater
|
||||
* than the read offset, no more requests may be sent.
|
||||
*
|
||||
* Note that, unlike the packet_queue, the buffer_queue places incoming
|
||||
* buffers at decreasing addresses. This makes the check for "is it time to
|
||||
* wrap the buffer pointer" cheaper in the assembly code which receives new
|
||||
* buffers, and means that the value which defines the queue size,
|
||||
* __last_buffer, is different than in the packet queue. Also, the offset
|
||||
* used in the packet_queue is already scaled by the size of a packet; here we
|
||||
* use unscaled slot indices for the offsets. (These differences are
|
||||
* historical, and in the future it's possible that the packet_queue will look
|
||||
* more like this queue.)
|
||||
*
|
||||
* @code
|
||||
* Here's an example of all 4 state variables and what they mean. Remember:
|
||||
* all pointers move right to left.
|
||||
*
|
||||
* V V V I I R R V V V
|
||||
* 0 1 2 3 4 5 6 7 8 9
|
||||
* ^ ^ ^ ^
|
||||
* | | | |
|
||||
* | | | __last_buffer
|
||||
* | | __buffer_write
|
||||
* | __buffer_requested_write
|
||||
* __buffer_read
|
||||
* @endcode
|
||||
*
|
||||
* This queue has 10 slots, and thus can hold 9 buffers (_last_buffer = 9).
|
||||
* The read pointer is at 2, and the write pointer is at 6; thus, there are
|
||||
* valid, unread buffers in slots 2, 1, 0, 9, 8, and 7. The requested write
|
||||
* pointer is at 4; thus, requests have been made to the IPP for buffers which
|
||||
* will be placed in slots 6 and 5 when they arrive. Finally, the remaining
|
||||
* slots are invalid (do not contain a buffer).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Ordinal number of the next buffer to be written: 0 for the first slot in
|
||||
* the queue, 1 for the second slot in the queue, etc. */
|
||||
volatile uint32_t __buffer_write;
|
||||
|
||||
/** Ordinal number of the last buffer (i.e., when any pointer is decremented
|
||||
* below zero, it is reloaded with this value). */
|
||||
uint32_t __last_buffer;
|
||||
}
|
||||
__netio_buffer_queue_t;
|
||||
|
||||
|
||||
/**
|
||||
* An object for providing Ethernet packets to a process.
|
||||
*/
|
||||
typedef struct __netio_queue_impl_t
|
||||
{
|
||||
/** The queue of packets waiting to be received. */
|
||||
__netio_packet_queue_t __packet_receive_queue;
|
||||
/** The intr bit mask that IDs this device. */
|
||||
unsigned int __intr_id;
|
||||
/** Offset to queues of empty buffers, one per size. */
|
||||
uint32_t __buffer_queue[NETIO_NUM_SIZES];
|
||||
/** The address of the first EPP tile, or -1 if no EPP. */
|
||||
/* ISSUE: Actually this is always "0" or "~0". */
|
||||
uint32_t __epp_location;
|
||||
/** The queue ID that this queue represents. */
|
||||
unsigned int __queue_id;
|
||||
/** Number of acknowledgements received. */
|
||||
volatile uint32_t __acks_received;
|
||||
/** Last completion number received for packet_sendv. */
|
||||
volatile uint32_t __last_completion_rcv;
|
||||
/** Number of packets allowed to be outstanding. */
|
||||
uint32_t __max_outstanding;
|
||||
/** First VA available for packets. */
|
||||
void* __va_0;
|
||||
/** First VA in second range available for packets. */
|
||||
void* __va_1;
|
||||
/** Padding to align the "__packets" field to the size of a netio_pkt_t. */
|
||||
uint32_t __padding[3];
|
||||
/** The packets themselves. */
|
||||
netio_pkt_t __packets[0];
|
||||
}
|
||||
netio_queue_impl_t;
|
||||
|
||||
|
||||
/**
|
||||
* An object for managing the user end of a NetIO queue.
|
||||
*/
|
||||
typedef struct __netio_queue_user_impl_t
|
||||
{
|
||||
/** The next incoming packet to be read. */
|
||||
uint32_t __packet_receive_read;
|
||||
/** The next empty buffers to be read, one index per size. */
|
||||
uint8_t __buffer_read[NETIO_NUM_SIZES];
|
||||
/** Where the empty buffer we next request from the IPP will go, one index
|
||||
* per size. */
|
||||
uint8_t __buffer_requested_write[NETIO_NUM_SIZES];
|
||||
/** PCIe interface flag. */
|
||||
uint8_t __pcie;
|
||||
/** Number of packets left to be received before we send a credit update. */
|
||||
uint32_t __receive_credit_remaining;
|
||||
/** Value placed in __receive_credit_remaining when it reaches zero. */
|
||||
uint32_t __receive_credit_interval;
|
||||
/** First fast I/O routine index. */
|
||||
uint32_t __fastio_index;
|
||||
/** Number of acknowledgements expected. */
|
||||
uint32_t __acks_outstanding;
|
||||
/** Last completion number requested. */
|
||||
uint32_t __last_completion_req;
|
||||
/** File descriptor for driver. */
|
||||
int __fd;
|
||||
}
|
||||
netio_queue_user_impl_t;
|
||||
|
||||
|
||||
#define NETIO_GROUP_CHUNK_SIZE 64 /**< Max # groups in one IPP request */
|
||||
#define NETIO_BUCKET_CHUNK_SIZE 64 /**< Max # buckets in one IPP request */
|
||||
|
||||
|
||||
/** Internal structure used to convey packet send information to the
|
||||
* hypervisor. FIXME: Actually, it's not used for that anymore, but
|
||||
* netio_packet_send() still uses it internally.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t flags; /**< Packet flags (__NETIO_SEND_FLG_xxx) */
|
||||
uint16_t transfer_size; /**< Size of packet */
|
||||
uint32_t va; /**< VA of start of packet */
|
||||
__netio_pkt_handle_t handle; /**< Packet handle */
|
||||
uint32_t csum0; /**< First checksum word */
|
||||
uint32_t csum1; /**< Second checksum word */
|
||||
}
|
||||
__netio_send_cmd_t;
|
||||
|
||||
|
||||
/** Flags used in two contexts:
|
||||
* - As the "flags" member in the __netio_send_cmd_t, above; used only
|
||||
* for netio_pkt_send_{prepare,commit}.
|
||||
* - As part of the flags passed to the various send packet fast I/O calls.
|
||||
*/
|
||||
|
||||
/** Need acknowledgement on this packet. Note that some code in the
|
||||
* normal send_pkt fast I/O handler assumes that this is equal to 1. */
|
||||
#define __NETIO_SEND_FLG_ACK 0x1
|
||||
|
||||
/** Do checksum on this packet. (Only used with the __netio_send_cmd_t;
|
||||
* normal packet sends use a special fast I/O index to denote checksumming,
|
||||
* and multi-segment sends test the checksum descriptor.) */
|
||||
#define __NETIO_SEND_FLG_CSUM 0x2
|
||||
|
||||
/** Get a completion on this packet. Only used with multi-segment sends. */
|
||||
#define __NETIO_SEND_FLG_COMPLETION 0x4
|
||||
|
||||
/** Position of the number-of-extra-segments value in the flags word.
|
||||
Only used with multi-segment sends. */
|
||||
#define __NETIO_SEND_FLG_XSEG_SHIFT 3
|
||||
|
||||
/** Width of the number-of-extra-segments value in the flags word. */
|
||||
#define __NETIO_SEND_FLG_XSEG_WIDTH 2
|
||||
|
||||
#endif /* __DRV_XGBE_IMPL_H__ */
|
615
arch/tile/include/hv/drv_xgbe_intf.h
Normal file
615
arch/tile/include/hv/drv_xgbe_intf.h
Normal file
@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drv_xgbe_intf.h
|
||||
* Interface to the hypervisor XGBE driver.
|
||||
*/
|
||||
|
||||
#ifndef __DRV_XGBE_INTF_H__
|
||||
#define __DRV_XGBE_INTF_H__
|
||||
|
||||
/**
|
||||
* An object for forwarding VAs and PAs to the hypervisor.
|
||||
* @ingroup types
|
||||
*
|
||||
* This allows the supervisor to specify a number of areas of memory to
|
||||
* store packet buffers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The physical address of the memory. */
|
||||
HV_PhysAddr pa;
|
||||
/** Page table entry for the memory. This is only used to derive the
|
||||
* memory's caching mode; the PA bits are ignored. */
|
||||
HV_PTE pte;
|
||||
/** The virtual address of the memory. */
|
||||
HV_VirtAddr va;
|
||||
/** Size (in bytes) of the memory area. */
|
||||
int size;
|
||||
|
||||
}
|
||||
netio_ipp_address_t;
|
||||
|
||||
/** The various pread/pwrite offsets into the hypervisor-level driver.
|
||||
* @ingroup types
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Inform the Linux driver of the address of the NetIO arena memory.
|
||||
* This offset is actually only used to convey information from netio
|
||||
* to the Linux driver; it never makes it from there to the hypervisor.
|
||||
* Write-only; takes a uint32_t specifying the VA address. */
|
||||
NETIO_FIXED_ADDR = 0x5000000000000000ULL,
|
||||
|
||||
/** Inform the Linux driver of the size of the NetIO arena memory.
|
||||
* This offset is actually only used to convey information from netio
|
||||
* to the Linux driver; it never makes it from there to the hypervisor.
|
||||
* Write-only; takes a uint32_t specifying the VA size. */
|
||||
NETIO_FIXED_SIZE = 0x5100000000000000ULL,
|
||||
|
||||
/** Register current tile with IPP. Write then read: write, takes a
|
||||
* netio_input_config_t, read returns a pointer to a netio_queue_impl_t. */
|
||||
NETIO_IPP_INPUT_REGISTER_OFF = 0x6000000000000000ULL,
|
||||
|
||||
/** Unregister current tile from IPP. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_INPUT_UNREGISTER_OFF = 0x6100000000000000ULL,
|
||||
|
||||
/** Start packets flowing. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_INPUT_INIT_OFF = 0x6200000000000000ULL,
|
||||
|
||||
/** Stop packets flowing. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_INPUT_UNINIT_OFF = 0x6300000000000000ULL,
|
||||
|
||||
/** Configure group (typically we group on VLAN). Write-only: takes an
|
||||
* array of netio_group_t's, low 24 bits of the offset is the base group
|
||||
* number times the size of a netio_group_t. */
|
||||
NETIO_IPP_INPUT_GROUP_CFG_OFF = 0x6400000000000000ULL,
|
||||
|
||||
/** Configure bucket. Write-only: takes an array of netio_bucket_t's, low
|
||||
* 24 bits of the offset is the base bucket number times the size of a
|
||||
* netio_bucket_t. */
|
||||
NETIO_IPP_INPUT_BUCKET_CFG_OFF = 0x6500000000000000ULL,
|
||||
|
||||
/** Get/set a parameter. Read or write: read or write data is the parameter
|
||||
* value, low 32 bits of the offset is a __netio_getset_offset_t. */
|
||||
NETIO_IPP_PARAM_OFF = 0x6600000000000000ULL,
|
||||
|
||||
/** Get fast I/O index. Read-only; returns a 4-byte base index value. */
|
||||
NETIO_IPP_GET_FASTIO_OFF = 0x6700000000000000ULL,
|
||||
|
||||
/** Configure hijack IP address. Packets with this IPv4 dest address
|
||||
* go to bucket NETIO_NUM_BUCKETS - 1. Write-only: takes an IP address
|
||||
* in some standard form. FIXME: Define the form! */
|
||||
NETIO_IPP_INPUT_HIJACK_CFG_OFF = 0x6800000000000000ULL,
|
||||
|
||||
/**
|
||||
* Offsets beyond this point are reserved for the supervisor (although that
|
||||
* enforcement must be done by the supervisor driver itself).
|
||||
*/
|
||||
NETIO_IPP_USER_MAX_OFF = 0x6FFFFFFFFFFFFFFFULL,
|
||||
|
||||
/** Register I/O memory. Write-only, takes a netio_ipp_address_t. */
|
||||
NETIO_IPP_IOMEM_REGISTER_OFF = 0x7000000000000000ULL,
|
||||
|
||||
/** Unregister I/O memory. Write-only, takes a netio_ipp_address_t. */
|
||||
NETIO_IPP_IOMEM_UNREGISTER_OFF = 0x7100000000000000ULL,
|
||||
|
||||
/* Offsets greater than 0x7FFFFFFF can't be used directly from Linux
|
||||
* userspace code due to limitations in the pread/pwrite syscalls. */
|
||||
|
||||
/** Drain LIPP buffers. */
|
||||
NETIO_IPP_DRAIN_OFF = 0xFA00000000000000ULL,
|
||||
|
||||
/** Supply a netio_ipp_address_t to be used as shared memory for the
|
||||
* LEPP command queue. */
|
||||
NETIO_EPP_SHM_OFF = 0xFB00000000000000ULL,
|
||||
|
||||
/* 0xFC... is currently unused. */
|
||||
|
||||
/** Stop IPP/EPP tiles. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_STOP_SHIM_OFF = 0xFD00000000000000ULL,
|
||||
|
||||
/** Start IPP/EPP tiles. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_START_SHIM_OFF = 0xFE00000000000000ULL,
|
||||
|
||||
/** Supply packet arena. Write-only, takes an array of
|
||||
* netio_ipp_address_t values. */
|
||||
NETIO_IPP_ADDRESS_OFF = 0xFF00000000000000ULL,
|
||||
} netio_hv_offset_t;
|
||||
|
||||
/** Extract the base offset from an offset */
|
||||
#define NETIO_BASE_OFFSET(off) ((off) & 0xFF00000000000000ULL)
|
||||
/** Extract the local offset from an offset */
|
||||
#define NETIO_LOCAL_OFFSET(off) ((off) & 0x00FFFFFFFFFFFFFFULL)
|
||||
|
||||
|
||||
/**
|
||||
* Get/set offset.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t addr:48; /**< Class-specific address */
|
||||
unsigned int class:8; /**< Class (e.g., NETIO_PARAM) */
|
||||
unsigned int opcode:8; /**< High 8 bits of NETIO_IPP_PARAM_OFF */
|
||||
}
|
||||
bits; /**< Bitfields */
|
||||
uint64_t word; /**< Aggregated value to use as the offset */
|
||||
}
|
||||
__netio_getset_offset_t;
|
||||
|
||||
/**
|
||||
* Fast I/O index offsets (must be contiguous).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NETIO_FASTIO_ALLOCATE = 0, /**< Get empty packet buffer */
|
||||
NETIO_FASTIO_FREE_BUFFER = 1, /**< Give buffer back to IPP */
|
||||
NETIO_FASTIO_RETURN_CREDITS = 2, /**< Give credits to IPP */
|
||||
NETIO_FASTIO_SEND_PKT_NOCK = 3, /**< Send a packet, no checksum */
|
||||
NETIO_FASTIO_SEND_PKT_CK = 4, /**< Send a packet, with checksum */
|
||||
NETIO_FASTIO_SEND_PKT_VEC = 5, /**< Send a vector of packets */
|
||||
NETIO_FASTIO_SENDV_PKT = 6, /**< Sendv one packet */
|
||||
NETIO_FASTIO_NUM_INDEX = 7, /**< Total number of fast I/O indices */
|
||||
} netio_fastio_index_t;
|
||||
|
||||
/** 3-word return type for Fast I/O call. */
|
||||
typedef struct
|
||||
{
|
||||
int err; /**< Error code. */
|
||||
uint32_t val0; /**< Value. Meaning depends upon the specific call. */
|
||||
uint32_t val1; /**< Value. Meaning depends upon the specific call. */
|
||||
} netio_fastio_rv3_t;
|
||||
|
||||
/** 0-argument fast I/O call */
|
||||
int __netio_fastio0(uint32_t fastio_index);
|
||||
/** 1-argument fast I/O call */
|
||||
int __netio_fastio1(uint32_t fastio_index, uint32_t arg0);
|
||||
/** 3-argument fast I/O call, 2-word return value */
|
||||
netio_fastio_rv3_t __netio_fastio3_rv3(uint32_t fastio_index, uint32_t arg0,
|
||||
uint32_t arg1, uint32_t arg2);
|
||||
/** 4-argument fast I/O call */
|
||||
int __netio_fastio4(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3);
|
||||
/** 6-argument fast I/O call */
|
||||
int __netio_fastio6(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5);
|
||||
/** 9-argument fast I/O call */
|
||||
int __netio_fastio9(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
|
||||
uint32_t arg6, uint32_t arg7, uint32_t arg8);
|
||||
|
||||
/** Allocate an empty packet.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param size Size of the packet to allocate.
|
||||
*/
|
||||
#define __netio_fastio_allocate(fastio_index, size) \
|
||||
__netio_fastio1((fastio_index) + NETIO_FASTIO_ALLOCATE, size)
|
||||
|
||||
/** Free a buffer.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param handle Handle for the packet to free.
|
||||
*/
|
||||
#define __netio_fastio_free_buffer(fastio_index, handle) \
|
||||
__netio_fastio1((fastio_index) + NETIO_FASTIO_FREE_BUFFER, handle)
|
||||
|
||||
/** Increment our receive credits.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param credits Number of credits to add.
|
||||
*/
|
||||
#define __netio_fastio_return_credits(fastio_index, credits) \
|
||||
__netio_fastio1((fastio_index) + NETIO_FASTIO_RETURN_CREDITS, credits)
|
||||
|
||||
/** Send packet, no checksum.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param ackflag Nonzero if we want an ack.
|
||||
* @param size Size of the packet.
|
||||
* @param va Virtual address of start of packet.
|
||||
* @param handle Packet handle.
|
||||
*/
|
||||
#define __netio_fastio_send_pkt_nock(fastio_index, ackflag, size, va, handle) \
|
||||
__netio_fastio4((fastio_index) + NETIO_FASTIO_SEND_PKT_NOCK, ackflag, \
|
||||
size, va, handle)
|
||||
|
||||
/** Send packet, calculate checksum.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param ackflag Nonzero if we want an ack.
|
||||
* @param size Size of the packet.
|
||||
* @param va Virtual address of start of packet.
|
||||
* @param handle Packet handle.
|
||||
* @param csum0 Shim checksum header.
|
||||
* @param csum1 Checksum seed.
|
||||
*/
|
||||
#define __netio_fastio_send_pkt_ck(fastio_index, ackflag, size, va, handle, \
|
||||
csum0, csum1) \
|
||||
__netio_fastio6((fastio_index) + NETIO_FASTIO_SEND_PKT_CK, ackflag, \
|
||||
size, va, handle, csum0, csum1)
|
||||
|
||||
|
||||
/** Format for the "csum0" argument to the __netio_fastio_send routines
|
||||
* and LEPP. Note that this is currently exactly identical to the
|
||||
* ShimProtocolOffloadHeader.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int start_byte:7; /**< The first byte to be checksummed */
|
||||
unsigned int count:14; /**< Number of bytes to be checksummed. */
|
||||
unsigned int destination_byte:7; /**< The byte to write the checksum to. */
|
||||
unsigned int reserved:4; /**< Reserved. */
|
||||
} bits; /**< Decomposed method of access. */
|
||||
unsigned int word; /**< To send out the IDN. */
|
||||
} __netio_checksum_header_t;
|
||||
|
||||
|
||||
/** Sendv packet with 1 or 2 segments.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param flags Ack/csum/notify flags in low 3 bits; number of segments minus
|
||||
* 1 in next 2 bits; expected checksum in high 16 bits.
|
||||
* @param confno Confirmation number to request, if notify flag set.
|
||||
* @param csum0 Checksum descriptor; if zero, no checksum.
|
||||
* @param va_F Virtual address of first segment.
|
||||
* @param va_L Virtual address of last segment, if 2 segments.
|
||||
* @param len_F_L Length of first segment in low 16 bits; length of last
|
||||
* segment, if 2 segments, in high 16 bits.
|
||||
*/
|
||||
#define __netio_fastio_sendv_pkt_1_2(fastio_index, flags, confno, csum0, \
|
||||
va_F, va_L, len_F_L) \
|
||||
__netio_fastio6((fastio_index) + NETIO_FASTIO_SENDV_PKT, flags, confno, \
|
||||
csum0, va_F, va_L, len_F_L)
|
||||
|
||||
/** Send packet on PCIe interface.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param flags Ack/csum/notify flags in low 3 bits.
|
||||
* @param confno Confirmation number to request, if notify flag set.
|
||||
* @param csum0 Checksum descriptor; Hard wired 0, not needed for PCIe.
|
||||
* @param va_F Virtual address of the packet buffer.
|
||||
* @param va_L Virtual address of last segment, if 2 segments. Hard wired 0.
|
||||
* @param len_F_L Length of the packet buffer in low 16 bits.
|
||||
*/
|
||||
#define __netio_fastio_send_pcie_pkt(fastio_index, flags, confno, csum0, \
|
||||
va_F, va_L, len_F_L) \
|
||||
__netio_fastio6((fastio_index) + PCIE_FASTIO_SENDV_PKT, flags, confno, \
|
||||
csum0, va_F, va_L, len_F_L)
|
||||
|
||||
/** Sendv packet with 3 or 4 segments.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param flags Ack/csum/notify flags in low 3 bits; number of segments minus
|
||||
* 1 in next 2 bits; expected checksum in high 16 bits.
|
||||
* @param confno Confirmation number to request, if notify flag set.
|
||||
* @param csum0 Checksum descriptor; if zero, no checksum.
|
||||
* @param va_F Virtual address of first segment.
|
||||
* @param va_L Virtual address of last segment (third segment if 3 segments,
|
||||
* fourth segment if 4 segments).
|
||||
* @param len_F_L Length of first segment in low 16 bits; length of last
|
||||
* segment in high 16 bits.
|
||||
* @param va_M0 Virtual address of "middle 0" segment; this segment is sent
|
||||
* second when there are three segments, and third if there are four.
|
||||
* @param va_M1 Virtual address of "middle 1" segment; this segment is sent
|
||||
* second when there are four segments.
|
||||
* @param len_M0_M1 Length of middle 0 segment in low 16 bits; length of middle
|
||||
* 1 segment, if 4 segments, in high 16 bits.
|
||||
*/
|
||||
#define __netio_fastio_sendv_pkt_3_4(fastio_index, flags, confno, csum0, va_F, \
|
||||
va_L, len_F_L, va_M0, va_M1, len_M0_M1) \
|
||||
__netio_fastio9((fastio_index) + NETIO_FASTIO_SENDV_PKT, flags, confno, \
|
||||
csum0, va_F, va_L, len_F_L, va_M0, va_M1, len_M0_M1)
|
||||
|
||||
/** Send vector of packets.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param seqno Number of packets transmitted so far on this interface;
|
||||
* used to decide which packets should be acknowledged.
|
||||
* @param nentries Number of entries in vector.
|
||||
* @param va Virtual address of start of vector entry array.
|
||||
* @return 3-word netio_fastio_rv3_t structure. The structure's err member
|
||||
* is an error code, or zero if no error. The val0 member is the
|
||||
* updated value of seqno; it has been incremented by 1 for each
|
||||
* packet sent. That increment may be less than nentries if an
|
||||
* error occured, or if some of the entries in the vector contain
|
||||
* handles equal to NETIO_PKT_HANDLE_NONE. The val1 member is the
|
||||
* updated value of nentries; it has been decremented by 1 for each
|
||||
* vector entry processed. Again, that decrement may be less than
|
||||
* nentries (leaving the returned value positive) if an error
|
||||
* occurred.
|
||||
*/
|
||||
#define __netio_fastio_send_pkt_vec(fastio_index, seqno, nentries, va) \
|
||||
__netio_fastio3_rv3((fastio_index) + NETIO_FASTIO_SEND_PKT_VEC, seqno, \
|
||||
nentries, va)
|
||||
|
||||
|
||||
/** An egress DMA command for LEPP. */
|
||||
typedef struct
|
||||
{
|
||||
/** Is this a TSO transfer?
|
||||
*
|
||||
* NOTE: This field is always 0, to distinguish it from
|
||||
* lepp_tso_cmd_t. It must come first!
|
||||
*/
|
||||
uint8_t tso : 1;
|
||||
|
||||
/** Unused padding bits. */
|
||||
uint8_t _unused : 3;
|
||||
|
||||
/** Should this packet be sent directly from caches instead of DRAM,
|
||||
* using hash-for-home to locate the packet data?
|
||||
*/
|
||||
uint8_t hash_for_home : 1;
|
||||
|
||||
/** Should we compute a checksum? */
|
||||
uint8_t compute_checksum : 1;
|
||||
|
||||
/** Is this the final buffer for this packet?
|
||||
*
|
||||
* A single packet can be split over several input buffers (a "gather"
|
||||
* operation). This flag indicates that this is the last buffer
|
||||
* in a packet.
|
||||
*/
|
||||
uint8_t end_of_packet : 1;
|
||||
|
||||
/** Should LEPP advance 'comp_busy' when this DMA is fully finished? */
|
||||
uint8_t send_completion : 1;
|
||||
|
||||
/** High bits of Client Physical Address of the start of the buffer
|
||||
* to be egressed.
|
||||
*
|
||||
* NOTE: Only 6 bits are actually needed here, as CPAs are
|
||||
* currently 38 bits. So two bits could be scavenged from this.
|
||||
*/
|
||||
uint8_t cpa_hi;
|
||||
|
||||
/** The number of bytes to be egressed. */
|
||||
uint16_t length;
|
||||
|
||||
/** Low 32 bits of Client Physical Address of the start of the buffer
|
||||
* to be egressed.
|
||||
*/
|
||||
uint32_t cpa_lo;
|
||||
|
||||
/** Checksum information (only used if 'compute_checksum'). */
|
||||
__netio_checksum_header_t checksum_data;
|
||||
|
||||
} lepp_cmd_t;
|
||||
|
||||
|
||||
/** A chunk of physical memory for a TSO egress. */
|
||||
typedef struct
|
||||
{
|
||||
/** The low bits of the CPA. */
|
||||
uint32_t cpa_lo;
|
||||
/** The high bits of the CPA. */
|
||||
uint16_t cpa_hi : 15;
|
||||
/** Should this packet be sent directly from caches instead of DRAM,
|
||||
* using hash-for-home to locate the packet data?
|
||||
*/
|
||||
uint16_t hash_for_home : 1;
|
||||
/** The length in bytes. */
|
||||
uint16_t length;
|
||||
} lepp_frag_t;
|
||||
|
||||
|
||||
/** An LEPP command that handles TSO. */
|
||||
typedef struct
|
||||
{
|
||||
/** Is this a TSO transfer?
|
||||
*
|
||||
* NOTE: This field is always 1, to distinguish it from
|
||||
* lepp_cmd_t. It must come first!
|
||||
*/
|
||||
uint8_t tso : 1;
|
||||
|
||||
/** Unused padding bits. */
|
||||
uint8_t _unused : 7;
|
||||
|
||||
/** Size of the header[] array in bytes. It must be in the range
|
||||
* [40, 127], which are the smallest header for a TCP packet over
|
||||
* Ethernet and the maximum possible prepend size supported by
|
||||
* hardware, respectively. Note that the array storage must be
|
||||
* padded out to a multiple of four bytes so that the following
|
||||
* LEPP command is aligned properly.
|
||||
*/
|
||||
uint8_t header_size;
|
||||
|
||||
/** Byte offset of the IP header in header[]. */
|
||||
uint8_t ip_offset;
|
||||
|
||||
/** Byte offset of the TCP header in header[]. */
|
||||
uint8_t tcp_offset;
|
||||
|
||||
/** The number of bytes to use for the payload of each packet,
|
||||
* except of course the last one, which may not have enough bytes.
|
||||
* This means that each Ethernet packet except the last will have a
|
||||
* size of header_size + payload_size.
|
||||
*/
|
||||
uint16_t payload_size;
|
||||
|
||||
/** The length of the 'frags' array that follows this struct. */
|
||||
uint16_t num_frags;
|
||||
|
||||
/** The actual frags. */
|
||||
lepp_frag_t frags[0 /* Variable-sized; num_frags entries. */];
|
||||
|
||||
/*
|
||||
* The packet header template logically follows frags[],
|
||||
* but you can't declare that in C.
|
||||
*
|
||||
* uint32_t header[header_size_in_words_rounded_up];
|
||||
*/
|
||||
|
||||
} lepp_tso_cmd_t;
|
||||
|
||||
|
||||
/** An LEPP completion ring entry. */
|
||||
typedef void* lepp_comp_t;
|
||||
|
||||
|
||||
/** Maximum number of frags for one TSO command. This is adapted from
|
||||
* linux's "MAX_SKB_FRAGS", and presumably over-estimates by one, for
|
||||
* our page size of exactly 65536. We add one for a "body" fragment.
|
||||
*/
|
||||
#define LEPP_MAX_FRAGS (65536 / HV_PAGE_SIZE_SMALL + 2 + 1)
|
||||
|
||||
/** Total number of bytes needed for an lepp_tso_cmd_t. */
|
||||
#define LEPP_TSO_CMD_SIZE(num_frags, header_size) \
|
||||
(sizeof(lepp_tso_cmd_t) + \
|
||||
(num_frags) * sizeof(lepp_frag_t) + \
|
||||
(((header_size) + 3) & -4))
|
||||
|
||||
/** The size of the lepp "cmd" queue. */
|
||||
#define LEPP_CMD_QUEUE_BYTES \
|
||||
(((CHIP_L2_CACHE_SIZE() - 2 * CHIP_L2_LINE_SIZE()) / \
|
||||
(sizeof(lepp_cmd_t) + sizeof(lepp_comp_t))) * sizeof(lepp_cmd_t))
|
||||
|
||||
/** The largest possible command that can go in lepp_queue_t::cmds[]. */
|
||||
#define LEPP_MAX_CMD_SIZE LEPP_TSO_CMD_SIZE(LEPP_MAX_FRAGS, 128)
|
||||
|
||||
/** The largest possible value of lepp_queue_t::cmd_{head, tail} (inclusive).
|
||||
*/
|
||||
#define LEPP_CMD_LIMIT \
|
||||
(LEPP_CMD_QUEUE_BYTES - LEPP_MAX_CMD_SIZE)
|
||||
|
||||
/** The maximum number of completions in an LEPP queue. */
|
||||
#define LEPP_COMP_QUEUE_SIZE \
|
||||
((LEPP_CMD_LIMIT + sizeof(lepp_cmd_t) - 1) / sizeof(lepp_cmd_t))
|
||||
|
||||
/** Increment an index modulo the queue size. */
|
||||
#define LEPP_QINC(var) \
|
||||
(var = __insn_mnz(var - (LEPP_COMP_QUEUE_SIZE - 1), var + 1))
|
||||
|
||||
/** A queue used to convey egress commands from the client to LEPP. */
|
||||
typedef struct
|
||||
{
|
||||
/** Index of first completion not yet processed by user code.
|
||||
* If this is equal to comp_busy, there are no such completions.
|
||||
*
|
||||
* NOTE: This is only read/written by the user.
|
||||
*/
|
||||
unsigned int comp_head;
|
||||
|
||||
/** Index of first completion record not yet completed.
|
||||
* If this is equal to comp_tail, there are no such completions.
|
||||
* This index gets advanced (modulo LEPP_QUEUE_SIZE) whenever
|
||||
* a command with the 'completion' bit set is finished.
|
||||
*
|
||||
* NOTE: This is only written by LEPP, only read by the user.
|
||||
*/
|
||||
volatile unsigned int comp_busy;
|
||||
|
||||
/** Index of the first empty slot in the completion ring.
|
||||
* Entries from this up to but not including comp_head (in ring order)
|
||||
* can be filled in with completion data.
|
||||
*
|
||||
* NOTE: This is only read/written by the user.
|
||||
*/
|
||||
unsigned int comp_tail;
|
||||
|
||||
/** Byte index of first command enqueued for LEPP but not yet processed.
|
||||
*
|
||||
* This is always divisible by sizeof(void*) and always <= LEPP_CMD_LIMIT.
|
||||
*
|
||||
* NOTE: LEPP advances this counter as soon as it no longer needs
|
||||
* the cmds[] storage for this entry, but the transfer is not actually
|
||||
* complete (i.e. the buffer pointed to by the command is no longer
|
||||
* needed) until comp_busy advances.
|
||||
*
|
||||
* If this is equal to cmd_tail, the ring is empty.
|
||||
*
|
||||
* NOTE: This is only written by LEPP, only read by the user.
|
||||
*/
|
||||
volatile unsigned int cmd_head;
|
||||
|
||||
/** Byte index of first empty slot in the command ring. This field can
|
||||
* be incremented up to but not equal to cmd_head (because that would
|
||||
* mean the ring is empty).
|
||||
*
|
||||
* This is always divisible by sizeof(void*) and always <= LEPP_CMD_LIMIT.
|
||||
*
|
||||
* NOTE: This is read/written by the user, only read by LEPP.
|
||||
*/
|
||||
volatile unsigned int cmd_tail;
|
||||
|
||||
/** A ring of variable-sized egress DMA commands.
|
||||
*
|
||||
* NOTE: Only written by the user, only read by LEPP.
|
||||
*/
|
||||
char cmds[LEPP_CMD_QUEUE_BYTES]
|
||||
__attribute__((aligned(CHIP_L2_LINE_SIZE())));
|
||||
|
||||
/** A ring of user completion data.
|
||||
* NOTE: Only read/written by the user.
|
||||
*/
|
||||
lepp_comp_t comps[LEPP_COMP_QUEUE_SIZE]
|
||||
__attribute__((aligned(CHIP_L2_LINE_SIZE())));
|
||||
} lepp_queue_t;
|
||||
|
||||
|
||||
/** An internal helper function for determining the number of entries
|
||||
* available in a ring buffer, given that there is one sentinel.
|
||||
*/
|
||||
static inline unsigned int
|
||||
_lepp_num_free_slots(unsigned int head, unsigned int tail)
|
||||
{
|
||||
/*
|
||||
* One entry is reserved for use as a sentinel, to distinguish
|
||||
* "empty" from "full". So we compute
|
||||
* (head - tail - 1) % LEPP_QUEUE_SIZE, but without using a slow % operation.
|
||||
*/
|
||||
return (head - tail - 1) + ((head <= tail) ? LEPP_COMP_QUEUE_SIZE : 0);
|
||||
}
|
||||
|
||||
|
||||
/** Returns how many new comp entries can be enqueued. */
|
||||
static inline unsigned int
|
||||
lepp_num_free_comp_slots(const lepp_queue_t* q)
|
||||
{
|
||||
return _lepp_num_free_slots(q->comp_head, q->comp_tail);
|
||||
}
|
||||
|
||||
static inline int
|
||||
lepp_qsub(int v1, int v2)
|
||||
{
|
||||
int delta = v1 - v2;
|
||||
return delta + ((delta >> 31) & LEPP_COMP_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/** FIXME: Check this from linux, via a new "pwrite()" call. */
|
||||
#define LIPP_VERSION 1
|
||||
|
||||
|
||||
/** We use exactly two bytes of alignment padding. */
|
||||
#define LIPP_PACKET_PADDING 2
|
||||
|
||||
/** The minimum size of a "small" buffer (including the padding). */
|
||||
#define LIPP_SMALL_PACKET_SIZE 128
|
||||
|
||||
/*
|
||||
* NOTE: The following two values should total to less than around
|
||||
* 13582, to keep the total size used for "lipp_state_t" below 64K.
|
||||
*/
|
||||
|
||||
/** The maximum number of "small" buffers.
|
||||
* This is enough for 53 network cpus with 128 credits. Note that
|
||||
* if these are exhausted, we will fall back to using large buffers.
|
||||
*/
|
||||
#define LIPP_SMALL_BUFFERS 6785
|
||||
|
||||
/** The maximum number of "large" buffers.
|
||||
* This is enough for 53 network cpus with 128 credits.
|
||||
*/
|
||||
#define LIPP_LARGE_BUFFERS 6785
|
||||
|
||||
#endif /* __DRV_XGBE_INTF_H__ */
|
122
arch/tile/include/hv/netio_errors.h
Normal file
122
arch/tile/include/hv/netio_errors.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Error codes returned from NetIO routines.
|
||||
*/
|
||||
|
||||
#ifndef __NETIO_ERRORS_H__
|
||||
#define __NETIO_ERRORS_H__
|
||||
|
||||
/**
|
||||
* @addtogroup error
|
||||
*
|
||||
* @brief The error codes returned by NetIO functions.
|
||||
*
|
||||
* NetIO functions return 0 (defined as ::NETIO_NO_ERROR) on success, and
|
||||
* a negative value if an error occurs.
|
||||
*
|
||||
* In cases where a NetIO function failed due to a error reported by
|
||||
* system libraries, the error code will be the negation of the
|
||||
* system errno at the time of failure. The @ref netio_strerror()
|
||||
* function will deliver error strings for both NetIO and system error
|
||||
* codes.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** The set of all NetIO errors. */
|
||||
typedef enum
|
||||
{
|
||||
/** Operation successfully completed. */
|
||||
NETIO_NO_ERROR = 0,
|
||||
|
||||
/** A packet was successfully retrieved from an input queue. */
|
||||
NETIO_PKT = 0,
|
||||
|
||||
/** Largest NetIO error number. */
|
||||
NETIO_ERR_MAX = -701,
|
||||
|
||||
/** The tile is not registered with the IPP. */
|
||||
NETIO_NOT_REGISTERED = -701,
|
||||
|
||||
/** No packet was available to retrieve from the input queue. */
|
||||
NETIO_NOPKT = -702,
|
||||
|
||||
/** The requested function is not implemented. */
|
||||
NETIO_NOT_IMPLEMENTED = -703,
|
||||
|
||||
/** On a registration operation, the target queue already has the maximum
|
||||
* number of tiles registered for it, and no more may be added. On a
|
||||
* packet send operation, the output queue is full and nothing more can
|
||||
* be queued until some of the queued packets are actually transmitted. */
|
||||
NETIO_QUEUE_FULL = -704,
|
||||
|
||||
/** The calling process or thread is not bound to exactly one CPU. */
|
||||
NETIO_BAD_AFFINITY = -705,
|
||||
|
||||
/** Cannot allocate memory on requested controllers. */
|
||||
NETIO_CANNOT_HOME = -706,
|
||||
|
||||
/** On a registration operation, the IPP specified is not configured
|
||||
* to support the options requested; for instance, the application
|
||||
* wants a specific type of tagged headers which the configured IPP
|
||||
* doesn't support. Or, the supplied configuration information is
|
||||
* not self-consistent, or is out of range; for instance, specifying
|
||||
* both NETIO_RECV and NETIO_NO_RECV, or asking for more than
|
||||
* NETIO_MAX_SEND_BUFFERS to be preallocated. On a VLAN or bucket
|
||||
* configure operation, the number of items, or the base item, was
|
||||
* out of range.
|
||||
*/
|
||||
NETIO_BAD_CONFIG = -707,
|
||||
|
||||
/** Too many tiles have registered to transmit packets. */
|
||||
NETIO_TOOMANY_XMIT = -708,
|
||||
|
||||
/** Packet transmission was attempted on a queue which was registered
|
||||
with transmit disabled. */
|
||||
NETIO_UNREG_XMIT = -709,
|
||||
|
||||
/** This tile is already registered with the IPP. */
|
||||
NETIO_ALREADY_REGISTERED = -710,
|
||||
|
||||
/** The Ethernet link is down. The application should try again later. */
|
||||
NETIO_LINK_DOWN = -711,
|
||||
|
||||
/** An invalid memory buffer has been specified. This may be an unmapped
|
||||
* virtual address, or one which does not meet alignment requirements.
|
||||
* For netio_input_register(), this error may be returned when multiple
|
||||
* processes specify different memory regions to be used for NetIO
|
||||
* buffers. That can happen if these processes specify explicit memory
|
||||
* regions with the ::NETIO_FIXED_BUFFER_VA flag, or if tmc_cmem_init()
|
||||
* has not been called by a common ancestor of the processes.
|
||||
*/
|
||||
NETIO_FAULT = -712,
|
||||
|
||||
/** Cannot combine user-managed shared memory and cache coherence. */
|
||||
NETIO_BAD_CACHE_CONFIG = -713,
|
||||
|
||||
/** Smallest NetIO error number. */
|
||||
NETIO_ERR_MIN = -713,
|
||||
|
||||
#ifndef __DOXYGEN__
|
||||
/** Used internally to mean that no response is needed; never returned to
|
||||
* an application. */
|
||||
NETIO_NO_RESPONSE = 1
|
||||
#endif
|
||||
} netio_error_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __NETIO_ERRORS_H__ */
|
2975
arch/tile/include/hv/netio_intf.h
Normal file
2975
arch/tile/include/hv/netio_intf.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,3 +15,4 @@ obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
621
arch/tile/kernel/pci.c
Normal file
621
arch/tile/kernel/pci.c
Normal file
@ -0,0 +1,621 @@
|
||||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/hv_driver.h>
|
||||
#include <hv/drv_pcie_rc_intf.h>
|
||||
|
||||
|
||||
/*
|
||||
* Initialization flow and process
|
||||
* -------------------------------
|
||||
*
|
||||
* This files containes the routines to search for PCI buses,
|
||||
* enumerate the buses, and configure any attached devices.
|
||||
*
|
||||
* There are two entry points here:
|
||||
* 1) tile_pci_init
|
||||
* This sets up the pci_controller structs, and opens the
|
||||
* FDs to the hypervisor. This is called from setup_arch() early
|
||||
* in the boot process.
|
||||
* 2) pcibios_init
|
||||
* This probes the PCI bus(es) for any attached hardware. It's
|
||||
* called by subsys_initcall. All of the real work is done by the
|
||||
* generic Linux PCI layer.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This flag tells if the platform is TILEmpower that needs
|
||||
* special configuration for the PLX switch chip.
|
||||
*/
|
||||
int __write_once tile_plx_gen1;
|
||||
|
||||
static struct pci_controller controllers[TILE_NUM_PCIE];
|
||||
static int num_controllers;
|
||||
|
||||
static struct pci_ops tile_cfg_ops;
|
||||
|
||||
|
||||
/*
|
||||
* We don't need to worry about the alignment of resources.
|
||||
*/
|
||||
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
{
|
||||
return res->start;
|
||||
}
|
||||
EXPORT_SYMBOL(pcibios_align_resource);
|
||||
|
||||
/*
|
||||
* Open a FD to the hypervisor PCI device.
|
||||
*
|
||||
* controller_id is the controller number, config type is 0 or 1 for
|
||||
* config0 or config1 operations.
|
||||
*/
|
||||
static int __init tile_pcie_open(int controller_id, int config_type)
|
||||
{
|
||||
char filename[32];
|
||||
int fd;
|
||||
|
||||
sprintf(filename, "pcie/%d/config%d", controller_id, config_type);
|
||||
|
||||
fd = hv_dev_open((HV_VirtAddr)filename, 0);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the IRQ numbers from the HV and set up the handlers for them.
|
||||
*/
|
||||
static int __init tile_init_irqs(int controller_id,
|
||||
struct pci_controller *controller)
|
||||
{
|
||||
char filename[32];
|
||||
int fd;
|
||||
int ret;
|
||||
int x;
|
||||
struct pcie_rc_config rc_config;
|
||||
|
||||
sprintf(filename, "pcie/%d/ctl", controller_id);
|
||||
fd = hv_dev_open((HV_VirtAddr)filename, 0);
|
||||
if (fd < 0) {
|
||||
pr_err("PCI: hv_dev_open(%s) failed\n", filename);
|
||||
return -1;
|
||||
}
|
||||
ret = hv_dev_pread(fd, 0, (HV_VirtAddr)(&rc_config),
|
||||
sizeof(rc_config), PCIE_RC_CONFIG_MASK_OFF);
|
||||
hv_dev_close(fd);
|
||||
if (ret != sizeof(rc_config)) {
|
||||
pr_err("PCI: wanted %zd bytes, got %d\n",
|
||||
sizeof(rc_config), ret);
|
||||
return -1;
|
||||
}
|
||||
/* Record irq_base so that we can map INTx to IRQ # later. */
|
||||
controller->irq_base = rc_config.intr;
|
||||
|
||||
for (x = 0; x < 4; x++)
|
||||
tile_irq_activate(rc_config.intr + x,
|
||||
TILE_IRQ_HW_CLEAR);
|
||||
|
||||
if (rc_config.plx_gen1)
|
||||
controller->plx_gen1 = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* First initialization entry point, called from setup_arch().
|
||||
*
|
||||
* Find valid controllers and fill in pci_controller structs for each
|
||||
* of them.
|
||||
*
|
||||
* Returns the number of controllers discovered.
|
||||
*/
|
||||
int __init tile_pci_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("PCI: Searching for controllers...\n");
|
||||
|
||||
/* Do any configuration we need before using the PCIe */
|
||||
|
||||
for (i = 0; i < TILE_NUM_PCIE; i++) {
|
||||
int hv_cfg_fd0 = -1;
|
||||
int hv_cfg_fd1 = -1;
|
||||
int hv_mem_fd = -1;
|
||||
char name[32];
|
||||
struct pci_controller *controller;
|
||||
|
||||
/*
|
||||
* Open the fd to the HV. If it fails then this
|
||||
* device doesn't exist.
|
||||
*/
|
||||
hv_cfg_fd0 = tile_pcie_open(i, 0);
|
||||
if (hv_cfg_fd0 < 0)
|
||||
continue;
|
||||
hv_cfg_fd1 = tile_pcie_open(i, 1);
|
||||
if (hv_cfg_fd1 < 0) {
|
||||
pr_err("PCI: Couldn't open config fd to HV "
|
||||
"for controller %d\n", i);
|
||||
goto err_cont;
|
||||
}
|
||||
|
||||
sprintf(name, "pcie/%d/mem", i);
|
||||
hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0);
|
||||
if (hv_mem_fd < 0) {
|
||||
pr_err("PCI: Could not open mem fd to HV!\n");
|
||||
goto err_cont;
|
||||
}
|
||||
|
||||
pr_info("PCI: Found PCI controller #%d\n", i);
|
||||
|
||||
controller = &controllers[num_controllers];
|
||||
|
||||
if (tile_init_irqs(i, controller)) {
|
||||
pr_err("PCI: Could not initialize "
|
||||
"IRQs, aborting.\n");
|
||||
goto err_cont;
|
||||
}
|
||||
|
||||
controller->index = num_controllers;
|
||||
controller->hv_cfg_fd[0] = hv_cfg_fd0;
|
||||
controller->hv_cfg_fd[1] = hv_cfg_fd1;
|
||||
controller->hv_mem_fd = hv_mem_fd;
|
||||
controller->first_busno = 0;
|
||||
controller->last_busno = 0xff;
|
||||
controller->ops = &tile_cfg_ops;
|
||||
|
||||
num_controllers++;
|
||||
continue;
|
||||
|
||||
err_cont:
|
||||
if (hv_cfg_fd0 >= 0)
|
||||
hv_dev_close(hv_cfg_fd0);
|
||||
if (hv_cfg_fd1 >= 0)
|
||||
hv_dev_close(hv_cfg_fd1);
|
||||
if (hv_mem_fd >= 0)
|
||||
hv_dev_close(hv_mem_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before using the PCIe, see if we need to do any platform-specific
|
||||
* configuration, such as the PLX switch Gen 1 issue on TILEmpower.
|
||||
*/
|
||||
for (i = 0; i < num_controllers; i++) {
|
||||
struct pci_controller *controller = &controllers[i];
|
||||
|
||||
if (controller->plx_gen1)
|
||||
tile_plx_gen1 = 1;
|
||||
}
|
||||
|
||||
return num_controllers;
|
||||
}
|
||||
|
||||
/*
|
||||
* (pin - 1) converts from the PCI standard's [1:4] convention to
|
||||
* a normal [0:3] range.
|
||||
*/
|
||||
static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
struct pci_controller *controller =
|
||||
(struct pci_controller *)dev->sysdata;
|
||||
return (pin - 1) + controller->irq_base;
|
||||
}
|
||||
|
||||
|
||||
static void __init fixup_read_and_payload_sizes(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */
|
||||
int max_read_size = 0x2; /* Limit to 512 byte reads. */
|
||||
u16 new_values;
|
||||
|
||||
/* Scan for the smallest maximum payload size. */
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
int pcie_caps_offset;
|
||||
u32 devcap;
|
||||
int max_payload;
|
||||
|
||||
pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (pcie_caps_offset == 0)
|
||||
continue;
|
||||
|
||||
pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
|
||||
&devcap);
|
||||
max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
|
||||
if (max_payload < smallest_max_payload)
|
||||
smallest_max_payload = max_payload;
|
||||
}
|
||||
|
||||
/* Now, set the max_payload_size for all devices to that value. */
|
||||
new_values = (max_read_size << 12) | (smallest_max_payload << 5);
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
int pcie_caps_offset;
|
||||
u16 devctl;
|
||||
|
||||
pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (pcie_caps_offset == 0)
|
||||
continue;
|
||||
|
||||
pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
|
||||
&devctl);
|
||||
devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ);
|
||||
devctl |= new_values;
|
||||
pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
|
||||
devctl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Second PCI initialization entry point, called by subsys_initcall.
|
||||
*
|
||||
* The controllers have been set up by the time we get here, by a call to
|
||||
* tile_pci_init.
|
||||
*/
|
||||
static int __init pcibios_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("PCI: Probing PCI hardware\n");
|
||||
|
||||
/*
|
||||
* Delay a bit in case devices aren't ready. Some devices are
|
||||
* known to require at least 20ms here, but we use a more
|
||||
* conservative value.
|
||||
*/
|
||||
mdelay(250);
|
||||
|
||||
/* Scan all of the recorded PCI controllers. */
|
||||
for (i = 0; i < num_controllers; i++) {
|
||||
struct pci_controller *controller = &controllers[i];
|
||||
struct pci_bus *bus;
|
||||
|
||||
pr_info("PCI: initializing controller #%d\n", i);
|
||||
|
||||
/*
|
||||
* This comes from the generic Linux PCI driver.
|
||||
*
|
||||
* It reads the PCI tree for this bus into the Linux
|
||||
* data structures.
|
||||
*
|
||||
* This is inlined in linux/pci.h and calls into
|
||||
* pci_scan_bus_parented() in probe.c.
|
||||
*/
|
||||
bus = pci_scan_bus(0, controller->ops, controller);
|
||||
controller->root_bus = bus;
|
||||
controller->last_busno = bus->subordinate;
|
||||
|
||||
}
|
||||
|
||||
/* Do machine dependent PCI interrupt routing */
|
||||
pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
|
||||
|
||||
/*
|
||||
* This comes from the generic Linux PCI driver.
|
||||
*
|
||||
* It allocates all of the resources (I/O memory, etc)
|
||||
* associated with the devices read in above.
|
||||
*/
|
||||
|
||||
pci_assign_unassigned_resources();
|
||||
|
||||
/* Configure the max_read_size and max_payload_size values. */
|
||||
fixup_read_and_payload_sizes();
|
||||
|
||||
/* Record the I/O resources in the PCI controller structure. */
|
||||
for (i = 0; i < num_controllers; i++) {
|
||||
struct pci_bus *root_bus = controllers[i].root_bus;
|
||||
struct pci_bus *next_bus;
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &root_bus->devices, bus_list) {
|
||||
/* Find the PCI host controller, ie. the 1st bridge. */
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
|
||||
(PCI_SLOT(dev->devfn) == 0)) {
|
||||
next_bus = dev->subordinate;
|
||||
controllers[i].mem_resources[0] =
|
||||
*next_bus->resource[0];
|
||||
controllers[i].mem_resources[1] =
|
||||
*next_bus->resource[1];
|
||||
controllers[i].mem_resources[2] =
|
||||
*next_bus->resource[2];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(pcibios_init);
|
||||
|
||||
/*
|
||||
* No bus fixups needed.
|
||||
*/
|
||||
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
|
||||
{
|
||||
/* Nothing needs to be done. */
|
||||
}
|
||||
|
||||
/*
|
||||
* This can be called from the generic PCI layer, but doesn't need to
|
||||
* do anything.
|
||||
*/
|
||||
char __devinit *pcibios_setup(char *str)
|
||||
{
|
||||
/* Nothing needs to be done. */
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from the generic Linux layer.
|
||||
*/
|
||||
void __init pcibios_update_irq(struct pci_dev *dev, int irq)
|
||||
{
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable memory and/or address decoding, as appropriate, for the
|
||||
* device described by the 'dev' struct.
|
||||
*
|
||||
* This is called from the generic PCI layer, and can be called
|
||||
* for bridges or endpoints.
|
||||
*/
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
u16 cmd, old_cmd;
|
||||
u8 header_type;
|
||||
int i;
|
||||
struct resource *r;
|
||||
|
||||
pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
old_cmd = cmd;
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/*
|
||||
* For bridges, we enable both memory and I/O decoding
|
||||
* in call cases.
|
||||
*/
|
||||
cmd |= PCI_COMMAND_IO;
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
} else {
|
||||
/*
|
||||
* For endpoints, we enable memory and/or I/O decoding
|
||||
* only if they have a memory resource of that type.
|
||||
*/
|
||||
for (i = 0; i < 6; i++) {
|
||||
r = &dev->resource[i];
|
||||
if (r->flags & IORESOURCE_UNSET) {
|
||||
pr_err("PCI: Device %s not available "
|
||||
"because of resource collisions\n",
|
||||
pci_name(dev));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r->flags & IORESOURCE_IO)
|
||||
cmd |= PCI_COMMAND_IO;
|
||||
if (r->flags & IORESOURCE_MEM)
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We only write the command if it changed.
|
||||
*/
|
||||
if (cmd != old_cmd)
|
||||
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
|
||||
{
|
||||
unsigned long start = pci_resource_start(dev, bar);
|
||||
unsigned long len = pci_resource_len(dev, bar);
|
||||
unsigned long flags = pci_resource_flags(dev, bar);
|
||||
|
||||
if (!len)
|
||||
return NULL;
|
||||
if (max && len > max)
|
||||
len = max;
|
||||
|
||||
if (!(flags & IORESOURCE_MEM)) {
|
||||
pr_info("PCI: Trying to map invalid resource %#lx\n", flags);
|
||||
start = 0;
|
||||
}
|
||||
|
||||
return (void __iomem *)start;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iomap);
|
||||
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* Tile PCI config space read/write routines
|
||||
*
|
||||
****************************************************************/
|
||||
|
||||
/*
|
||||
* These are the normal read and write ops
|
||||
* These are expanded with macros from pci_bus_read_config_byte() etc.
|
||||
*
|
||||
* devfn is the combined PCI slot & function.
|
||||
*
|
||||
* offset is in bytes, from the start of config space for the
|
||||
* specified bus & slot.
|
||||
*/
|
||||
|
||||
static int __devinit tile_cfg_read(struct pci_bus *bus,
|
||||
unsigned int devfn,
|
||||
int offset,
|
||||
int size,
|
||||
u32 *val)
|
||||
{
|
||||
struct pci_controller *controller = bus->sysdata;
|
||||
int busnum = bus->number & 0xff;
|
||||
int slot = (devfn >> 3) & 0x1f;
|
||||
int function = devfn & 0x7;
|
||||
u32 addr;
|
||||
int config_mode = 1;
|
||||
|
||||
/*
|
||||
* There is no bridge between the Tile and bus 0, so we
|
||||
* use config0 to talk to bus 0.
|
||||
*
|
||||
* If we're talking to a bus other than zero then we
|
||||
* must have found a bridge.
|
||||
*/
|
||||
if (busnum == 0) {
|
||||
/*
|
||||
* We fake an empty slot for (busnum == 0) && (slot > 0),
|
||||
* since there is only one slot on bus 0.
|
||||
*/
|
||||
if (slot) {
|
||||
*val = 0xFFFFFFFF;
|
||||
return 0;
|
||||
}
|
||||
config_mode = 0;
|
||||
}
|
||||
|
||||
addr = busnum << 20; /* Bus in 27:20 */
|
||||
addr |= slot << 15; /* Slot (device) in 19:15 */
|
||||
addr |= function << 12; /* Function is in 14:12 */
|
||||
addr |= (offset & 0xFFF); /* byte address in 0:11 */
|
||||
|
||||
return hv_dev_pread(controller->hv_cfg_fd[config_mode], 0,
|
||||
(HV_VirtAddr)(val), size, addr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* See tile_cfg_read() for relevent comments.
|
||||
* Note that "val" is the value to write, not a pointer to that value.
|
||||
*/
|
||||
static int __devinit tile_cfg_write(struct pci_bus *bus,
|
||||
unsigned int devfn,
|
||||
int offset,
|
||||
int size,
|
||||
u32 val)
|
||||
{
|
||||
struct pci_controller *controller = bus->sysdata;
|
||||
int busnum = bus->number & 0xff;
|
||||
int slot = (devfn >> 3) & 0x1f;
|
||||
int function = devfn & 0x7;
|
||||
u32 addr;
|
||||
int config_mode = 1;
|
||||
HV_VirtAddr valp = (HV_VirtAddr)&val;
|
||||
|
||||
/*
|
||||
* For bus 0 slot 0 we use config 0 accesses.
|
||||
*/
|
||||
if (busnum == 0) {
|
||||
/*
|
||||
* We fake an empty slot for (busnum == 0) && (slot > 0),
|
||||
* since there is only one slot on bus 0.
|
||||
*/
|
||||
if (slot)
|
||||
return 0;
|
||||
config_mode = 0;
|
||||
}
|
||||
|
||||
addr = busnum << 20; /* Bus in 27:20 */
|
||||
addr |= slot << 15; /* Slot (device) in 19:15 */
|
||||
addr |= function << 12; /* Function is in 14:12 */
|
||||
addr |= (offset & 0xFFF); /* byte address in 0:11 */
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
/* Point to the correct part of the 32-bit "val". */
|
||||
valp += 4 - size;
|
||||
#endif
|
||||
|
||||
return hv_dev_pwrite(controller->hv_cfg_fd[config_mode], 0,
|
||||
valp, size, addr);
|
||||
}
|
||||
|
||||
|
||||
static struct pci_ops tile_cfg_ops = {
|
||||
.read = tile_cfg_read,
|
||||
.write = tile_cfg_write,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* In the following, each PCI controller's mem_resources[1]
|
||||
* represents its (non-prefetchable) PCI memory resource.
|
||||
* mem_resources[0] and mem_resources[2] refer to its PCI I/O and
|
||||
* prefetchable PCI memory resources, respectively.
|
||||
* For more details, see pci_setup_bridge() in setup-bus.c.
|
||||
* By comparing the target PCI memory address against the
|
||||
* end address of controller 0, we can determine the controller
|
||||
* that should accept the PCI memory access.
|
||||
*/
|
||||
#define TILE_READ(size, type) \
|
||||
type _tile_read##size(unsigned long addr) \
|
||||
{ \
|
||||
type val; \
|
||||
int idx = 0; \
|
||||
if (addr > controllers[0].mem_resources[1].end && \
|
||||
addr > controllers[0].mem_resources[2].end) \
|
||||
idx = 1; \
|
||||
if (hv_dev_pread(controllers[idx].hv_mem_fd, 0, \
|
||||
(HV_VirtAddr)(&val), sizeof(type), addr)) \
|
||||
pr_err("PCI: read %zd bytes at 0x%lX failed\n", \
|
||||
sizeof(type), addr); \
|
||||
return val; \
|
||||
} \
|
||||
EXPORT_SYMBOL(_tile_read##size)
|
||||
|
||||
TILE_READ(b, u8);
|
||||
TILE_READ(w, u16);
|
||||
TILE_READ(l, u32);
|
||||
TILE_READ(q, u64);
|
||||
|
||||
#define TILE_WRITE(size, type) \
|
||||
void _tile_write##size(type val, unsigned long addr) \
|
||||
{ \
|
||||
int idx = 0; \
|
||||
if (addr > controllers[0].mem_resources[1].end && \
|
||||
addr > controllers[0].mem_resources[2].end) \
|
||||
idx = 1; \
|
||||
if (hv_dev_pwrite(controllers[idx].hv_mem_fd, 0, \
|
||||
(HV_VirtAddr)(&val), sizeof(type), addr)) \
|
||||
pr_err("PCI: write %zd bytes at 0x%lX failed\n", \
|
||||
sizeof(type), addr); \
|
||||
} \
|
||||
EXPORT_SYMBOL(_tile_write##size)
|
||||
|
||||
TILE_WRITE(b, u8);
|
||||
TILE_WRITE(w, u16);
|
||||
TILE_WRITE(l, u32);
|
||||
TILE_WRITE(q, u64);
|
@ -840,7 +840,7 @@ static int __init topology_init(void)
|
||||
for_each_online_node(i)
|
||||
register_one_node(i);
|
||||
|
||||
for_each_present_cpu(i)
|
||||
for (i = 0; i < smp_height * smp_width; ++i)
|
||||
register_cpu(&cpu_devices[i], i);
|
||||
|
||||
return 0;
|
||||
|
@ -18,12 +18,24 @@
|
||||
|
||||
void *memchr(const void *s, int c, size_t n)
|
||||
{
|
||||
const uint32_t *last_word_ptr;
|
||||
const uint32_t *p;
|
||||
const char *last_byte_ptr;
|
||||
uintptr_t s_int;
|
||||
uint32_t goal, before_mask, v, bits;
|
||||
char *ret;
|
||||
|
||||
if (__builtin_expect(n == 0, 0)) {
|
||||
/* Don't dereference any memory if the array is empty. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get an aligned pointer. */
|
||||
const uintptr_t s_int = (uintptr_t) s;
|
||||
const uint32_t *p = (const uint32_t *)(s_int & -4);
|
||||
s_int = (uintptr_t) s;
|
||||
p = (const uint32_t *)(s_int & -4);
|
||||
|
||||
/* Create four copies of the byte for which we are looking. */
|
||||
const uint32_t goal = 0x01010101 * (uint8_t) c;
|
||||
goal = 0x01010101 * (uint8_t) c;
|
||||
|
||||
/* Read the first word, but munge it so that bytes before the array
|
||||
* will not match goal.
|
||||
@ -31,23 +43,14 @@ void *memchr(const void *s, int c, size_t n)
|
||||
* Note that this shift count expression works because we know
|
||||
* shift counts are taken mod 32.
|
||||
*/
|
||||
const uint32_t before_mask = (1 << (s_int << 3)) - 1;
|
||||
uint32_t v = (*p | before_mask) ^ (goal & before_mask);
|
||||
before_mask = (1 << (s_int << 3)) - 1;
|
||||
v = (*p | before_mask) ^ (goal & before_mask);
|
||||
|
||||
/* Compute the address of the last byte. */
|
||||
const char *const last_byte_ptr = (const char *)s + n - 1;
|
||||
last_byte_ptr = (const char *)s + n - 1;
|
||||
|
||||
/* Compute the address of the word containing the last byte. */
|
||||
const uint32_t *const last_word_ptr =
|
||||
(const uint32_t *)((uintptr_t) last_byte_ptr & -4);
|
||||
|
||||
uint32_t bits;
|
||||
char *ret;
|
||||
|
||||
if (__builtin_expect(n == 0, 0)) {
|
||||
/* Don't dereference any memory if the array is empty. */
|
||||
return NULL;
|
||||
}
|
||||
last_word_ptr = (const uint32_t *)((uintptr_t) last_byte_ptr & -4);
|
||||
|
||||
while ((bits = __insn_seqb(v, goal)) == 0) {
|
||||
if (__builtin_expect(p == last_word_ptr, 0)) {
|
||||
|
@ -167,23 +167,30 @@ void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
|
||||
* when we compare them.
|
||||
*/
|
||||
u32 my_ticket_;
|
||||
|
||||
/* Take out the next ticket; this will also stop would-be readers. */
|
||||
if (val & 1)
|
||||
val = get_rwlock(rwlock);
|
||||
rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT);
|
||||
|
||||
/* Extract my ticket value from the original word. */
|
||||
my_ticket_ = val >> WR_NEXT_SHIFT;
|
||||
u32 iterations = 0;
|
||||
|
||||
/*
|
||||
* Wait until the "current" field matches our ticket, and
|
||||
* there are no remaining readers.
|
||||
* Wait until there are no readers, then bump up the next
|
||||
* field and capture the ticket value.
|
||||
*/
|
||||
for (;;) {
|
||||
if (!(val & 1)) {
|
||||
if ((val >> RD_COUNT_SHIFT) == 0)
|
||||
break;
|
||||
rwlock->lock = val;
|
||||
}
|
||||
delay_backoff(iterations++);
|
||||
val = __insn_tns((int *)&rwlock->lock);
|
||||
}
|
||||
|
||||
/* Take out the next ticket and extract my ticket value. */
|
||||
rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT);
|
||||
my_ticket_ = val >> WR_NEXT_SHIFT;
|
||||
|
||||
/* Wait until the "current" field matches our ticket. */
|
||||
for (;;) {
|
||||
u32 curr_ = val >> WR_CURR_SHIFT;
|
||||
u32 readers = val >> RD_COUNT_SHIFT;
|
||||
u32 delta = ((my_ticket_ - curr_) & WR_MASK) + !!readers;
|
||||
u32 delta = ((my_ticket_ - curr_) & WR_MASK);
|
||||
if (likely(delta == 0))
|
||||
break;
|
||||
|
||||
|
@ -727,6 +727,9 @@ struct winch {
|
||||
|
||||
static void free_winch(struct winch *winch, int free_irq_ok)
|
||||
{
|
||||
if (free_irq_ok)
|
||||
free_irq(WINCH_IRQ, winch);
|
||||
|
||||
list_del(&winch->list);
|
||||
|
||||
if (winch->pid != -1)
|
||||
@ -735,8 +738,6 @@ static void free_winch(struct winch *winch, int free_irq_ok)
|
||||
os_close_file(winch->fd);
|
||||
if (winch->stack != 0)
|
||||
free_stack(winch->stack, 0);
|
||||
if (free_irq_ok)
|
||||
free_irq(WINCH_IRQ, winch);
|
||||
kfree(winch);
|
||||
}
|
||||
|
||||
|
@ -216,8 +216,8 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
|
||||
}
|
||||
|
||||
/* Return an pointer with offset calculated */
|
||||
static inline unsigned long __set_fixmap_offset(enum fixed_addresses idx,
|
||||
phys_addr_t phys, pgprot_t flags)
|
||||
static __always_inline unsigned long
|
||||
__set_fixmap_offset(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
|
||||
{
|
||||
__set_fixmap(idx, phys, flags);
|
||||
return fix_to_virt(idx) + (phys & (PAGE_SIZE - 1));
|
||||
|
@ -1200,8 +1200,6 @@ asmlinkage void __init xen_start_kernel(void)
|
||||
/* Allocate and initialize top and mid mfn levels for p2m structure */
|
||||
xen_build_mfn_list_list();
|
||||
|
||||
init_mm.pgd = pgd;
|
||||
|
||||
/* keep using Xen gdt for now; no urgent need to change it */
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
@ -2133,44 +2133,83 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
|
||||
return pgd;
|
||||
}
|
||||
#else /* !CONFIG_X86_64 */
|
||||
static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD);
|
||||
static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
|
||||
static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
|
||||
|
||||
static __init void xen_write_cr3_init(unsigned long cr3)
|
||||
{
|
||||
unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
|
||||
|
||||
BUG_ON(read_cr3() != __pa(initial_page_table));
|
||||
BUG_ON(cr3 != __pa(swapper_pg_dir));
|
||||
|
||||
/*
|
||||
* We are switching to swapper_pg_dir for the first time (from
|
||||
* initial_page_table) and therefore need to mark that page
|
||||
* read-only and then pin it.
|
||||
*
|
||||
* Xen disallows sharing of kernel PMDs for PAE
|
||||
* guests. Therefore we must copy the kernel PMD from
|
||||
* initial_page_table into a new kernel PMD to be used in
|
||||
* swapper_pg_dir.
|
||||
*/
|
||||
swapper_kernel_pmd =
|
||||
extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
|
||||
memcpy(swapper_kernel_pmd, initial_kernel_pmd,
|
||||
sizeof(pmd_t) * PTRS_PER_PMD);
|
||||
swapper_pg_dir[KERNEL_PGD_BOUNDARY] =
|
||||
__pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT);
|
||||
set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO);
|
||||
|
||||
set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
|
||||
xen_write_cr3(cr3);
|
||||
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn);
|
||||
|
||||
pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
|
||||
PFN_DOWN(__pa(initial_page_table)));
|
||||
set_page_prot(initial_page_table, PAGE_KERNEL);
|
||||
set_page_prot(initial_kernel_pmd, PAGE_KERNEL);
|
||||
|
||||
pv_mmu_ops.write_cr3 = &xen_write_cr3;
|
||||
}
|
||||
|
||||
__init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
|
||||
unsigned long max_pfn)
|
||||
{
|
||||
pmd_t *kernel_pmd;
|
||||
|
||||
level2_kernel_pgt = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
|
||||
initial_kernel_pmd =
|
||||
extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
|
||||
|
||||
max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
|
||||
xen_start_info->nr_pt_frames * PAGE_SIZE +
|
||||
512*1024);
|
||||
|
||||
kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
|
||||
memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
|
||||
memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
|
||||
|
||||
xen_map_identity_early(level2_kernel_pgt, max_pfn);
|
||||
xen_map_identity_early(initial_kernel_pmd, max_pfn);
|
||||
|
||||
memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
|
||||
set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
|
||||
__pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));
|
||||
memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
|
||||
initial_page_table[KERNEL_PGD_BOUNDARY] =
|
||||
__pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
|
||||
|
||||
set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
|
||||
set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
|
||||
set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO);
|
||||
set_page_prot(initial_page_table, PAGE_KERNEL_RO);
|
||||
set_page_prot(empty_zero_page, PAGE_KERNEL_RO);
|
||||
|
||||
pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
|
||||
|
||||
xen_write_cr3(__pa(swapper_pg_dir));
|
||||
|
||||
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
|
||||
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE,
|
||||
PFN_DOWN(__pa(initial_page_table)));
|
||||
xen_write_cr3(__pa(initial_page_table));
|
||||
|
||||
memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
|
||||
__pa(xen_start_info->pt_base +
|
||||
xen_start_info->nr_pt_frames * PAGE_SIZE),
|
||||
"XEN PAGETABLES");
|
||||
|
||||
return swapper_pg_dir;
|
||||
return initial_page_table;
|
||||
}
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
@ -2304,7 +2343,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
|
||||
.write_cr2 = xen_write_cr2,
|
||||
|
||||
.read_cr3 = xen_read_cr3,
|
||||
#ifdef CONFIG_X86_32
|
||||
.write_cr3 = xen_write_cr3_init,
|
||||
#else
|
||||
.write_cr3 = xen_write_cr3,
|
||||
#endif
|
||||
|
||||
.flush_tlb_user = xen_flush_tlb,
|
||||
.flush_tlb_kernel = xen_flush_tlb,
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <xen/interface/callback.h>
|
||||
#include <xen/interface/memory.h>
|
||||
#include <xen/interface/physdev.h>
|
||||
#include <xen/interface/memory.h>
|
||||
#include <xen/features.h>
|
||||
|
||||
#include "xen-ops.h"
|
||||
|
@ -1547,31 +1547,16 @@ static int init_vqs(struct ports_device *portdev)
|
||||
nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;
|
||||
|
||||
vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
|
||||
if (!vqs) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL);
|
||||
if (!io_callbacks) {
|
||||
err = -ENOMEM;
|
||||
goto free_vqs;
|
||||
}
|
||||
io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL);
|
||||
if (!io_names) {
|
||||
err = -ENOMEM;
|
||||
goto free_callbacks;
|
||||
}
|
||||
portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
|
||||
GFP_KERNEL);
|
||||
if (!portdev->in_vqs) {
|
||||
err = -ENOMEM;
|
||||
goto free_names;
|
||||
}
|
||||
portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
|
||||
GFP_KERNEL);
|
||||
if (!portdev->out_vqs) {
|
||||
if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
|
||||
!portdev->out_vqs) {
|
||||
err = -ENOMEM;
|
||||
goto free_invqs;
|
||||
goto free;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1605,7 +1590,7 @@ static int init_vqs(struct ports_device *portdev)
|
||||
io_callbacks,
|
||||
(const char **)io_names);
|
||||
if (err)
|
||||
goto free_outvqs;
|
||||
goto free;
|
||||
|
||||
j = 0;
|
||||
portdev->in_vqs[0] = vqs[0];
|
||||
@ -1621,23 +1606,19 @@ static int init_vqs(struct ports_device *portdev)
|
||||
portdev->out_vqs[i] = vqs[j + 1];
|
||||
}
|
||||
}
|
||||
kfree(io_callbacks);
|
||||
kfree(io_names);
|
||||
kfree(io_callbacks);
|
||||
kfree(vqs);
|
||||
|
||||
return 0;
|
||||
|
||||
free_names:
|
||||
kfree(io_names);
|
||||
free_callbacks:
|
||||
kfree(io_callbacks);
|
||||
free_outvqs:
|
||||
free:
|
||||
kfree(portdev->out_vqs);
|
||||
free_invqs:
|
||||
kfree(portdev->in_vqs);
|
||||
free_vqs:
|
||||
kfree(io_names);
|
||||
kfree(io_callbacks);
|
||||
kfree(vqs);
|
||||
fail:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -497,12 +497,14 @@ static unsigned long chipset_ids[] = {
|
||||
0
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
static struct pci_device_id i5k_amb_ids[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
|
||||
#endif
|
||||
|
||||
static int __devinit i5k_amb_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -186,7 +186,7 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int lis3lv02d_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||||
@ -213,12 +213,9 @@ static int lis3lv02d_i2c_resume(struct device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define lis3lv02d_i2c_suspend NULL
|
||||
#define lis3lv02d_i2c_resume NULL
|
||||
#define lis3lv02d_i2c_shutdown NULL
|
||||
#endif
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int lis3_i2c_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||||
@ -236,6 +233,7 @@ static int lis3_i2c_runtime_resume(struct device *dev)
|
||||
lis3lv02d_poweron(lis3);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_RUNTIME */
|
||||
|
||||
static const struct i2c_device_id lis3lv02d_id[] = {
|
||||
{"lis3lv02d", 0 },
|
||||
|
@ -125,11 +125,22 @@ struct lp5521_chip {
|
||||
u8 num_leds;
|
||||
};
|
||||
|
||||
#define cdev_to_led(c) container_of(c, struct lp5521_led, cdev)
|
||||
#define engine_to_lp5521(eng) container_of((eng), struct lp5521_chip, \
|
||||
engines[(eng)->id - 1])
|
||||
#define led_to_lp5521(led) container_of((led), struct lp5521_chip, \
|
||||
leds[(led)->id])
|
||||
static inline struct lp5521_led *cdev_to_led(struct led_classdev *cdev)
|
||||
{
|
||||
return container_of(cdev, struct lp5521_led, cdev);
|
||||
}
|
||||
|
||||
static inline struct lp5521_chip *engine_to_lp5521(struct lp5521_engine *engine)
|
||||
{
|
||||
return container_of(engine, struct lp5521_chip,
|
||||
engines[engine->id - 1]);
|
||||
}
|
||||
|
||||
static inline struct lp5521_chip *led_to_lp5521(struct lp5521_led *led)
|
||||
{
|
||||
return container_of(led, struct lp5521_chip,
|
||||
leds[led->id]);
|
||||
}
|
||||
|
||||
static void lp5521_led_brightness_work(struct work_struct *work);
|
||||
|
||||
@ -185,14 +196,17 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
|
||||
|
||||
/* move current engine to direct mode and remember the state */
|
||||
ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
|
||||
usleep_range(1000, 10000);
|
||||
/* Mode change requires min 500 us delay. 1 - 2 ms with margin */
|
||||
usleep_range(1000, 2000);
|
||||
ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode);
|
||||
|
||||
/* For loading, all the engines to load mode */
|
||||
lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
|
||||
usleep_range(1000, 10000);
|
||||
/* Mode change requires min 500 us delay. 1 - 2 ms with margin */
|
||||
usleep_range(1000, 2000);
|
||||
lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD);
|
||||
usleep_range(1000, 10000);
|
||||
/* Mode change requires min 500 us delay. 1 - 2 ms with margin */
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE;
|
||||
i2c_smbus_write_i2c_block_data(client,
|
||||
@ -231,10 +245,6 @@ static int lp5521_configure(struct i2c_client *client,
|
||||
|
||||
lp5521_init_engine(chip, attr_group);
|
||||
|
||||
lp5521_write(client, LP5521_REG_RESET, 0xff);
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
/* Set all PWMs to direct control mode */
|
||||
ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
|
||||
|
||||
@ -251,8 +261,8 @@ static int lp5521_configure(struct i2c_client *client,
|
||||
ret |= lp5521_write(client, LP5521_REG_ENABLE,
|
||||
LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM |
|
||||
LP5521_EXEC_RUN);
|
||||
/* enable takes 500us */
|
||||
usleep_range(500, 20000);
|
||||
/* enable takes 500us. 1 - 2 ms leaves some margin */
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -305,7 +315,8 @@ static int lp5521_detect(struct i2c_client *client)
|
||||
LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM);
|
||||
if (ret)
|
||||
return ret;
|
||||
usleep_range(1000, 10000);
|
||||
/* enable takes 500us. 1 - 2 ms leaves some margin */
|
||||
usleep_range(1000, 2000);
|
||||
ret = lp5521_read(client, LP5521_REG_ENABLE, &buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -693,11 +704,16 @@ static int lp5521_probe(struct i2c_client *client,
|
||||
|
||||
if (pdata->enable) {
|
||||
pdata->enable(0);
|
||||
usleep_range(1000, 10000);
|
||||
usleep_range(1000, 2000); /* Keep enable down at least 1ms */
|
||||
pdata->enable(1);
|
||||
usleep_range(1000, 10000); /* Spec says min 500us */
|
||||
usleep_range(1000, 2000); /* 500us abs min. */
|
||||
}
|
||||
|
||||
lp5521_write(client, LP5521_REG_RESET, 0xff);
|
||||
usleep_range(10000, 20000); /*
|
||||
* Exact value is not available. 10 - 20ms
|
||||
* appears to be enough for reset.
|
||||
*/
|
||||
ret = lp5521_detect(client);
|
||||
|
||||
if (ret) {
|
||||
|
@ -134,15 +134,18 @@ struct lp5523_chip {
|
||||
u8 num_leds;
|
||||
};
|
||||
|
||||
#define cdev_to_led(c) container_of(c, struct lp5523_led, cdev)
|
||||
static inline struct lp5523_led *cdev_to_led(struct led_classdev *cdev)
|
||||
{
|
||||
return container_of(cdev, struct lp5523_led, cdev);
|
||||
}
|
||||
|
||||
static struct lp5523_chip *engine_to_lp5523(struct lp5523_engine *engine)
|
||||
static inline struct lp5523_chip *engine_to_lp5523(struct lp5523_engine *engine)
|
||||
{
|
||||
return container_of(engine, struct lp5523_chip,
|
||||
engines[engine->id - 1]);
|
||||
}
|
||||
|
||||
static struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
|
||||
static inline struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
|
||||
{
|
||||
return container_of(led, struct lp5523_chip,
|
||||
leds[led->id]);
|
||||
@ -200,13 +203,9 @@ static int lp5523_configure(struct i2c_client *client)
|
||||
{ 0x9c, 0x50, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0},
|
||||
};
|
||||
|
||||
lp5523_write(client, LP5523_REG_RESET, 0xff);
|
||||
|
||||
usleep_range(10000, 100000);
|
||||
|
||||
ret |= lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE);
|
||||
/* Chip startup time after reset is 500 us */
|
||||
usleep_range(1000, 10000);
|
||||
/* Chip startup time is 500 us, 1 - 2 ms gives some margin */
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
ret |= lp5523_write(client, LP5523_REG_CONFIG,
|
||||
LP5523_AUTO_INC | LP5523_PWR_SAVE |
|
||||
@ -243,8 +242,8 @@ static int lp5523_configure(struct i2c_client *client)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait 3ms and check the engine status */
|
||||
usleep_range(3000, 20000);
|
||||
/* Let the programs run for couple of ms and check the engine status */
|
||||
usleep_range(3000, 6000);
|
||||
lp5523_read(client, LP5523_REG_STATUS, &status);
|
||||
status &= LP5523_ENG_STATUS_MASK;
|
||||
|
||||
@ -449,10 +448,10 @@ static ssize_t lp5523_selftest(struct device *dev,
|
||||
/* Measure VDD (i.e. VBAT) first (channel 16 corresponds to VDD) */
|
||||
lp5523_write(chip->client, LP5523_REG_LED_TEST_CTRL,
|
||||
LP5523_EN_LEDTEST | 16);
|
||||
usleep_range(3000, 10000);
|
||||
usleep_range(3000, 6000); /* ADC conversion time is typically 2.7 ms */
|
||||
ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
|
||||
if (!(status & LP5523_LEDTEST_DONE))
|
||||
usleep_range(3000, 10000);
|
||||
usleep_range(3000, 6000); /* Was not ready. Wait little bit */
|
||||
|
||||
ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd);
|
||||
vdd--; /* There may be some fluctuation in measurement */
|
||||
@ -468,16 +467,16 @@ static ssize_t lp5523_selftest(struct device *dev,
|
||||
chip->pdata->led_config[i].led_current);
|
||||
|
||||
lp5523_write(chip->client, LP5523_REG_LED_PWM_BASE + i, 0xff);
|
||||
/* let current stabilize 2ms before measurements start */
|
||||
usleep_range(2000, 10000);
|
||||
/* let current stabilize 2 - 4ms before measurements start */
|
||||
usleep_range(2000, 4000);
|
||||
lp5523_write(chip->client,
|
||||
LP5523_REG_LED_TEST_CTRL,
|
||||
LP5523_EN_LEDTEST | i);
|
||||
/* ledtest takes 2.7ms */
|
||||
usleep_range(3000, 10000);
|
||||
/* ADC conversion time is 2.7 ms typically */
|
||||
usleep_range(3000, 6000);
|
||||
ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status);
|
||||
if (!(status & LP5523_LEDTEST_DONE))
|
||||
usleep_range(3000, 10000);
|
||||
usleep_range(3000, 6000);/* Was not ready. Wait. */
|
||||
ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc);
|
||||
|
||||
if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM)
|
||||
@ -930,11 +929,16 @@ static int lp5523_probe(struct i2c_client *client,
|
||||
|
||||
if (pdata->enable) {
|
||||
pdata->enable(0);
|
||||
usleep_range(1000, 10000);
|
||||
usleep_range(1000, 2000); /* Keep enable down at least 1ms */
|
||||
pdata->enable(1);
|
||||
usleep_range(1000, 10000); /* Spec says min 500us */
|
||||
usleep_range(1000, 2000); /* 500us abs min. */
|
||||
}
|
||||
|
||||
lp5523_write(client, LP5523_REG_RESET, 0xff);
|
||||
usleep_range(10000, 20000); /*
|
||||
* Exact value is not available. 10 - 20ms
|
||||
* appears to be enough for reset.
|
||||
*/
|
||||
ret = lp5523_detect(client);
|
||||
if (ret)
|
||||
goto fail2;
|
||||
|
@ -102,6 +102,7 @@ static struct dmi_system_id __initdata nas_led_whitelist[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1337,7 +1337,7 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
|
||||
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
|
||||
rdev->sb_page);
|
||||
md_super_wait(rdev->mddev);
|
||||
return num_sectors / 2; /* kB for sysfs */
|
||||
return num_sectors;
|
||||
}
|
||||
|
||||
|
||||
@ -1704,7 +1704,7 @@ super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
|
||||
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
|
||||
rdev->sb_page);
|
||||
md_super_wait(rdev->mddev);
|
||||
return num_sectors / 2; /* kB for sysfs */
|
||||
return num_sectors;
|
||||
}
|
||||
|
||||
static struct super_type super_types[] = {
|
||||
@ -4338,6 +4338,8 @@ static int md_alloc(dev_t dev, char *name)
|
||||
if (mddev->kobj.sd &&
|
||||
sysfs_create_group(&mddev->kobj, &md_bitmap_group))
|
||||
printk(KERN_DEBUG "pointless warning\n");
|
||||
|
||||
blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA);
|
||||
abort:
|
||||
mutex_unlock(&disks_mutex);
|
||||
if (!error && mddev->kobj.sd) {
|
||||
|
@ -1161,6 +1161,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
|
||||
* is not possible.
|
||||
*/
|
||||
if (!test_bit(Faulty, &rdev->flags) &&
|
||||
!mddev->recovery_disabled &&
|
||||
mddev->degraded < conf->raid_disks) {
|
||||
err = -EBUSY;
|
||||
goto abort;
|
||||
|
@ -183,9 +183,7 @@ static int isl29020_probe(struct i2c_client *client,
|
||||
|
||||
static int isl29020_remove(struct i2c_client *client)
|
||||
{
|
||||
struct als_data *data = i2c_get_clientdata(client);
|
||||
sysfs_remove_group(&client->dev.kobj, &m_als_gr);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -245,6 +243,6 @@ static void __exit sensor_isl29020_exit(void)
|
||||
module_init(sensor_isl29020_init);
|
||||
module_exit(sensor_isl29020_exit);
|
||||
|
||||
MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
|
||||
MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com>");
|
||||
MODULE_DESCRIPTION("Intersil isl29020 ALS Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -439,18 +439,23 @@ xpc_discovery(void)
|
||||
* nodes that can comprise an access protection grouping. The access
|
||||
* protection is in regards to memory, IOI and IPI.
|
||||
*/
|
||||
max_regions = 64;
|
||||
region_size = xp_region_size;
|
||||
|
||||
switch (region_size) {
|
||||
case 128:
|
||||
max_regions *= 2;
|
||||
case 64:
|
||||
max_regions *= 2;
|
||||
case 32:
|
||||
max_regions *= 2;
|
||||
region_size = 16;
|
||||
DBUG_ON(!is_shub2());
|
||||
if (is_uv())
|
||||
max_regions = 256;
|
||||
else {
|
||||
max_regions = 64;
|
||||
|
||||
switch (region_size) {
|
||||
case 128:
|
||||
max_regions *= 2;
|
||||
case 64:
|
||||
max_regions *= 2;
|
||||
case 32:
|
||||
max_regions *= 2;
|
||||
region_size = 16;
|
||||
DBUG_ON(!is_shub2());
|
||||
}
|
||||
}
|
||||
|
||||
for (region = 0; region < max_regions; region++) {
|
||||
|
@ -466,6 +466,12 @@ config MMC_SH_MMCIF
|
||||
|
||||
This driver supports MMCIF in sh7724/sh7757/sh7372.
|
||||
|
||||
config SH_MMCIF_DMA
|
||||
bool "Use DMA for MMCIF"
|
||||
depends on MMC_SH_MMCIF
|
||||
help
|
||||
Use SH dma-engine driver for data transfer
|
||||
|
||||
config MMC_JZ4740
|
||||
tristate "JZ4740 SD/Multimedia Card Interface support"
|
||||
depends on MACH_JZ4740
|
||||
|
@ -16,16 +16,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/core.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mmc/sh_mmcif.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define DRIVER_NAME "sh_mmcif"
|
||||
#define DRIVER_VERSION "2010-04-28"
|
||||
@ -62,25 +65,6 @@
|
||||
/* CE_BLOCK_SET */
|
||||
#define BLOCK_SIZE_MASK 0x0000ffff
|
||||
|
||||
/* CE_CLK_CTRL */
|
||||
#define CLK_ENABLE (1 << 24) /* 1: output mmc clock */
|
||||
#define CLK_CLEAR ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
|
||||
#define CLK_SUP_PCLK ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
|
||||
#define SRSPTO_256 ((1 << 13) | (0 << 12)) /* resp timeout */
|
||||
#define SRBSYTO_29 ((1 << 11) | (1 << 10) | \
|
||||
(1 << 9) | (1 << 8)) /* resp busy timeout */
|
||||
#define SRWDTO_29 ((1 << 7) | (1 << 6) | \
|
||||
(1 << 5) | (1 << 4)) /* read/write timeout */
|
||||
#define SCCSTO_29 ((1 << 3) | (1 << 2) | \
|
||||
(1 << 1) | (1 << 0)) /* ccs timeout */
|
||||
|
||||
/* CE_BUF_ACC */
|
||||
#define BUF_ACC_DMAWEN (1 << 25)
|
||||
#define BUF_ACC_DMAREN (1 << 24)
|
||||
#define BUF_ACC_BUSW_32 (0 << 17)
|
||||
#define BUF_ACC_BUSW_16 (1 << 17)
|
||||
#define BUF_ACC_ATYP (1 << 16)
|
||||
|
||||
/* CE_INT */
|
||||
#define INT_CCSDE (1 << 29)
|
||||
#define INT_CMD12DRE (1 << 26)
|
||||
@ -165,10 +149,6 @@
|
||||
STS2_AC12BSYTO | STS2_RSPBSYTO | \
|
||||
STS2_AC12RSPTO | STS2_RSPTO)
|
||||
|
||||
/* CE_VERSION */
|
||||
#define SOFT_RST_ON (1 << 31)
|
||||
#define SOFT_RST_OFF (0 << 31)
|
||||
|
||||
#define CLKDEV_EMMC_DATA 52000000 /* 52MHz */
|
||||
#define CLKDEV_MMC_DATA 20000000 /* 20MHz */
|
||||
#define CLKDEV_INIT 400000 /* 400 KHz */
|
||||
@ -176,18 +156,21 @@
|
||||
struct sh_mmcif_host {
|
||||
struct mmc_host *mmc;
|
||||
struct mmc_data *data;
|
||||
struct mmc_command *cmd;
|
||||
struct platform_device *pd;
|
||||
struct clk *hclk;
|
||||
unsigned int clk;
|
||||
int bus_width;
|
||||
u16 wait_int;
|
||||
u16 sd_error;
|
||||
bool sd_error;
|
||||
long timeout;
|
||||
void __iomem *addr;
|
||||
wait_queue_head_t intr_wait;
|
||||
};
|
||||
struct completion intr_wait;
|
||||
|
||||
/* DMA support */
|
||||
struct dma_chan *chan_rx;
|
||||
struct dma_chan *chan_tx;
|
||||
struct completion dma_complete;
|
||||
unsigned int dma_sglen;
|
||||
};
|
||||
|
||||
static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
|
||||
unsigned int reg, u32 val)
|
||||
@ -201,6 +184,208 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host,
|
||||
writel(~val & readl(host->addr + reg), host->addr + reg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SH_MMCIF_DMA
|
||||
static void mmcif_dma_complete(void *arg)
|
||||
{
|
||||
struct sh_mmcif_host *host = arg;
|
||||
dev_dbg(&host->pd->dev, "Command completed\n");
|
||||
|
||||
if (WARN(!host->data, "%s: NULL data in DMA completion!\n",
|
||||
dev_name(&host->pd->dev)))
|
||||
return;
|
||||
|
||||
if (host->data->flags & MMC_DATA_READ)
|
||||
dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
|
||||
DMA_FROM_DEVICE);
|
||||
else
|
||||
dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
complete(&host->dma_complete);
|
||||
}
|
||||
|
||||
static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
|
||||
{
|
||||
struct scatterlist *sg = host->data->sg;
|
||||
struct dma_async_tx_descriptor *desc = NULL;
|
||||
struct dma_chan *chan = host->chan_rx;
|
||||
dma_cookie_t cookie = -EINVAL;
|
||||
int ret;
|
||||
|
||||
ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_FROM_DEVICE);
|
||||
if (ret > 0) {
|
||||
host->dma_sglen = ret;
|
||||
desc = chan->device->device_prep_slave_sg(chan, sg, ret,
|
||||
DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
}
|
||||
|
||||
if (desc) {
|
||||
desc->callback = mmcif_dma_complete;
|
||||
desc->callback_param = host;
|
||||
cookie = desc->tx_submit(desc);
|
||||
if (cookie < 0) {
|
||||
desc = NULL;
|
||||
ret = cookie;
|
||||
} else {
|
||||
sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
|
||||
chan->device->device_issue_pending(chan);
|
||||
}
|
||||
}
|
||||
dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
|
||||
__func__, host->data->sg_len, ret, cookie);
|
||||
|
||||
if (!desc) {
|
||||
/* DMA failed, fall back to PIO */
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
host->chan_rx = NULL;
|
||||
host->dma_sglen = 0;
|
||||
dma_release_channel(chan);
|
||||
/* Free the Tx channel too */
|
||||
chan = host->chan_tx;
|
||||
if (chan) {
|
||||
host->chan_tx = NULL;
|
||||
dma_release_channel(chan);
|
||||
}
|
||||
dev_warn(&host->pd->dev,
|
||||
"DMA failed: %d, falling back to PIO\n", ret);
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
|
||||
}
|
||||
|
||||
dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
|
||||
desc, cookie, host->data->sg_len);
|
||||
}
|
||||
|
||||
static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
|
||||
{
|
||||
struct scatterlist *sg = host->data->sg;
|
||||
struct dma_async_tx_descriptor *desc = NULL;
|
||||
struct dma_chan *chan = host->chan_tx;
|
||||
dma_cookie_t cookie = -EINVAL;
|
||||
int ret;
|
||||
|
||||
ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_TO_DEVICE);
|
||||
if (ret > 0) {
|
||||
host->dma_sglen = ret;
|
||||
desc = chan->device->device_prep_slave_sg(chan, sg, ret,
|
||||
DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||
}
|
||||
|
||||
if (desc) {
|
||||
desc->callback = mmcif_dma_complete;
|
||||
desc->callback_param = host;
|
||||
cookie = desc->tx_submit(desc);
|
||||
if (cookie < 0) {
|
||||
desc = NULL;
|
||||
ret = cookie;
|
||||
} else {
|
||||
sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
|
||||
chan->device->device_issue_pending(chan);
|
||||
}
|
||||
}
|
||||
dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
|
||||
__func__, host->data->sg_len, ret, cookie);
|
||||
|
||||
if (!desc) {
|
||||
/* DMA failed, fall back to PIO */
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
host->chan_tx = NULL;
|
||||
host->dma_sglen = 0;
|
||||
dma_release_channel(chan);
|
||||
/* Free the Rx channel too */
|
||||
chan = host->chan_rx;
|
||||
if (chan) {
|
||||
host->chan_rx = NULL;
|
||||
dma_release_channel(chan);
|
||||
}
|
||||
dev_warn(&host->pd->dev,
|
||||
"DMA failed: %d, falling back to PIO\n", ret);
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
|
||||
}
|
||||
|
||||
dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d\n", __func__,
|
||||
desc, cookie);
|
||||
}
|
||||
|
||||
static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
|
||||
{
|
||||
dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
|
||||
chan->private = arg;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
|
||||
struct sh_mmcif_plat_data *pdata)
|
||||
{
|
||||
host->dma_sglen = 0;
|
||||
|
||||
/* We can only either use DMA for both Tx and Rx or not use it at all */
|
||||
if (pdata->dma) {
|
||||
dma_cap_mask_t mask;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
|
||||
host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
|
||||
&pdata->dma->chan_priv_tx);
|
||||
dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
|
||||
host->chan_tx);
|
||||
|
||||
if (!host->chan_tx)
|
||||
return;
|
||||
|
||||
host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
|
||||
&pdata->dma->chan_priv_rx);
|
||||
dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
|
||||
host->chan_rx);
|
||||
|
||||
if (!host->chan_rx) {
|
||||
dma_release_channel(host->chan_tx);
|
||||
host->chan_tx = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
init_completion(&host->dma_complete);
|
||||
}
|
||||
}
|
||||
|
||||
static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
|
||||
{
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
|
||||
/* Descriptors are freed automatically */
|
||||
if (host->chan_tx) {
|
||||
struct dma_chan *chan = host->chan_tx;
|
||||
host->chan_tx = NULL;
|
||||
dma_release_channel(chan);
|
||||
}
|
||||
if (host->chan_rx) {
|
||||
struct dma_chan *chan = host->chan_rx;
|
||||
host->chan_rx = NULL;
|
||||
dma_release_channel(chan);
|
||||
}
|
||||
|
||||
host->dma_sglen = 0;
|
||||
}
|
||||
#else
|
||||
static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
|
||||
{
|
||||
}
|
||||
|
||||
static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
|
||||
{
|
||||
}
|
||||
|
||||
static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
|
||||
struct sh_mmcif_plat_data *pdata)
|
||||
{
|
||||
/* host->chan_tx, host->chan_tx and host->dma_sglen are all zero */
|
||||
}
|
||||
|
||||
static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
|
||||
{
|
||||
@ -239,13 +424,12 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
|
||||
u32 state1, state2;
|
||||
int ret, timeout = 10000000;
|
||||
|
||||
host->sd_error = 0;
|
||||
host->wait_int = 0;
|
||||
host->sd_error = false;
|
||||
|
||||
state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
|
||||
state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
|
||||
pr_debug("%s: ERR HOST_STS1 = %08x\n", DRIVER_NAME, state1);
|
||||
pr_debug("%s: ERR HOST_STS2 = %08x\n", DRIVER_NAME, state2);
|
||||
dev_dbg(&host->pd->dev, "ERR HOST_STS1 = %08x\n", state1);
|
||||
dev_dbg(&host->pd->dev, "ERR HOST_STS2 = %08x\n", state2);
|
||||
|
||||
if (state1 & STS1_CMDSEQ) {
|
||||
sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
|
||||
@ -253,8 +437,8 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
|
||||
while (1) {
|
||||
timeout--;
|
||||
if (timeout < 0) {
|
||||
pr_err(DRIVER_NAME": Forceed end of " \
|
||||
"command sequence timeout err\n");
|
||||
dev_err(&host->pd->dev,
|
||||
"Forceed end of command sequence timeout err\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
|
||||
@ -263,18 +447,18 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
|
||||
mdelay(1);
|
||||
}
|
||||
sh_mmcif_sync_reset(host);
|
||||
pr_debug(DRIVER_NAME": Forced end of command sequence\n");
|
||||
dev_dbg(&host->pd->dev, "Forced end of command sequence\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (state2 & STS2_CRC_ERR) {
|
||||
pr_debug(DRIVER_NAME": Happened CRC error\n");
|
||||
dev_dbg(&host->pd->dev, ": Happened CRC error\n");
|
||||
ret = -EIO;
|
||||
} else if (state2 & STS2_TIMEOUT_ERR) {
|
||||
pr_debug(DRIVER_NAME": Happened Timeout error\n");
|
||||
dev_dbg(&host->pd->dev, ": Happened Timeout error\n");
|
||||
ret = -ETIMEDOUT;
|
||||
} else {
|
||||
pr_debug(DRIVER_NAME": Happened End/Index error\n");
|
||||
dev_dbg(&host->pd->dev, ": Happened End/Index error\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
return ret;
|
||||
@ -287,17 +471,13 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host,
|
||||
long time;
|
||||
u32 blocksize, i, *p = sg_virt(data->sg);
|
||||
|
||||
host->wait_int = 0;
|
||||
|
||||
/* buf read enable */
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
if (time <= 0 || host->sd_error)
|
||||
return sh_mmcif_error_manage(host);
|
||||
|
||||
host->wait_int = 0;
|
||||
blocksize = (BLOCK_SIZE_MASK &
|
||||
sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
|
||||
for (i = 0; i < blocksize / 4; i++)
|
||||
@ -305,13 +485,11 @@ static int sh_mmcif_single_read(struct sh_mmcif_host *host,
|
||||
|
||||
/* buffer read end */
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
if (time <= 0 || host->sd_error)
|
||||
return sh_mmcif_error_manage(host);
|
||||
|
||||
host->wait_int = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -326,19 +504,15 @@ static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
|
||||
MMCIF_CE_BLOCK_SET);
|
||||
for (j = 0; j < data->sg_len; j++) {
|
||||
p = sg_virt(data->sg);
|
||||
host->wait_int = 0;
|
||||
for (sec = 0; sec < data->sg->length / blocksize; sec++) {
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
|
||||
/* buf read enable */
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
|
||||
if (host->wait_int != 1 &&
|
||||
(time == 0 || host->sd_error != 0))
|
||||
if (time <= 0 || host->sd_error)
|
||||
return sh_mmcif_error_manage(host);
|
||||
|
||||
host->wait_int = 0;
|
||||
for (i = 0; i < blocksize / 4; i++)
|
||||
*p++ = sh_mmcif_readl(host->addr,
|
||||
MMCIF_CE_DATA);
|
||||
@ -356,17 +530,14 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
|
||||
long time;
|
||||
u32 blocksize, i, *p = sg_virt(data->sg);
|
||||
|
||||
host->wait_int = 0;
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
|
||||
|
||||
/* buf write enable */
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
if (time <= 0 || host->sd_error)
|
||||
return sh_mmcif_error_manage(host);
|
||||
|
||||
host->wait_int = 0;
|
||||
blocksize = (BLOCK_SIZE_MASK &
|
||||
sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
|
||||
for (i = 0; i < blocksize / 4; i++)
|
||||
@ -375,13 +546,11 @@ static int sh_mmcif_single_write(struct sh_mmcif_host *host,
|
||||
/* buffer write end */
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
|
||||
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
if (time <= 0 || host->sd_error)
|
||||
return sh_mmcif_error_manage(host);
|
||||
|
||||
host->wait_int = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -397,19 +566,15 @@ static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
|
||||
|
||||
for (j = 0; j < data->sg_len; j++) {
|
||||
p = sg_virt(data->sg);
|
||||
host->wait_int = 0;
|
||||
for (sec = 0; sec < data->sg->length / blocksize; sec++) {
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
|
||||
/* buf write enable*/
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
|
||||
if (host->wait_int != 1 &&
|
||||
(time == 0 || host->sd_error != 0))
|
||||
if (time <= 0 || host->sd_error)
|
||||
return sh_mmcif_error_manage(host);
|
||||
|
||||
host->wait_int = 0;
|
||||
for (i = 0; i < blocksize / 4; i++)
|
||||
sh_mmcif_writel(host->addr,
|
||||
MMCIF_CE_DATA, *p++);
|
||||
@ -457,7 +622,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
|
||||
tmp |= CMD_SET_RTYP_17B;
|
||||
break;
|
||||
default:
|
||||
pr_err(DRIVER_NAME": Not support type response.\n");
|
||||
dev_err(&host->pd->dev, "Unsupported response type.\n");
|
||||
break;
|
||||
}
|
||||
switch (opc) {
|
||||
@ -485,7 +650,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
|
||||
tmp |= CMD_SET_DATW_8;
|
||||
break;
|
||||
default:
|
||||
pr_err(DRIVER_NAME": Not support bus width.\n");
|
||||
dev_err(&host->pd->dev, "Unsupported bus width.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -513,10 +678,10 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
|
||||
return opc = ((opc << 24) | tmp);
|
||||
}
|
||||
|
||||
static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host,
|
||||
static int sh_mmcif_data_trans(struct sh_mmcif_host *host,
|
||||
struct mmc_request *mrq, u32 opc)
|
||||
{
|
||||
u32 ret;
|
||||
int ret;
|
||||
|
||||
switch (opc) {
|
||||
case MMC_READ_MULTIPLE_BLOCK:
|
||||
@ -533,7 +698,7 @@ static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host,
|
||||
ret = sh_mmcif_single_read(host, mrq);
|
||||
break;
|
||||
default:
|
||||
pr_err(DRIVER_NAME": NOT SUPPORT CMD = d'%08d\n", opc);
|
||||
dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -547,8 +712,6 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
|
||||
int ret = 0, mask = 0;
|
||||
u32 opc = cmd->opcode;
|
||||
|
||||
host->cmd = cmd;
|
||||
|
||||
switch (opc) {
|
||||
/* respons busy check */
|
||||
case MMC_SWITCH:
|
||||
@ -579,13 +742,12 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
|
||||
/* set arg */
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
|
||||
host->wait_int = 0;
|
||||
/* set cmd */
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
|
||||
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 || host->sd_error == 1, host->timeout);
|
||||
if (host->wait_int != 1 && time == 0) {
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
if (time <= 0) {
|
||||
cmd->error = sh_mmcif_error_manage(host);
|
||||
return;
|
||||
}
|
||||
@ -597,26 +759,34 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
|
||||
cmd->error = -ETIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: Cmd(d'%d) err\n",
|
||||
DRIVER_NAME, cmd->opcode);
|
||||
dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n",
|
||||
cmd->opcode);
|
||||
cmd->error = sh_mmcif_error_manage(host);
|
||||
break;
|
||||
}
|
||||
host->sd_error = 0;
|
||||
host->wait_int = 0;
|
||||
host->sd_error = false;
|
||||
return;
|
||||
}
|
||||
if (!(cmd->flags & MMC_RSP_PRESENT)) {
|
||||
cmd->error = ret;
|
||||
host->wait_int = 0;
|
||||
cmd->error = 0;
|
||||
return;
|
||||
}
|
||||
if (host->wait_int == 1) {
|
||||
sh_mmcif_get_response(host, cmd);
|
||||
host->wait_int = 0;
|
||||
}
|
||||
sh_mmcif_get_response(host, cmd);
|
||||
if (host->data) {
|
||||
ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
|
||||
if (!host->dma_sglen) {
|
||||
ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
|
||||
} else {
|
||||
long time =
|
||||
wait_for_completion_interruptible_timeout(&host->dma_complete,
|
||||
host->timeout);
|
||||
if (!time)
|
||||
ret = -ETIMEDOUT;
|
||||
else if (time < 0)
|
||||
ret = time;
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
|
||||
BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
|
||||
host->dma_sglen = 0;
|
||||
}
|
||||
if (ret < 0)
|
||||
mrq->data->bytes_xfered = 0;
|
||||
else
|
||||
@ -636,20 +806,18 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
|
||||
else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)
|
||||
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
|
||||
else {
|
||||
pr_err(DRIVER_NAME": not support stop cmd\n");
|
||||
dev_err(&host->pd->dev, "unsupported stop cmd\n");
|
||||
cmd->error = sh_mmcif_error_manage(host);
|
||||
return;
|
||||
}
|
||||
|
||||
time = wait_event_interruptible_timeout(host->intr_wait,
|
||||
host->wait_int == 1 ||
|
||||
host->sd_error == 1, host->timeout);
|
||||
if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) {
|
||||
time = wait_for_completion_interruptible_timeout(&host->intr_wait,
|
||||
host->timeout);
|
||||
if (time <= 0 || host->sd_error) {
|
||||
cmd->error = sh_mmcif_error_manage(host);
|
||||
return;
|
||||
}
|
||||
sh_mmcif_get_cmd12response(host, cmd);
|
||||
host->wait_int = 0;
|
||||
cmd->error = 0;
|
||||
}
|
||||
|
||||
@ -676,6 +844,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
break;
|
||||
}
|
||||
host->data = mrq->data;
|
||||
if (mrq->data) {
|
||||
if (mrq->data->flags & MMC_DATA_READ) {
|
||||
if (host->chan_rx)
|
||||
sh_mmcif_start_dma_rx(host);
|
||||
} else {
|
||||
if (host->chan_tx)
|
||||
sh_mmcif_start_dma_tx(host);
|
||||
}
|
||||
}
|
||||
sh_mmcif_start_cmd(host, mrq, mrq->cmd);
|
||||
host->data = NULL;
|
||||
|
||||
@ -735,7 +912,7 @@ static void sh_mmcif_detect(struct mmc_host *mmc)
|
||||
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
|
||||
{
|
||||
struct sh_mmcif_host *host = dev_id;
|
||||
u32 state = 0;
|
||||
u32 state;
|
||||
int err = 0;
|
||||
|
||||
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
|
||||
@ -774,17 +951,19 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
|
||||
err = 1;
|
||||
} else {
|
||||
pr_debug("%s: Not support int\n", DRIVER_NAME);
|
||||
dev_dbg(&host->pd->dev, "Not support int\n");
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
|
||||
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
|
||||
err = 1;
|
||||
}
|
||||
if (err) {
|
||||
host->sd_error = 1;
|
||||
pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state);
|
||||
host->sd_error = true;
|
||||
dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
|
||||
}
|
||||
host->wait_int = 1;
|
||||
wake_up(&host->intr_wait);
|
||||
if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
|
||||
complete(&host->intr_wait);
|
||||
else
|
||||
dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -793,8 +972,8 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0, irq[2];
|
||||
struct mmc_host *mmc;
|
||||
struct sh_mmcif_host *host = NULL;
|
||||
struct sh_mmcif_plat_data *pd = NULL;
|
||||
struct sh_mmcif_host *host;
|
||||
struct sh_mmcif_plat_data *pd;
|
||||
struct resource *res;
|
||||
void __iomem *reg;
|
||||
char clk_name[8];
|
||||
@ -802,7 +981,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
|
||||
irq[0] = platform_get_irq(pdev, 0);
|
||||
irq[1] = platform_get_irq(pdev, 1);
|
||||
if (irq[0] < 0 || irq[1] < 0) {
|
||||
pr_err(DRIVER_NAME": Get irq error\n");
|
||||
dev_err(&pdev->dev, "Get irq error\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@ -815,7 +994,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "ioremap error.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
pd = (struct sh_mmcif_plat_data *)(pdev->dev.platform_data);
|
||||
pd = pdev->dev.platform_data;
|
||||
if (!pd) {
|
||||
dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
|
||||
ret = -ENXIO;
|
||||
@ -842,7 +1021,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
|
||||
host->clk = clk_get_rate(host->hclk);
|
||||
host->pd = pdev;
|
||||
|
||||
init_waitqueue_head(&host->intr_wait);
|
||||
init_completion(&host->intr_wait);
|
||||
|
||||
mmc->ops = &sh_mmcif_ops;
|
||||
mmc->f_max = host->clk;
|
||||
@ -858,33 +1037,37 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
|
||||
mmc->caps = MMC_CAP_MMC_HIGHSPEED;
|
||||
if (pd->caps)
|
||||
mmc->caps |= pd->caps;
|
||||
mmc->max_segs = 128;
|
||||
mmc->max_segs = 32;
|
||||
mmc->max_blk_size = 512;
|
||||
mmc->max_blk_count = 65535;
|
||||
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
|
||||
mmc->max_req_size = PAGE_CACHE_SIZE * mmc->max_segs;
|
||||
mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
|
||||
mmc->max_seg_size = mmc->max_req_size;
|
||||
|
||||
sh_mmcif_sync_reset(host);
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
/* See if we also get DMA */
|
||||
sh_mmcif_request_dma(host, pd);
|
||||
|
||||
mmc_add_host(mmc);
|
||||
|
||||
ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
|
||||
if (ret) {
|
||||
pr_err(DRIVER_NAME": request_irq error (sh_mmc:error)\n");
|
||||
dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
|
||||
goto clean_up2;
|
||||
}
|
||||
ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
|
||||
if (ret) {
|
||||
free_irq(irq[0], host);
|
||||
pr_err(DRIVER_NAME": request_irq error (sh_mmc:int)\n");
|
||||
dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
|
||||
goto clean_up2;
|
||||
}
|
||||
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
|
||||
sh_mmcif_detect(host->mmc);
|
||||
|
||||
pr_info("%s: driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
|
||||
pr_debug("%s: chip ver H'%04x\n", DRIVER_NAME,
|
||||
dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
|
||||
dev_dbg(&pdev->dev, "chip ver H'%04x\n",
|
||||
sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
|
||||
return ret;
|
||||
|
||||
@ -903,20 +1086,22 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
|
||||
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
|
||||
int irq[2];
|
||||
|
||||
mmc_remove_host(host->mmc);
|
||||
sh_mmcif_release_dma(host);
|
||||
|
||||
if (host->addr)
|
||||
iounmap(host->addr);
|
||||
|
||||
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
|
||||
|
||||
irq[0] = platform_get_irq(pdev, 0);
|
||||
irq[1] = platform_get_irq(pdev, 1);
|
||||
|
||||
if (host->addr)
|
||||
iounmap(host->addr);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
mmc_remove_host(host->mmc);
|
||||
|
||||
free_irq(irq[0], host);
|
||||
free_irq(irq[1], host);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
clk_disable(host->hclk);
|
||||
mmc_free_host(host->mmc);
|
||||
|
||||
@ -947,5 +1132,5 @@ module_exit(sh_mmcif_exit);
|
||||
|
||||
MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS(DRIVER_NAME);
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>");
|
||||
|
@ -2945,6 +2945,18 @@ source "drivers/s390/net/Kconfig"
|
||||
|
||||
source "drivers/net/caif/Kconfig"
|
||||
|
||||
config TILE_NET
|
||||
tristate "Tilera GBE/XGBE network driver support"
|
||||
depends on TILE
|
||||
default y
|
||||
select CRC32
|
||||
help
|
||||
This is a standard Linux network device driver for the
|
||||
on-chip Tilera Gigabit Ethernet and XAUI interfaces.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called tile_net.
|
||||
|
||||
config XEN_NETDEV_FRONTEND
|
||||
tristate "Xen network device frontend driver"
|
||||
depends on XEN
|
||||
|
@ -301,3 +301,4 @@ obj-$(CONFIG_CAIF) += caif/
|
||||
|
||||
obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
|
||||
obj-$(CONFIG_PCH_GBE) += pch_gbe/
|
||||
obj-$(CONFIG_TILE_NET) += tile/
|
||||
|
10
drivers/net/tile/Makefile
Normal file
10
drivers/net/tile/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Makefile for the TILE on-chip networking support.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_TILE_NET) += tile_net.o
|
||||
ifdef CONFIG_TILEGX
|
||||
tile_net-objs := tilegx.o mpipe.o iorpc_mpipe.o dma_queue.o
|
||||
else
|
||||
tile_net-objs := tilepro.o
|
||||
endif
|
2406
drivers/net/tile/tilepro.c
Normal file
2406
drivers/net/tile/tilepro.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
|
||||
obj-$(CONFIG_X86_VISWS) += setup-irq.o
|
||||
obj-$(CONFIG_MN10300) += setup-bus.o
|
||||
obj-$(CONFIG_MICROBLAZE) += setup-bus.o
|
||||
obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
|
||||
|
||||
#
|
||||
# ACPI Related PCI FW Functions
|
||||
|
@ -2136,6 +2136,24 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
|
||||
quirk_unhide_mch_dev6);
|
||||
|
||||
#ifdef CONFIG_TILE
|
||||
/*
|
||||
* The Tilera TILEmpower platform needs to set the link speed
|
||||
* to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed
|
||||
* setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe
|
||||
* capability register of the PEX8624 PCIe switch. The switch
|
||||
* supports link speed auto negotiation, but falsely sets
|
||||
* the link speed to 5GT/s.
|
||||
*/
|
||||
static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
|
||||
{
|
||||
if (tile_plx_gen1) {
|
||||
pci_write_config_dword(dev, 0x98, 0x1);
|
||||
mdelay(50);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
|
||||
#endif /* CONFIG_TILE */
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
/* Some chipsets do not support MSI. We cannot easily rely on setting
|
||||
|
@ -345,7 +345,7 @@ extern int fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
|
||||
* : SCpnt - Command to queue
|
||||
* Returns : 0 - success, else error
|
||||
*/
|
||||
extern int fas216_noqueue_command(struct Scsi_Host *, struct scsi_cmnd *)
|
||||
extern int fas216_noqueue_command(struct Scsi_Host *, struct scsi_cmnd *);
|
||||
|
||||
/* Function: irqreturn_t fas216_intr (FAS216_Info *info)
|
||||
* Purpose : handle interrupts from the interface to progress a command
|
||||
|
@ -418,8 +418,11 @@ int clk_register(struct clk *clk)
|
||||
list_add(&clk->sibling, &root_clks);
|
||||
|
||||
list_add(&clk->node, &clock_list);
|
||||
|
||||
#ifdef CONFIG_SH_CLK_CPG_LEGACY
|
||||
if (clk->ops && clk->ops->init)
|
||||
clk->ops->init(clk);
|
||||
#endif
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&clock_list_sem);
|
||||
@ -454,12 +457,6 @@ unsigned long clk_get_rate(struct clk *clk)
|
||||
EXPORT_SYMBOL_GPL(clk_get_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return clk_set_rate_ex(clk, rate, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
|
||||
int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
|
||||
{
|
||||
int ret = -EOPNOTSUPP;
|
||||
unsigned long flags;
|
||||
@ -467,7 +464,7 @@ int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
|
||||
spin_lock_irqsave(&clock_lock, flags);
|
||||
|
||||
if (likely(clk->ops && clk->ops->set_rate)) {
|
||||
ret = clk->ops->set_rate(clk, rate, algo_id);
|
||||
ret = clk->ops->set_rate(clk, rate);
|
||||
if (ret != 0)
|
||||
goto out_unlock;
|
||||
} else {
|
||||
@ -485,7 +482,7 @@ out_unlock:
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate_ex);
|
||||
EXPORT_SYMBOL_GPL(clk_set_rate);
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
@ -653,8 +650,7 @@ static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
|
||||
clkp->ops->set_parent(clkp,
|
||||
clkp->parent);
|
||||
if (likely(clkp->ops->set_rate))
|
||||
clkp->ops->set_rate(clkp,
|
||||
rate, NO_CHANGE);
|
||||
clkp->ops->set_rate(clkp, rate);
|
||||
else if (likely(clkp->ops->recalc))
|
||||
clkp->rate = clkp->ops->recalc(clkp);
|
||||
}
|
||||
|
@ -110,8 +110,7 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div6_set_rate(struct clk *clk,
|
||||
unsigned long rate, int algo_id)
|
||||
static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long value;
|
||||
int idx;
|
||||
@ -132,7 +131,7 @@ static int sh_clk_div6_enable(struct clk *clk)
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
|
||||
ret = sh_clk_div6_set_rate(clk, clk->rate);
|
||||
if (ret == 0) {
|
||||
value = __raw_readl(clk->enable_reg);
|
||||
value &= ~0x100; /* clear stop bit to enable clock */
|
||||
@ -253,7 +252,7 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
|
||||
static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
struct clk_div4_table *d4t = clk->priv;
|
||||
unsigned long value;
|
||||
|
@ -197,12 +197,12 @@ static int backlight_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
||||
if (bd->ops->options & BL_CORE_SUSPENDRESUME) {
|
||||
mutex_lock(&bd->ops_lock);
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
|
||||
bd->props.state |= BL_CORE_SUSPENDED;
|
||||
backlight_update_status(bd);
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
}
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -211,12 +211,12 @@ static int backlight_resume(struct device *dev)
|
||||
{
|
||||
struct backlight_device *bd = to_backlight_device(dev);
|
||||
|
||||
if (bd->ops->options & BL_CORE_SUSPENDRESUME) {
|
||||
mutex_lock(&bd->ops_lock);
|
||||
mutex_lock(&bd->ops_lock);
|
||||
if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
|
||||
bd->props.state &= ~BL_CORE_SUSPENDED;
|
||||
backlight_update_status(bd);
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
}
|
||||
mutex_unlock(&bd->ops_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -88,34 +88,48 @@ static const struct fb_cmap default_16_colors = {
|
||||
*
|
||||
*/
|
||||
|
||||
int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
|
||||
int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
|
||||
{
|
||||
int size = len*sizeof(u16);
|
||||
int size = len * sizeof(u16);
|
||||
int ret = -ENOMEM;
|
||||
|
||||
if (cmap->len != len) {
|
||||
fb_dealloc_cmap(cmap);
|
||||
if (!len)
|
||||
return 0;
|
||||
if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
|
||||
goto fail;
|
||||
if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
|
||||
goto fail;
|
||||
if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
|
||||
goto fail;
|
||||
if (transp) {
|
||||
if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
|
||||
if (cmap->len != len) {
|
||||
fb_dealloc_cmap(cmap);
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
cmap->red = kmalloc(size, flags);
|
||||
if (!cmap->red)
|
||||
goto fail;
|
||||
cmap->green = kmalloc(size, flags);
|
||||
if (!cmap->green)
|
||||
goto fail;
|
||||
cmap->blue = kmalloc(size, flags);
|
||||
if (!cmap->blue)
|
||||
goto fail;
|
||||
if (transp) {
|
||||
cmap->transp = kmalloc(size, flags);
|
||||
if (!cmap->transp)
|
||||
goto fail;
|
||||
} else {
|
||||
cmap->transp = NULL;
|
||||
}
|
||||
}
|
||||
cmap->start = 0;
|
||||
cmap->len = len;
|
||||
ret = fb_copy_cmap(fb_default_cmap(len), cmap);
|
||||
if (ret)
|
||||
goto fail;
|
||||
} else
|
||||
cmap->transp = NULL;
|
||||
}
|
||||
cmap->start = 0;
|
||||
cmap->len = len;
|
||||
fb_copy_cmap(fb_default_cmap(len), cmap);
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fb_dealloc_cmap(cmap);
|
||||
return -ENOMEM;
|
||||
fb_dealloc_cmap(cmap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
|
||||
{
|
||||
return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,8 +264,12 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
|
||||
int rc, size = cmap->len * sizeof(u16);
|
||||
struct fb_cmap umap;
|
||||
|
||||
if (size < 0 || size < cmap->len)
|
||||
return -E2BIG;
|
||||
|
||||
memset(&umap, 0, sizeof(struct fb_cmap));
|
||||
rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
|
||||
rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
|
||||
GFP_KERNEL);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (copy_from_user(umap.red, cmap->red, size) ||
|
||||
|
@ -276,10 +276,10 @@ static void lx_graphics_enable(struct fb_info *info)
|
||||
write_fp(par, FP_PT1, 0);
|
||||
temp = FP_PT2_SCRC;
|
||||
|
||||
if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
|
||||
if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
|
||||
temp |= FP_PT2_HSP;
|
||||
|
||||
if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
|
||||
if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
|
||||
temp |= FP_PT2_VSP;
|
||||
|
||||
write_fp(par, FP_PT2, temp);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/ipu.h>
|
||||
#include <mach/mx3fb.h>
|
||||
@ -1420,6 +1421,9 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
|
||||
struct device *dev;
|
||||
struct mx3fb_platform_data *mx3fb_pdata;
|
||||
|
||||
if (!imx_dma_is_ipu(chan))
|
||||
return false;
|
||||
|
||||
if (!rq)
|
||||
return false;
|
||||
|
||||
|
@ -860,7 +860,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
|
||||
/* Couldn't reconfigure, hopefully, can continue as before */
|
||||
return;
|
||||
|
||||
info->fix.line_length = mode2.xres * (ch->cfg.bpp / 8);
|
||||
info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
|
||||
|
||||
/*
|
||||
* fb_set_var() calls the notifier change internally, only if
|
||||
@ -868,7 +868,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
|
||||
* user event, we have to call the chain ourselves.
|
||||
*/
|
||||
event.info = info;
|
||||
event.data = &mode2;
|
||||
event.data = &mode1;
|
||||
fb_notifier_call_chain(evnt, &event);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,21 +53,8 @@
|
||||
#ifndef _INIT_H_
|
||||
#define _INIT_H_
|
||||
|
||||
#include "osdef.h"
|
||||
#include "initdef.h"
|
||||
|
||||
#ifdef SIS_XORG_XF86
|
||||
#include "sis.h"
|
||||
#define SIS_NEED_inSISREG
|
||||
#define SIS_NEED_inSISREGW
|
||||
#define SIS_NEED_inSISREGL
|
||||
#define SIS_NEED_outSISREG
|
||||
#define SIS_NEED_outSISREGW
|
||||
#define SIS_NEED_outSISREGL
|
||||
#include "sis_regs.h"
|
||||
#endif
|
||||
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
#include "vgatypes.h"
|
||||
#include "vstruct.h"
|
||||
#ifdef SIS_CP
|
||||
@ -78,7 +65,6 @@
|
||||
#include <linux/fb.h>
|
||||
#include "sis.h"
|
||||
#include <video/sisfb.h>
|
||||
#endif
|
||||
|
||||
/* Mode numbers */
|
||||
static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
|
||||
@ -286,7 +272,7 @@ static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
|
||||
{ 1280, 854, 8,16} /* 0x22 */
|
||||
};
|
||||
|
||||
#if defined(SIS300) || defined(SIS315H)
|
||||
#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
|
||||
static const struct SiS_StandTable_S SiS_StandTable[]=
|
||||
{
|
||||
/* 0x00: MD_0_200 */
|
||||
@ -1521,10 +1507,6 @@ static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
|
||||
};
|
||||
|
||||
bool SiSInitPtr(struct SiS_Private *SiS_Pr);
|
||||
#ifdef SIS_XORG_XF86
|
||||
unsigned short SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
|
||||
int Depth, bool FSTN, int LCDwith, int LCDheight);
|
||||
#endif
|
||||
unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
|
||||
int VDisplay, int Depth, bool FSTN,
|
||||
unsigned short CustomT, int LCDwith, int LCDheight,
|
||||
@ -1550,17 +1532,11 @@ void SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR
|
||||
void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
|
||||
void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
|
||||
void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
|
||||
#ifndef SIS_LINUX_KERNEL
|
||||
void SiSSetLVDSetc(struct SiS_Private *SiS_Pr);
|
||||
#endif
|
||||
void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
|
||||
void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
|
||||
unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
|
||||
unsigned short ModeIdIndex);
|
||||
bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
|
||||
#ifndef SIS_LINUX_KERNEL
|
||||
void SiS_GetVBType(struct SiS_Private *SiS_Pr);
|
||||
#endif
|
||||
|
||||
bool SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
|
||||
unsigned short *ModeIdIndex);
|
||||
@ -1572,37 +1548,19 @@ unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short Mode
|
||||
unsigned short ModeIdIndex);
|
||||
unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
|
||||
unsigned short ModeIdIndex, unsigned short RRTI);
|
||||
#ifdef SIS300
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
|
||||
unsigned short *idx2);
|
||||
unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
|
||||
unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
|
||||
#endif
|
||||
void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
|
||||
#ifdef SIS_XORG_XF86
|
||||
bool SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
|
||||
bool dosetpitch);
|
||||
bool SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
|
||||
DisplayModePtr mode, bool IsCustom);
|
||||
bool SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
|
||||
DisplayModePtr mode, bool IsCustom);
|
||||
bool SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
|
||||
DisplayModePtr mode, bool IsCustom);
|
||||
#endif
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
|
||||
#endif
|
||||
void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
|
||||
void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
|
||||
unsigned short ModeIdIndex);
|
||||
#ifdef SIS_XORG_XF86
|
||||
void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
|
||||
int yres, DisplayModePtr current);
|
||||
#endif
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
|
||||
int yres, struct fb_var_screeninfo *var, bool writeres);
|
||||
#endif
|
||||
|
||||
/* From init301.c: */
|
||||
extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
|
||||
@ -1626,29 +1584,16 @@ extern unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short
|
||||
extern bool SiS_IsVAMode(struct SiS_Private *);
|
||||
extern bool SiS_IsDualEdge(struct SiS_Private *);
|
||||
|
||||
#ifdef SIS_XORG_XF86
|
||||
/* From other modules: */
|
||||
extern unsigned short SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
|
||||
unsigned int VBFlags);
|
||||
extern unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, unsigned short offset,
|
||||
unsigned char value);
|
||||
extern unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
|
||||
extern unsigned short SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
|
||||
unsigned int VBFlags);
|
||||
#endif
|
||||
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
#ifdef SIS300
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
|
||||
extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
|
||||
unsigned int val);
|
||||
#endif
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
|
||||
unsigned char val);
|
||||
extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,15 +53,8 @@
|
||||
#ifndef _INIT301_H_
|
||||
#define _INIT301_H_
|
||||
|
||||
#include "osdef.h"
|
||||
#include "initdef.h"
|
||||
|
||||
#ifdef SIS_XORG_XF86
|
||||
#include "sis.h"
|
||||
#include "sis_regs.h"
|
||||
#endif
|
||||
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
#include "vgatypes.h"
|
||||
#include "vstruct.h"
|
||||
#ifdef SIS_CP
|
||||
@ -72,7 +65,6 @@
|
||||
#include <linux/fb.h>
|
||||
#include "sis.h"
|
||||
#include <video/sisfb.h>
|
||||
#endif
|
||||
|
||||
static const unsigned char SiS_YPbPrTable[3][64] = {
|
||||
{
|
||||
@ -237,7 +229,7 @@ static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
|
||||
0xFF,0xFF,
|
||||
};
|
||||
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
/* 661 et al LCD data structure (2.03.00) */
|
||||
static const unsigned char SiS_LCDStruct661[] = {
|
||||
/* 1024x768 */
|
||||
@ -279,7 +271,7 @@ static const unsigned char SiS_LCDStruct661[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SIS300
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
static unsigned char SiS300_TrumpionData[14][80] = {
|
||||
{ 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
|
||||
0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
|
||||
@ -356,9 +348,6 @@ static unsigned char SiS300_TrumpionData[14][80] = {
|
||||
#endif
|
||||
|
||||
void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
|
||||
#ifndef SIS_LINUX_KERNEL
|
||||
void SiS_LockCRT2(struct SiS_Private *SiS_Pr);
|
||||
#endif
|
||||
void SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
|
||||
unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
|
||||
void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
|
||||
@ -375,9 +364,6 @@ unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo
|
||||
unsigned short RefreshRateTableIndex);
|
||||
unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
|
||||
void SiS_DisableBridge(struct SiS_Private *SiS_Pr);
|
||||
#ifndef SIS_LINUX_KERNEL
|
||||
void SiS_EnableBridge(struct SiS_Private *SiS_Pr);
|
||||
#endif
|
||||
bool SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
|
||||
void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
|
||||
void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
|
||||
@ -386,13 +372,9 @@ void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned cha
|
||||
unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
|
||||
void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
|
||||
unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
|
||||
#ifndef SIS_LINUX_KERNEL
|
||||
void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
|
||||
unsigned short SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempax);
|
||||
#endif
|
||||
void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
|
||||
unsigned char orval,unsigned short andval);
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
|
||||
static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
|
||||
static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
|
||||
@ -401,7 +383,7 @@ void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
|
||||
void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
|
||||
#endif /* 315 */
|
||||
|
||||
#ifdef SIS300
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
static bool SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
|
||||
void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
|
||||
#endif
|
||||
@ -412,21 +394,12 @@ unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, i
|
||||
unsigned short adaptnum, unsigned short DDCdatatype,
|
||||
unsigned char *buffer, unsigned int VBFlags2);
|
||||
|
||||
#ifdef SIS_XORG_XF86
|
||||
unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
|
||||
int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
|
||||
bool checkcr32, unsigned int VBFlags2);
|
||||
unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
|
||||
unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
|
||||
unsigned char *buffer);
|
||||
#else
|
||||
static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
|
||||
int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
|
||||
bool checkcr32, unsigned int VBFlags2);
|
||||
static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
|
||||
static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
|
||||
unsigned char *buffer);
|
||||
#endif
|
||||
static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
|
||||
static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr);
|
||||
static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr);
|
||||
@ -441,13 +414,13 @@ static unsigned short SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
|
||||
static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
|
||||
static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
|
||||
|
||||
#ifdef SIS300
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
|
||||
unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
|
||||
static void SetOEMLCDData2(struct SiS_Private *SiS_Pr,
|
||||
unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
|
||||
#endif
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
|
||||
unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
|
||||
static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
|
||||
@ -482,15 +455,13 @@ extern void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short M
|
||||
extern void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
|
||||
extern unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
|
||||
extern unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
|
||||
#ifdef SIS300
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
extern void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
|
||||
unsigned short *tempcl);
|
||||
extern unsigned short SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
|
||||
extern unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
|
||||
extern unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -25,7 +25,6 @@
|
||||
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
||||
*/
|
||||
|
||||
#include "osdef.h"
|
||||
#include "initdef.h"
|
||||
#include "vgatypes.h"
|
||||
#include "vstruct.h"
|
||||
@ -59,7 +58,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
|
||||
|
||||
if(rateindex > 0) rateindex--;
|
||||
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
switch(ModeNo) {
|
||||
case 0x5a: ModeNo = 0x50; break;
|
||||
case 0x5b: ModeNo = 0x56;
|
||||
@ -103,7 +102,7 @@ sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
|
||||
|
||||
if(rateindex > 0) rateindex--;
|
||||
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
switch(ModeNo) {
|
||||
case 0x5a: ModeNo = 0x50; break;
|
||||
case 0x5b: ModeNo = 0x56;
|
||||
@ -187,7 +186,7 @@ sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *ht
|
||||
|
||||
if(rateindex > 0) rateindex--;
|
||||
|
||||
#ifdef SIS315H
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
switch(ModeNo) {
|
||||
case 0x5a: ModeNo = 0x50; break;
|
||||
case 0x5b: ModeNo = 0x56;
|
||||
|
@ -1,133 +0,0 @@
|
||||
/* $XFree86$ */
|
||||
/* $XdotOrg$ */
|
||||
/*
|
||||
* OS depending defines
|
||||
*
|
||||
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
|
||||
*
|
||||
* If distributed as part of the Linux kernel, the following license terms
|
||||
* apply:
|
||||
*
|
||||
* * 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 named License,
|
||||
* * or any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Otherwise, the following license terms apply:
|
||||
*
|
||||
* * Redistribution and use in source and binary forms, with or without
|
||||
* * modification, are permitted provided that the following conditions
|
||||
* * are met:
|
||||
* * 1) Redistributions of source code must retain the above copyright
|
||||
* * notice, this list of conditions and the following disclaimer.
|
||||
* * 2) Redistributions in binary form must reproduce the above copyright
|
||||
* * notice, this list of conditions and the following disclaimer in the
|
||||
* * documentation and/or other materials provided with the distribution.
|
||||
* * 3) The name of the author may not be used to endorse or promote products
|
||||
* * derived from this software without specific prior written permission.
|
||||
* *
|
||||
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
||||
* Silicon Integrated Systems, Inc. (used by permission)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SIS_OSDEF_H_
|
||||
#define _SIS_OSDEF_H_
|
||||
|
||||
/* The choices are: */
|
||||
#define SIS_LINUX_KERNEL /* Linux kernel framebuffer */
|
||||
#undef SIS_XORG_XF86 /* XFree86/X.org */
|
||||
|
||||
#ifdef OutPortByte
|
||||
#undef OutPortByte
|
||||
#endif
|
||||
|
||||
#ifdef OutPortWord
|
||||
#undef OutPortWord
|
||||
#endif
|
||||
|
||||
#ifdef OutPortLong
|
||||
#undef OutPortLong
|
||||
#endif
|
||||
|
||||
#ifdef InPortByte
|
||||
#undef InPortByte
|
||||
#endif
|
||||
|
||||
#ifdef InPortWord
|
||||
#undef InPortWord
|
||||
#endif
|
||||
|
||||
#ifdef InPortLong
|
||||
#undef InPortLong
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
/* LINUX KERNEL */
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
|
||||
#ifdef CONFIG_FB_SIS_300
|
||||
#define SIS300
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB_SIS_315
|
||||
#define SIS315H
|
||||
#endif
|
||||
|
||||
#if !defined(SIS300) && !defined(SIS315H)
|
||||
#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
|
||||
#warning sisfb will not work!
|
||||
#endif
|
||||
|
||||
#define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
|
||||
#define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
|
||||
#define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
|
||||
#define InPortByte(p) inb((SISIOADDRESS)(p))
|
||||
#define InPortWord(p) inw((SISIOADDRESS)(p))
|
||||
#define InPortLong(p) inl((SISIOADDRESS)(p))
|
||||
#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
|
||||
|
||||
#endif /* LINUX_KERNEL */
|
||||
|
||||
/**********************************************************************/
|
||||
/* XFree86/X.org */
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef SIS_XORG_XF86
|
||||
|
||||
#define SIS300
|
||||
#define SIS315H
|
||||
|
||||
#define OutPortByte(p,v) outSISREG((IOADDRESS)(p),(CARD8)(v))
|
||||
#define OutPortWord(p,v) outSISREGW((IOADDRESS)(p),(CARD16)(v))
|
||||
#define OutPortLong(p,v) outSISREGL((IOADDRESS)(p),(CARD32)(v))
|
||||
#define InPortByte(p) inSISREG((IOADDRESS)(p))
|
||||
#define InPortWord(p) inSISREGW((IOADDRESS)(p))
|
||||
#define InPortLong(p) inSISREGL((IOADDRESS)(p))
|
||||
#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
|
||||
|
||||
#endif /* XF86 */
|
||||
|
||||
#endif /* _OSDEF_H_ */
|
@ -24,7 +24,6 @@
|
||||
#ifndef _SIS_H_
|
||||
#define _SIS_H_
|
||||
|
||||
#include "osdef.h"
|
||||
#include <video/sisfb.h>
|
||||
|
||||
#include "vgatypes.h"
|
||||
|
@ -60,6 +60,11 @@
|
||||
#include "sis.h"
|
||||
#include "sis_main.h"
|
||||
|
||||
#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
|
||||
#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
|
||||
#warning sisfb will not work!
|
||||
#endif
|
||||
|
||||
static void sisfb_handle_command(struct sis_video_info *ivideo,
|
||||
struct sisfb_cmd *sisfb_command);
|
||||
|
||||
@ -4114,14 +4119,6 @@ sisfb_find_rom(struct pci_dev *pdev)
|
||||
if(sisfb_check_rom(rom_base, ivideo)) {
|
||||
|
||||
if((myrombase = vmalloc(65536))) {
|
||||
|
||||
/* Work around bug in pci/rom.c: Folks forgot to check
|
||||
* whether the size retrieved from the BIOS image eventually
|
||||
* is larger than the mapped size
|
||||
*/
|
||||
if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
|
||||
romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
|
||||
|
||||
memcpy_fromio(myrombase, rom_base,
|
||||
(romsize > 65536) ? 65536 : romsize);
|
||||
}
|
||||
@ -4155,23 +4152,6 @@ sisfb_find_rom(struct pci_dev *pdev)
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
|
||||
pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
|
||||
(ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
|
||||
|
||||
rom_base = ioremap(ivideo->video_base, 65536);
|
||||
if(rom_base) {
|
||||
if(sisfb_check_rom(rom_base, ivideo)) {
|
||||
if((myrombase = vmalloc(65536)))
|
||||
memcpy_fromio(myrombase, rom_base, 65536);
|
||||
}
|
||||
iounmap(rom_base);
|
||||
}
|
||||
|
||||
pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
|
||||
|
||||
#endif
|
||||
|
||||
return myrombase;
|
||||
|
@ -55,21 +55,10 @@
|
||||
|
||||
#define SISIOMEMTYPE
|
||||
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
typedef unsigned long SISIOADDRESS;
|
||||
#include <linux/types.h> /* Need __iomem */
|
||||
#undef SISIOMEMTYPE
|
||||
#define SISIOMEMTYPE __iomem
|
||||
#endif
|
||||
|
||||
#ifdef SIS_XORG_XF86
|
||||
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
|
||||
typedef unsigned long IOADDRESS;
|
||||
typedef unsigned long SISIOADDRESS;
|
||||
#else
|
||||
typedef IOADDRESS SISIOADDRESS;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum _SIS_CHIP_TYPE {
|
||||
SIS_VGALegacy = 0,
|
||||
|
@ -233,24 +233,15 @@ struct SiS_Private
|
||||
{
|
||||
unsigned char ChipType;
|
||||
unsigned char ChipRevision;
|
||||
#ifdef SIS_XORG_XF86
|
||||
PCITAG PciTag;
|
||||
#endif
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
void *ivideo;
|
||||
#endif
|
||||
unsigned char *VirtualRomBase;
|
||||
bool UseROM;
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
unsigned char SISIOMEMTYPE *VideoMemoryAddress;
|
||||
unsigned int VideoMemorySize;
|
||||
#endif
|
||||
SISIOADDRESS IOAddress;
|
||||
SISIOADDRESS IOAddress2; /* For dual chip XGI volari */
|
||||
|
||||
#ifdef SIS_LINUX_KERNEL
|
||||
SISIOADDRESS RelIO;
|
||||
#endif
|
||||
SISIOADDRESS SiS_P3c4;
|
||||
SISIOADDRESS SiS_P3d4;
|
||||
SISIOADDRESS SiS_P3c0;
|
||||
@ -280,9 +271,6 @@ struct SiS_Private
|
||||
unsigned short SiS_IF_DEF_FSTN;
|
||||
unsigned short SiS_SysFlags;
|
||||
unsigned char SiS_VGAINFO;
|
||||
#ifdef SIS_XORG_XF86
|
||||
unsigned short SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
|
||||
#endif
|
||||
bool SiS_UseROM;
|
||||
bool SiS_ROMNew;
|
||||
bool SiS_XGIROM;
|
||||
|
@ -9,19 +9,19 @@ static ssize_t device_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
return sprintf(buf, "%hu", dev->id.device);
|
||||
return sprintf(buf, "0x%04x\n", dev->id.device);
|
||||
}
|
||||
static ssize_t vendor_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
return sprintf(buf, "%hu", dev->id.vendor);
|
||||
return sprintf(buf, "0x%04x\n", dev->id.vendor);
|
||||
}
|
||||
static ssize_t status_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
||||
return sprintf(buf, "0x%08x", dev->config->get_status(dev));
|
||||
return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
|
||||
}
|
||||
static ssize_t modalias_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -230,9 +230,6 @@ add_head:
|
||||
pr_debug("Added buffer head %i to %p\n", head, vq);
|
||||
END_USE(vq);
|
||||
|
||||
/* If we're indirect, we can fit many (assuming not OOM). */
|
||||
if (vq->indirect)
|
||||
return vq->num_free ? vq->vring.num : 0;
|
||||
return vq->num_free;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(virtqueue_add_buf_gfp);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user