Merge branches 'sh/ftrace' and 'sh/cachetlb'
This commit is contained in:
commit
7119888df1
|
@ -10,6 +10,7 @@ config SUPERH
|
|||
select EMBEDDED
|
||||
select HAVE_CLK
|
||||
select HAVE_IDE
|
||||
select HAVE_LMB
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_IOREMAP_PROT if MMU
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/smc91x.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb/r8a66597.h>
|
||||
#include <video/sh_mobile_lcdc.h>
|
||||
#include <media/sh_mobile_ceu.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -302,6 +303,34 @@ static struct platform_device sh_eth_device = {
|
|||
.resource = sh_eth_resources,
|
||||
};
|
||||
|
||||
static struct r8a66597_platdata sh7724_usb0_host_data = {
|
||||
};
|
||||
|
||||
static struct resource sh7724_usb0_host_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xa4d80000,
|
||||
.end = 0xa4d800ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 65,
|
||||
.end = 65,
|
||||
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sh7724_usb0_host_device = {
|
||||
.name = "r8a66597_hcd",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = NULL, /* not use dma */
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &sh7724_usb0_host_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sh7724_usb0_host_resources),
|
||||
.resource = sh7724_usb0_host_resources,
|
||||
};
|
||||
|
||||
static struct platform_device *ms7724se_devices[] __initdata = {
|
||||
&heartbeat_device,
|
||||
&smc91x_eth_device,
|
||||
|
@ -311,6 +340,7 @@ static struct platform_device *ms7724se_devices[] __initdata = {
|
|||
&ceu1_device,
|
||||
&keysc_device,
|
||||
&sh_eth_device,
|
||||
&sh7724_usb0_host_device,
|
||||
};
|
||||
|
||||
#define EEPROM_OP 0xBA206000
|
||||
|
@ -364,6 +394,7 @@ static void __init sh_eth_init(void)
|
|||
#define SW4140 0xBA201000
|
||||
#define FPGA_OUT 0xBA200400
|
||||
#define PORT_HIZA 0xA4050158
|
||||
#define PORT_MSELCRB 0xA4050182
|
||||
|
||||
#define SW41_A 0x0100
|
||||
#define SW41_B 0x0200
|
||||
|
@ -373,6 +404,7 @@ static void __init sh_eth_init(void)
|
|||
#define SW41_F 0x2000
|
||||
#define SW41_G 0x4000
|
||||
#define SW41_H 0x8000
|
||||
|
||||
static int __init devices_setup(void)
|
||||
{
|
||||
u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
|
||||
|
@ -385,6 +417,12 @@ static int __init devices_setup(void)
|
|||
(1 << 14)), /* RMII */
|
||||
FPGA_OUT);
|
||||
|
||||
/* turn on USB clocks, use external clock */
|
||||
ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
|
||||
|
||||
/* enable USB0 port */
|
||||
ctrl_outw(0x0600, 0xa40501d4);
|
||||
|
||||
/* enable IRQ 0,1,2 */
|
||||
gpio_request(GPIO_FN_INTC_IRQ0, NULL);
|
||||
gpio_request(GPIO_FN_INTC_IRQ1, NULL);
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef __ASM_SH_HWBLK_H
|
||||
#define __ASM_SH_HWBLK_H
|
||||
|
||||
#include <asm/clock.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */
|
||||
|
||||
#define HWBLK_AREA(_flags, _parent) \
|
||||
{ \
|
||||
.flags = _flags, \
|
||||
.parent = _parent, \
|
||||
}
|
||||
|
||||
struct hwblk_area {
|
||||
unsigned long cnt;
|
||||
unsigned char parent;
|
||||
unsigned char flags;
|
||||
};
|
||||
|
||||
#define HWBLK(_mstp, _bit, _area) \
|
||||
{ \
|
||||
.mstp = (void __iomem *)_mstp, \
|
||||
.bit = _bit, \
|
||||
.area = _area, \
|
||||
}
|
||||
|
||||
struct hwblk {
|
||||
void __iomem *mstp;
|
||||
unsigned char bit;
|
||||
unsigned char area;
|
||||
unsigned long cnt;
|
||||
};
|
||||
|
||||
struct hwblk_info {
|
||||
struct hwblk_area *areas;
|
||||
int nr_areas;
|
||||
struct hwblk *hwblks;
|
||||
int nr_hwblks;
|
||||
};
|
||||
|
||||
/* Should be defined by processor-specific code */
|
||||
int arch_hwblk_init(void);
|
||||
int arch_hwblk_sleep_mode(void);
|
||||
|
||||
int hwblk_register(struct hwblk_info *info);
|
||||
int hwblk_init(void);
|
||||
|
||||
/* allow clocks to enable and disable hardware blocks */
|
||||
#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.id = _id, \
|
||||
.parent = _parent, \
|
||||
.arch_flags = _hwblk, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
int sh_hwblk_clk_register(struct clk *clks, int nr);
|
||||
|
||||
#endif /* __ASM_SH_HWBLK_H */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __ASM_SH_LMB_H
|
||||
#define __ASM_SH_LMB_H
|
||||
|
||||
#define LMB_REAL_LIMIT 0
|
||||
|
||||
#endif /* __ASM_SH_LMB_H */
|
|
@ -4,4 +4,6 @@
|
|||
/* SH only supports software counters through this interface. */
|
||||
static inline void set_perf_counter_pending(void) {}
|
||||
|
||||
#define PERF_COUNTER_INDEX_OFFSET 0
|
||||
|
||||
#endif /* __ASM_SH_PERF_COUNTER_H */
|
||||
|
|
|
@ -10,6 +10,15 @@ struct swsusp_arch_regs {
|
|||
struct pt_regs user_regs;
|
||||
unsigned long bank1_regs[8];
|
||||
};
|
||||
|
||||
void sh_mobile_call_standby(unsigned long mode);
|
||||
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
void sh_mobile_setup_cpuidle(void);
|
||||
#else
|
||||
static inline void sh_mobile_setup_cpuidle(void) {}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* flags passed to assembly suspend code */
|
||||
|
|
|
@ -221,4 +221,18 @@ enum {
|
|||
GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
|
||||
};
|
||||
|
||||
enum {
|
||||
HWBLK_UNKNOWN = 0,
|
||||
HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_URAM, HWBLK_XYMEM,
|
||||
HWBLK_INTC, HWBLK_DMAC, HWBLK_SHYWAY, HWBLK_HUDI,
|
||||
HWBLK_UBC, HWBLK_TMU, HWBLK_CMT, HWBLK_RWDT, HWBLK_FLCTL,
|
||||
HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SIO,
|
||||
HWBLK_SIOF0, HWBLK_SIOF1, HWBLK_IIC, HWBLK_RTC,
|
||||
HWBLK_TPU, HWBLK_IRDA, HWBLK_SDHI, HWBLK_SIM, HWBLK_KEYSC,
|
||||
HWBLK_TSIF, HWBLK_USBF, HWBLK_2DG, HWBLK_SIU, HWBLK_VOU,
|
||||
HWBLK_JPU, HWBLK_BEU, HWBLK_CEU, HWBLK_VEU, HWBLK_VPU,
|
||||
HWBLK_LCDC,
|
||||
HWBLK_NR,
|
||||
};
|
||||
|
||||
#endif /* __ASM_SH7722_H__ */
|
||||
|
|
|
@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP) += ubc.o
|
|||
obj-$(CONFIG_SH_ADC) += adc.o
|
||||
obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
|
||||
|
||||
obj-y += irq/ init.o clock.o
|
||||
obj-y += irq/ init.o clock.o hwblk.o
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/hwblk.h>
|
||||
#include <asm/clock.h>
|
||||
|
||||
static DEFINE_SPINLOCK(hwblk_lock);
|
||||
|
||||
static void hwblk_area_inc(struct hwblk_info *info, int area)
|
||||
{
|
||||
struct hwblk_area *hap = info->areas + area;
|
||||
|
||||
hap->cnt++;
|
||||
if (hap->cnt == 1)
|
||||
if (hap->flags & HWBLK_AREA_FLAG_PARENT)
|
||||
hwblk_area_inc(info, hap->parent);
|
||||
}
|
||||
|
||||
static void hwblk_area_dec(struct hwblk_info *info, int area)
|
||||
{
|
||||
struct hwblk_area *hap = info->areas + area;
|
||||
|
||||
if (hap->cnt == 1)
|
||||
if (hap->flags & HWBLK_AREA_FLAG_PARENT)
|
||||
hwblk_area_dec(info, hap->parent);
|
||||
hap->cnt--;
|
||||
}
|
||||
|
||||
static void hwblk_enable(struct hwblk_info *info, int hwblk)
|
||||
{
|
||||
struct hwblk *hp = info->hwblks + hwblk;
|
||||
unsigned long tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hwblk_lock, flags);
|
||||
|
||||
hp->cnt++;
|
||||
if (hp->cnt == 1) {
|
||||
hwblk_area_inc(info, hp->area);
|
||||
|
||||
tmp = __raw_readl(hp->mstp);
|
||||
tmp &= ~(1 << hp->bit);
|
||||
__raw_writel(tmp, hp->mstp);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&hwblk_lock, flags);
|
||||
}
|
||||
|
||||
static void hwblk_disable(struct hwblk_info *info, int hwblk)
|
||||
{
|
||||
struct hwblk *hp = info->hwblks + hwblk;
|
||||
unsigned long tmp;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hwblk_lock, flags);
|
||||
|
||||
if (hp->cnt == 1) {
|
||||
hwblk_area_dec(info, hp->area);
|
||||
|
||||
tmp = __raw_readl(hp->mstp);
|
||||
tmp |= 1 << hp->bit;
|
||||
__raw_writel(tmp, hp->mstp);
|
||||
}
|
||||
hp->cnt--;
|
||||
|
||||
spin_unlock_irqrestore(&hwblk_lock, flags);
|
||||
}
|
||||
|
||||
static struct hwblk_info *hwblk_info;
|
||||
|
||||
int __init hwblk_register(struct hwblk_info *info)
|
||||
{
|
||||
hwblk_info = info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init __weak arch_hwblk_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __weak arch_hwblk_sleep_mode(void)
|
||||
{
|
||||
return SUSP_SH_SLEEP;
|
||||
}
|
||||
|
||||
int __init hwblk_init(void)
|
||||
{
|
||||
return arch_hwblk_init();
|
||||
}
|
||||
|
||||
/* allow clocks to enable and disable hardware blocks */
|
||||
static int sh_hwblk_clk_enable(struct clk *clk)
|
||||
{
|
||||
if (!hwblk_info)
|
||||
return -ENOENT;
|
||||
|
||||
hwblk_enable(hwblk_info, clk->arch_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_hwblk_clk_disable(struct clk *clk)
|
||||
{
|
||||
if (hwblk_info)
|
||||
hwblk_disable(hwblk_info, clk->arch_flags);
|
||||
}
|
||||
|
||||
static struct clk_ops sh_hwblk_clk_ops = {
|
||||
.enable = sh_hwblk_clk_enable,
|
||||
.disable = sh_hwblk_clk_disable,
|
||||
.recalc = followparent_recalc,
|
||||
};
|
||||
|
||||
int __init sh_hwblk_clk_register(struct clk *clks, int nr)
|
||||
{
|
||||
struct clk *clkp;
|
||||
int ret = 0;
|
||||
int k;
|
||||
|
||||
for (k = 0; !ret && (k < nr); k++) {
|
||||
clkp = clks + k;
|
||||
clkp->ops = &sh_hwblk_clk_ops;
|
||||
ret |= clk_register(clkp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -25,7 +25,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
|
|||
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
|
||||
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/hwblk.h>
|
||||
#include <cpu/sh7722.h>
|
||||
|
||||
/* SH7722 registers */
|
||||
#define FRQCR 0xa4150000
|
||||
|
@ -140,35 +142,37 @@ struct clk div6_clks[] = {
|
|||
SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
|
||||
};
|
||||
|
||||
#define MSTP(_str, _parent, _reg, _bit, _flags) \
|
||||
SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
|
||||
#define R_CLK &r_clk
|
||||
#define P_CLK &div4_clks[DIV4_P]
|
||||
#define B_CLK &div4_clks[DIV4_B]
|
||||
#define U_CLK &div4_clks[DIV4_U]
|
||||
|
||||
static struct clk mstp_clks[] = {
|
||||
MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
|
||||
MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
|
||||
MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
||||
MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
|
||||
MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
|
||||
MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
||||
MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
|
||||
MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
|
||||
MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
||||
SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
|
||||
SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
|
||||
SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
|
||||
SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
|
||||
SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
|
||||
SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
|
||||
SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
|
||||
SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
|
||||
SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
|
||||
|
||||
MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
|
||||
MSTP("rtc0", &r_clk, MSTPCR1, 8, 0),
|
||||
SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
|
||||
SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
|
||||
|
||||
MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
|
||||
MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
|
||||
MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
|
||||
MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
|
||||
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
|
||||
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
|
||||
MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
|
||||
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
|
||||
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
|
||||
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
|
||||
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
|
||||
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
|
||||
SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
|
||||
SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
|
||||
SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
|
||||
SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
|
||||
SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
|
||||
SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
|
||||
SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
|
||||
SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
|
||||
SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
|
||||
SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT),
|
||||
SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
|
||||
SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
|
@ -191,7 +195,7 @@ int __init arch_clk_init(void)
|
|||
ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
|
||||
|
||||
if (!ret)
|
||||
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
|
||||
ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
|
||||
*
|
||||
* SH7722 hardware block support
|
||||
*
|
||||
* Copyright (C) 2009 Magnus Damm
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/hwblk.h>
|
||||
#include <cpu/sh7722.h>
|
||||
|
||||
/* SH7722 registers */
|
||||
#define MSTPCR0 0xa4150030
|
||||
#define MSTPCR1 0xa4150034
|
||||
#define MSTPCR2 0xa4150038
|
||||
|
||||
/* SH7722 Power Domains */
|
||||
enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
|
||||
static struct hwblk_area sh7722_hwblk_area[] = {
|
||||
[CORE_AREA] = HWBLK_AREA(0, 0),
|
||||
[CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
|
||||
[SUB_AREA] = HWBLK_AREA(0, 0),
|
||||
};
|
||||
|
||||
/* Table mapping HWBLK to Module Stop Bit and Power Domain */
|
||||
static struct hwblk sh7722_hwblk[HWBLK_NR] = {
|
||||
[HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
|
||||
[HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
|
||||
[HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
|
||||
[HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA),
|
||||
[HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA),
|
||||
[HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
|
||||
[HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
|
||||
[HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
|
||||
[HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
|
||||
[HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
|
||||
[HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA),
|
||||
[HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
|
||||
[HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
|
||||
[HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
|
||||
[HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA),
|
||||
[HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA),
|
||||
[HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA),
|
||||
[HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA),
|
||||
[HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
|
||||
[HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
|
||||
|
||||
[HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
|
||||
[HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
|
||||
|
||||
[HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
|
||||
[HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
|
||||
[HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA),
|
||||
[HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA),
|
||||
[HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
|
||||
[HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA),
|
||||
[HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA),
|
||||
[HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
|
||||
[HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
|
||||
[HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
|
||||
[HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
|
||||
[HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
|
||||
[HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
|
||||
[HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
|
||||
[HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
|
||||
[HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
|
||||
};
|
||||
|
||||
static struct hwblk_info sh7722_hwblk_info = {
|
||||
.areas = sh7722_hwblk_area,
|
||||
.nr_areas = ARRAY_SIZE(sh7722_hwblk_area),
|
||||
.hwblks = sh7722_hwblk,
|
||||
.nr_hwblks = ARRAY_SIZE(sh7722_hwblk),
|
||||
};
|
||||
|
||||
int arch_hwblk_sleep_mode(void)
|
||||
{
|
||||
if (!sh7722_hwblk_area[CORE_AREA].cnt)
|
||||
return SUSP_SH_STANDBY | SUSP_SH_SF;
|
||||
|
||||
if (!sh7722_hwblk_area[CORE_AREA_BM].cnt)
|
||||
return SUSP_SH_SLEEP | SUSP_SH_SF;
|
||||
|
||||
return SUSP_SH_SLEEP;
|
||||
}
|
||||
|
||||
int __init arch_hwblk_init(void)
|
||||
{
|
||||
return hwblk_register(&sh7722_hwblk_info);
|
||||
}
|
|
@ -4,3 +4,4 @@
|
|||
|
||||
# Power Management & Sleep mode
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o
|
||||
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/shmobile/cpuidle.c
|
||||
*
|
||||
* Cpuidle support code for SuperH Mobile
|
||||
*
|
||||
* Copyright (C) 2009 Magnus Damm
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/hwblk.h>
|
||||
|
||||
static unsigned long cpuidle_mode[] = {
|
||||
SUSP_SH_SLEEP, /* regular sleep mode */
|
||||
SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
|
||||
};
|
||||
|
||||
static int cpuidle_sleep_enter(struct cpuidle_device *dev,
|
||||
struct cpuidle_state *state)
|
||||
{
|
||||
unsigned long allowed_mode = arch_hwblk_sleep_mode();
|
||||
ktime_t before, after;
|
||||
int requested_state = state - &dev->states[0];
|
||||
int allowed_state;
|
||||
int k;
|
||||
|
||||
/* convert allowed mode to allowed state */
|
||||
for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
|
||||
if (cpuidle_mode[k] == allowed_mode)
|
||||
break;
|
||||
|
||||
allowed_state = k;
|
||||
|
||||
/* take the following into account for sleep mode selection:
|
||||
* - allowed_state: best mode allowed by hardware (clock deps)
|
||||
* - requested_state: best mode allowed by software (latencies)
|
||||
*/
|
||||
k = min_t(int, allowed_state, requested_state);
|
||||
|
||||
dev->last_state = &dev->states[k];
|
||||
before = ktime_get();
|
||||
sh_mobile_call_standby(cpuidle_mode[k]);
|
||||
after = ktime_get();
|
||||
return ktime_to_ns(ktime_sub(after, before)) >> 10;
|
||||
}
|
||||
|
||||
static struct cpuidle_device cpuidle_dev;
|
||||
static struct cpuidle_driver cpuidle_driver = {
|
||||
.name = "sh_idle",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
void sh_mobile_setup_cpuidle(void)
|
||||
{
|
||||
struct cpuidle_device *dev = &cpuidle_dev;
|
||||
struct cpuidle_state *state;
|
||||
int i;
|
||||
|
||||
cpuidle_register_driver(&cpuidle_driver);
|
||||
|
||||
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
|
||||
dev->states[i].name[0] = '\0';
|
||||
dev->states[i].desc[0] = '\0';
|
||||
}
|
||||
|
||||
i = CPUIDLE_DRIVER_STATE_START;
|
||||
|
||||
state = &dev->states[i++];
|
||||
snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
|
||||
strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
|
||||
state->exit_latency = 1;
|
||||
state->target_residency = 1 * 2;
|
||||
state->power_usage = 3;
|
||||
state->flags = 0;
|
||||
state->flags |= CPUIDLE_FLAG_SHALLOW;
|
||||
state->flags |= CPUIDLE_FLAG_TIME_VALID;
|
||||
state->enter = cpuidle_sleep_enter;
|
||||
|
||||
dev->safe_state = state;
|
||||
|
||||
state = &dev->states[i++];
|
||||
snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
|
||||
strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN);
|
||||
state->exit_latency = 100;
|
||||
state->target_residency = 1 * 2;
|
||||
state->power_usage = 1;
|
||||
state->flags = 0;
|
||||
state->flags |= CPUIDLE_FLAG_TIME_VALID;
|
||||
state->enter = cpuidle_sleep_enter;
|
||||
|
||||
dev->state_count = i;
|
||||
|
||||
cpuidle_register_device(dev);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c
|
||||
* arch/sh/kernel/cpu/shmobile/pm.c
|
||||
*
|
||||
* Power management support code for SuperH Mobile
|
||||
*
|
||||
|
@ -32,20 +32,17 @@
|
|||
*
|
||||
* R-standby mode is unsupported, but will be added in the future
|
||||
* U-standby mode is low priority since it needs bootloader hacks
|
||||
*
|
||||
* All modes should be tied in with cpuidle. But before that can
|
||||
* happen we need to keep track of enabled hardware blocks so we
|
||||
* can avoid entering sleep modes that stop clocks to hardware
|
||||
* blocks that are in use even though the cpu core is idle.
|
||||
*/
|
||||
|
||||
#define ILRAM_BASE 0xe5200000
|
||||
|
||||
extern const unsigned char sh_mobile_standby[];
|
||||
extern const unsigned int sh_mobile_standby_size;
|
||||
|
||||
static void sh_mobile_call_standby(unsigned long mode)
|
||||
void sh_mobile_call_standby(unsigned long mode)
|
||||
{
|
||||
extern void *vbr_base;
|
||||
void *onchip_mem = (void *)0xe5200000; /* ILRAM */
|
||||
void *onchip_mem = (void *)ILRAM_BASE;
|
||||
void (*standby_onchip_mem)(unsigned long) = onchip_mem;
|
||||
|
||||
/* Note: Wake up from sleep may generate exceptions!
|
||||
|
@ -55,11 +52,6 @@ static void sh_mobile_call_standby(unsigned long mode)
|
|||
if (mode & SUSP_SH_SF)
|
||||
asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
|
||||
|
||||
/* Copy the assembly snippet to the otherwise ununsed ILRAM */
|
||||
memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
|
||||
wmb();
|
||||
ctrl_barrier();
|
||||
|
||||
/* Let assembly snippet in on-chip memory handle the rest */
|
||||
standby_onchip_mem(mode);
|
||||
|
||||
|
@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = {
|
|||
|
||||
static int __init sh_pm_init(void)
|
||||
{
|
||||
void *onchip_mem = (void *)ILRAM_BASE;
|
||||
|
||||
/* Copy the assembly snippet to the otherwise ununsed ILRAM */
|
||||
memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
|
||||
wmb();
|
||||
ctrl_barrier();
|
||||
|
||||
suspend_set_ops(&sh_pm_ops);
|
||||
sh_mobile_setup_cpuidle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/lmb.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -233,39 +234,45 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
|
|||
void __init setup_bootmem_allocator(unsigned long free_pfn)
|
||||
{
|
||||
unsigned long bootmap_size;
|
||||
unsigned long bootmap_pages, bootmem_paddr;
|
||||
u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT;
|
||||
int i;
|
||||
|
||||
bootmap_pages = bootmem_bootmap_pages(total_pages);
|
||||
|
||||
bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Find a proper area for the bootmem bitmap. After this
|
||||
* bootstrap step all allocations (until the page allocator
|
||||
* is intact) must be done via bootmem_alloc().
|
||||
*/
|
||||
bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
|
||||
bootmap_size = init_bootmem_node(NODE_DATA(0),
|
||||
bootmem_paddr >> PAGE_SHIFT,
|
||||
min_low_pfn, max_low_pfn);
|
||||
|
||||
__add_active_range(0, min_low_pfn, max_low_pfn);
|
||||
/* Add active regions with valid PFNs. */
|
||||
for (i = 0; i < lmb.memory.cnt; i++) {
|
||||
unsigned long start_pfn, end_pfn;
|
||||
start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
|
||||
end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
|
||||
__add_active_range(0, start_pfn, end_pfn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add all physical memory to the bootmem map and mark each
|
||||
* area as present.
|
||||
*/
|
||||
register_bootmem_low_pages();
|
||||
|
||||
node_set_online(0);
|
||||
|
||||
/*
|
||||
* Reserve the kernel text and
|
||||
* Reserve the bootmem bitmap. We do this in two steps (first step
|
||||
* was init_bootmem()), because this catches the (definitely buggy)
|
||||
* case of us accidentally initializing the bootmem allocator with
|
||||
* an invalid RAM area.
|
||||
*/
|
||||
reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
|
||||
(PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) -
|
||||
(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET),
|
||||
BOOTMEM_DEFAULT);
|
||||
|
||||
/*
|
||||
* Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
|
||||
*/
|
||||
if (CONFIG_ZERO_PAGE_OFFSET != 0)
|
||||
reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
|
||||
/* Reserve the sections we're already using. */
|
||||
for (i = 0; i < lmb.reserved.cnt; i++)
|
||||
reserve_bootmem(lmb.reserved.region[i].base,
|
||||
lmb_size_bytes(&lmb.reserved, i),
|
||||
BOOTMEM_DEFAULT);
|
||||
|
||||
node_set_online(0);
|
||||
|
||||
sparse_memory_present_with_active_regions(0);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
|
@ -296,12 +303,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
|
|||
static void __init setup_memory(void)
|
||||
{
|
||||
unsigned long start_pfn;
|
||||
u64 base = min_low_pfn << PAGE_SHIFT;
|
||||
u64 size = (max_low_pfn << PAGE_SHIFT) - base;
|
||||
|
||||
/*
|
||||
* Partially used pages are not usable - thus
|
||||
* we are rounding upwards:
|
||||
*/
|
||||
start_pfn = PFN_UP(__pa(_end));
|
||||
|
||||
lmb_add(base, size);
|
||||
|
||||
/*
|
||||
* Reserve the kernel text and
|
||||
* Reserve the bootmem bitmap. We do this in two steps (first step
|
||||
* was init_bootmem()), because this catches the (definitely buggy)
|
||||
* case of us accidentally initializing the bootmem allocator with
|
||||
* an invalid RAM area.
|
||||
*/
|
||||
lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
|
||||
(PFN_PHYS(start_pfn) + PAGE_SIZE - 1) -
|
||||
(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
|
||||
|
||||
/*
|
||||
* Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
|
||||
*/
|
||||
if (CONFIG_ZERO_PAGE_OFFSET != 0)
|
||||
lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
|
||||
|
||||
lmb_analyze();
|
||||
lmb_dump_all();
|
||||
|
||||
setup_bootmem_allocator(start_pfn);
|
||||
}
|
||||
#else
|
||||
|
@ -402,6 +434,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
nodes_clear(node_online_map);
|
||||
|
||||
/* Setup bootmem with available RAM */
|
||||
lmb_init();
|
||||
setup_memory();
|
||||
sparse_init();
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/smp.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <asm/clock.h>
|
||||
#include <asm/hwblk.h>
|
||||
#include <asm/rtc.h>
|
||||
|
||||
/* Dummy RTC ops */
|
||||
|
@ -96,6 +97,7 @@ void __init time_init(void)
|
|||
if (board_time_init)
|
||||
board_time_init();
|
||||
|
||||
hwblk_init();
|
||||
clk_init();
|
||||
|
||||
rtc_sh_get_time(&xtime);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Page fault handler for SH with an MMU.
|
||||
*
|
||||
* Copyright (C) 1999 Niibe Yutaka
|
||||
* Copyright (C) 2003 - 2008 Paul Mundt
|
||||
* Copyright (C) 2003 - 2009 Paul Mundt
|
||||
*
|
||||
* Based on linux/arch/i386/mm/fault.c:
|
||||
* Copyright (C) 1995 Linus Torvalds
|
||||
|
@ -25,18 +25,84 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
if (!user_mode(regs)) {
|
||||
if (kprobes_built_in() && !user_mode(regs)) {
|
||||
preempt_disable();
|
||||
if (kprobe_running() && kprobe_fault_handler(regs, trap))
|
||||
ret = 1;
|
||||
preempt_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
|
||||
{
|
||||
unsigned index = pgd_index(address);
|
||||
pgd_t *pgd_k;
|
||||
pud_t *pud, *pud_k;
|
||||
pmd_t *pmd, *pmd_k;
|
||||
|
||||
pgd += index;
|
||||
pgd_k = init_mm.pgd + index;
|
||||
|
||||
if (!pgd_present(*pgd_k))
|
||||
return NULL;
|
||||
|
||||
pud = pud_offset(pgd, address);
|
||||
pud_k = pud_offset(pgd_k, address);
|
||||
if (!pud_present(*pud_k))
|
||||
return NULL;
|
||||
|
||||
pmd = pmd_offset(pud, address);
|
||||
pmd_k = pmd_offset(pud_k, address);
|
||||
if (!pmd_present(*pmd_k))
|
||||
return NULL;
|
||||
|
||||
if (!pmd_present(*pmd))
|
||||
set_pmd(pmd, *pmd_k);
|
||||
else
|
||||
BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
|
||||
|
||||
return pmd_k;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a fault on the vmalloc or module mapping area
|
||||
*/
|
||||
static noinline int vmalloc_fault(unsigned long address)
|
||||
{
|
||||
pgd_t *pgd_k;
|
||||
pmd_t *pmd_k;
|
||||
pte_t *pte_k;
|
||||
|
||||
/* Make sure we are in vmalloc area: */
|
||||
if (!(address >= VMALLOC_START && address < VMALLOC_END))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Synchronize this task's top level page-table
|
||||
* with the 'reference' page table.
|
||||
*
|
||||
* Do _not_ use "current" here. We might be inside
|
||||
* an interrupt in the middle of a task switch..
|
||||
*/
|
||||
pgd_k = get_TTB();
|
||||
pmd_k = vmalloc_sync_one(__va((unsigned long)pgd_k), address);
|
||||
if (!pmd_k)
|
||||
return -1;
|
||||
|
||||
pte_k = pte_offset_kernel(pmd_k, address);
|
||||
if (!pte_present(*pte_k))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fault_in_kernel_space(unsigned long address)
|
||||
{
|
||||
return address >= TASK_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine handles page faults. It determines the address,
|
||||
* and the problem, and then passes it off to one of the appropriate
|
||||
|
@ -46,6 +112,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
unsigned long writeaccess,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long vec;
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct * vma;
|
||||
|
@ -53,59 +120,30 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
int fault;
|
||||
siginfo_t info;
|
||||
|
||||
/*
|
||||
* We don't bother with any notifier callbacks here, as they are
|
||||
* all handled through the __do_page_fault() fast-path.
|
||||
*/
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
si_code = SEGV_MAPERR;
|
||||
vec = lookup_exception_vector();
|
||||
|
||||
if (unlikely(address >= TASK_SIZE)) {
|
||||
/*
|
||||
* Synchronize this task's top level page-table
|
||||
* with the 'reference' page table.
|
||||
*
|
||||
* Do _not_ use "tsk" here. We might be inside
|
||||
* an interrupt in the middle of a task switch..
|
||||
*/
|
||||
int offset = pgd_index(address);
|
||||
pgd_t *pgd, *pgd_k;
|
||||
pud_t *pud, *pud_k;
|
||||
pmd_t *pmd, *pmd_k;
|
||||
|
||||
pgd = get_TTB() + offset;
|
||||
pgd_k = swapper_pg_dir + offset;
|
||||
|
||||
if (!pgd_present(*pgd)) {
|
||||
if (!pgd_present(*pgd_k))
|
||||
goto bad_area_nosemaphore;
|
||||
set_pgd(pgd, *pgd_k);
|
||||
/*
|
||||
* We fault-in kernel-space virtual memory on-demand. The
|
||||
* 'reference' page table is init_mm.pgd.
|
||||
*
|
||||
* NOTE! We MUST NOT take any locks for this case. We may
|
||||
* be in an interrupt or a critical region, and should
|
||||
* only copy the information from the master page table,
|
||||
* nothing more.
|
||||
*/
|
||||
if (unlikely(fault_in_kernel_space(address))) {
|
||||
if (vmalloc_fault(address) >= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
pud = pud_offset(pgd, address);
|
||||
pud_k = pud_offset(pgd_k, address);
|
||||
|
||||
if (!pud_present(*pud)) {
|
||||
if (!pud_present(*pud_k))
|
||||
goto bad_area_nosemaphore;
|
||||
set_pud(pud, *pud_k);
|
||||
if (notify_page_fault(regs, vec))
|
||||
return;
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, address);
|
||||
pmd_k = pmd_offset(pud_k, address);
|
||||
if (pmd_present(*pmd) || !pmd_present(*pmd_k))
|
||||
goto bad_area_nosemaphore;
|
||||
set_pmd(pmd, *pmd_k);
|
||||
|
||||
return;
|
||||
goto bad_area_nosemaphore;
|
||||
}
|
||||
|
||||
mm = tsk->mm;
|
||||
|
||||
if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
|
||||
if (unlikely(notify_page_fault(regs, vec)))
|
||||
return;
|
||||
|
||||
/* Only enable interrupts if they were on before the fault */
|
||||
|
@ -115,8 +153,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
|
||||
|
||||
/*
|
||||
* If we're in an interrupt or have no user
|
||||
* context, we must not take the fault..
|
||||
* If we're in an interrupt, have no user context or are running
|
||||
* in an atomic region then we must not take the fault:
|
||||
*/
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
@ -132,10 +170,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||
goto bad_area;
|
||||
if (expand_stack(vma, address))
|
||||
goto bad_area;
|
||||
/*
|
||||
* Ok, we have a good vm_area for this memory access, so
|
||||
* we can handle it..
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ok, we have a good vm_area for this memory access, so
|
||||
* we can handle it..
|
||||
*/
|
||||
good_area:
|
||||
si_code = SEGV_ACCERR;
|
||||
if (writeaccess) {
|
||||
|
@ -173,10 +212,10 @@ survive:
|
|||
up_read(&mm->mmap_sem);
|
||||
return;
|
||||
|
||||
/*
|
||||
* Something tried to access memory that isn't in our memory map..
|
||||
* Fix it, but check if it's kernel or user first..
|
||||
*/
|
||||
/*
|
||||
* Something tried to access memory that isn't in our memory map..
|
||||
* Fix it, but check if it's kernel or user first..
|
||||
*/
|
||||
bad_area:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/lmb.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/numa.h>
|
||||
#include <linux/pfn.h>
|
||||
|
@ -26,6 +27,15 @@ EXPORT_SYMBOL_GPL(node_data);
|
|||
void __init setup_memory(void)
|
||||
{
|
||||
unsigned long free_pfn = PFN_UP(__pa(_end));
|
||||
u64 base = min_low_pfn << PAGE_SHIFT;
|
||||
u64 size = (max_low_pfn << PAGE_SHIFT) - min_low_pfn;
|
||||
|
||||
lmb_add(base, size);
|
||||
|
||||
/* Reserve the LMB regions used by the kernel, initrd, etc.. */
|
||||
lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
|
||||
(PFN_PHYS(free_pfn) + PAGE_SIZE - 1) -
|
||||
(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
|
||||
|
||||
/*
|
||||
* Node 0 sets up its pgdat at the first available pfn,
|
||||
|
@ -45,24 +55,23 @@ void __init setup_memory(void)
|
|||
|
||||
void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned long bootmap_pages, bootmap_start, bootmap_size;
|
||||
unsigned long start_pfn, free_pfn, end_pfn;
|
||||
unsigned long bootmap_pages;
|
||||
unsigned long start_pfn, end_pfn;
|
||||
unsigned long bootmem_paddr;
|
||||
|
||||
/* Don't allow bogus node assignment */
|
||||
BUG_ON(nid > MAX_NUMNODES || nid == 0);
|
||||
|
||||
/*
|
||||
* The free pfn starts at the beginning of the range, and is
|
||||
* advanced as necessary for pgdat and node map allocations.
|
||||
*/
|
||||
free_pfn = start_pfn = start >> PAGE_SHIFT;
|
||||
start_pfn = start >> PAGE_SHIFT;
|
||||
end_pfn = end >> PAGE_SHIFT;
|
||||
|
||||
lmb_add(start, end - start);
|
||||
|
||||
__add_active_range(nid, start_pfn, end_pfn);
|
||||
|
||||
/* Node-local pgdat */
|
||||
NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
|
||||
free_pfn += PFN_UP(sizeof(struct pglist_data));
|
||||
NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data),
|
||||
SMP_CACHE_BYTES, end_pfn));
|
||||
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
|
||||
|
||||
NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
|
||||
|
@ -71,16 +80,17 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
|
|||
|
||||
/* Node-local bootmap */
|
||||
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
|
||||
bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
|
||||
bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
|
||||
end_pfn);
|
||||
bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
|
||||
PAGE_SIZE, end_pfn);
|
||||
init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
|
||||
start_pfn, end_pfn);
|
||||
|
||||
free_bootmem_with_active_regions(nid, end_pfn);
|
||||
|
||||
/* Reserve the pgdat and bootmap space with the bootmem allocator */
|
||||
reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
|
||||
sizeof(struct pglist_data), BOOTMEM_DEFAULT);
|
||||
reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
|
||||
reserve_bootmem_node(NODE_DATA(nid), bootmem_paddr,
|
||||
bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
|
||||
|
||||
/* It's up */
|
||||
|
|
|
@ -707,12 +707,13 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
|
|||
|
||||
static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
|
||||
{
|
||||
unsigned short ssr_status, scr_status;
|
||||
unsigned short ssr_status, scr_status, err_enabled;
|
||||
struct uart_port *port = ptr;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
ssr_status = sci_in(port, SCxSR);
|
||||
scr_status = sci_in(port, SCSCR);
|
||||
err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
|
||||
|
||||
/* Tx Interrupt */
|
||||
if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE))
|
||||
|
@ -721,10 +722,10 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
|
|||
if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE))
|
||||
ret = sci_rx_interrupt(irq, ptr);
|
||||
/* Error Interrupt */
|
||||
if ((ssr_status & 0x0080) && (scr_status & SCI_CTRL_FLAGS_REIE))
|
||||
if ((ssr_status & 0x0080) && err_enabled)
|
||||
ret = sci_er_interrupt(irq, ptr);
|
||||
/* Break Interrupt */
|
||||
if ((ssr_status & 0x0010) && (scr_status & SCI_CTRL_FLAGS_REIE))
|
||||
if ((ssr_status & 0x0010) && err_enabled)
|
||||
ret = sci_br_interrupt(irq, ptr);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
|
|||
MODULE_AUTHOR("Yoshihiro Shimoda");
|
||||
MODULE_ALIAS("platform:m66592_udc");
|
||||
|
||||
#define DRIVER_VERSION "18 Oct 2007"
|
||||
#define DRIVER_VERSION "26 Jun 2009"
|
||||
|
||||
/* module parameters */
|
||||
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
|
||||
|
@ -276,24 +276,27 @@ static int pipe_buffer_setting(struct m66592 *m66592,
|
|||
buf_bsize = 0;
|
||||
break;
|
||||
case M66592_BULK:
|
||||
bufnum = m66592->bi_bufnum +
|
||||
(info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
|
||||
m66592->bi_bufnum += 16;
|
||||
/* isochronous pipes may be used as bulk pipes */
|
||||
if (info->pipe > M66592_BASE_PIPENUM_BULK)
|
||||
bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
|
||||
else
|
||||
bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
|
||||
|
||||
bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
|
||||
buf_bsize = 7;
|
||||
pipecfg |= M66592_DBLB;
|
||||
if (!info->dir_in)
|
||||
pipecfg |= M66592_SHTNAK;
|
||||
break;
|
||||
case M66592_ISO:
|
||||
bufnum = m66592->bi_bufnum +
|
||||
bufnum = M66592_BASE_BUFNUM +
|
||||
(info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
|
||||
m66592->bi_bufnum += 16;
|
||||
buf_bsize = 7;
|
||||
break;
|
||||
}
|
||||
if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
|
||||
pr_err("m66592 pipe memory is insufficient(%d)\n",
|
||||
m66592->bi_bufnum);
|
||||
|
||||
if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
|
||||
pr_err("m66592 pipe memory is insufficient\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -313,17 +316,6 @@ static void pipe_buffer_release(struct m66592 *m66592,
|
|||
if (info->pipe == 0)
|
||||
return;
|
||||
|
||||
switch (info->type) {
|
||||
case M66592_BULK:
|
||||
if (is_bulk_pipe(info->pipe))
|
||||
m66592->bi_bufnum -= 16;
|
||||
break;
|
||||
case M66592_ISO:
|
||||
if (is_isoc_pipe(info->pipe))
|
||||
m66592->bi_bufnum -= 16;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_bulk_pipe(info->pipe)) {
|
||||
m66592->bulk--;
|
||||
} else if (is_interrupt_pipe(info->pipe))
|
||||
|
@ -1603,8 +1595,6 @@ static int __init m66592_probe(struct platform_device *pdev)
|
|||
m66592->timer.data = (unsigned long)m66592;
|
||||
m66592->reg = reg;
|
||||
|
||||
m66592->bi_bufnum = M66592_BASE_BUFNUM;
|
||||
|
||||
ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
|
||||
udc_name, m66592);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -506,7 +506,6 @@ struct m66592 {
|
|||
int interrupt;
|
||||
int isochronous;
|
||||
int num_dma;
|
||||
int bi_bufnum; /* bulk and isochronous's bufnum */
|
||||
};
|
||||
|
||||
#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
|
||||
|
|
|
@ -337,10 +337,10 @@ config USB_R8A66597_HCD
|
|||
|
||||
config SUPERH_ON_CHIP_R8A66597
|
||||
boolean "Enable SuperH on-chip R8A66597 USB"
|
||||
depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723)
|
||||
depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
|
||||
help
|
||||
This driver enables support for the on-chip R8A66597 in the
|
||||
SH7366 and SH7723 processors.
|
||||
SH7366, SH7723 and SH7724 processors.
|
||||
|
||||
config USB_WHCI_HCD
|
||||
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
|
||||
|
|
Loading…
Reference in New Issue