Merge branches 'sh/ftrace' and 'sh/cachetlb'
This commit is contained in:
@@ -10,6 +10,7 @@ config SUPERH
|
|||||||
select EMBEDDED
|
select EMBEDDED
|
||||||
select HAVE_CLK
|
select HAVE_CLK
|
||||||
select HAVE_IDE
|
select HAVE_IDE
|
||||||
|
select HAVE_LMB
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
select HAVE_GENERIC_DMA_COHERENT
|
select HAVE_GENERIC_DMA_COHERENT
|
||||||
select HAVE_IOREMAP_PROT if MMU
|
select HAVE_IOREMAP_PROT if MMU
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <linux/smc91x.h>
|
#include <linux/smc91x.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <linux/usb/r8a66597.h>
|
||||||
#include <video/sh_mobile_lcdc.h>
|
#include <video/sh_mobile_lcdc.h>
|
||||||
#include <media/sh_mobile_ceu.h>
|
#include <media/sh_mobile_ceu.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
@@ -302,6 +303,34 @@ static struct platform_device sh_eth_device = {
|
|||||||
.resource = sh_eth_resources,
|
.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 = {
|
static struct platform_device *ms7724se_devices[] __initdata = {
|
||||||
&heartbeat_device,
|
&heartbeat_device,
|
||||||
&smc91x_eth_device,
|
&smc91x_eth_device,
|
||||||
@@ -311,6 +340,7 @@ static struct platform_device *ms7724se_devices[] __initdata = {
|
|||||||
&ceu1_device,
|
&ceu1_device,
|
||||||
&keysc_device,
|
&keysc_device,
|
||||||
&sh_eth_device,
|
&sh_eth_device,
|
||||||
|
&sh7724_usb0_host_device,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EEPROM_OP 0xBA206000
|
#define EEPROM_OP 0xBA206000
|
||||||
@@ -364,6 +394,7 @@ static void __init sh_eth_init(void)
|
|||||||
#define SW4140 0xBA201000
|
#define SW4140 0xBA201000
|
||||||
#define FPGA_OUT 0xBA200400
|
#define FPGA_OUT 0xBA200400
|
||||||
#define PORT_HIZA 0xA4050158
|
#define PORT_HIZA 0xA4050158
|
||||||
|
#define PORT_MSELCRB 0xA4050182
|
||||||
|
|
||||||
#define SW41_A 0x0100
|
#define SW41_A 0x0100
|
||||||
#define SW41_B 0x0200
|
#define SW41_B 0x0200
|
||||||
@@ -373,6 +404,7 @@ static void __init sh_eth_init(void)
|
|||||||
#define SW41_F 0x2000
|
#define SW41_F 0x2000
|
||||||
#define SW41_G 0x4000
|
#define SW41_G 0x4000
|
||||||
#define SW41_H 0x8000
|
#define SW41_H 0x8000
|
||||||
|
|
||||||
static int __init devices_setup(void)
|
static int __init devices_setup(void)
|
||||||
{
|
{
|
||||||
u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
|
u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
|
||||||
@@ -385,6 +417,12 @@ static int __init devices_setup(void)
|
|||||||
(1 << 14)), /* RMII */
|
(1 << 14)), /* RMII */
|
||||||
FPGA_OUT);
|
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 */
|
/* enable IRQ 0,1,2 */
|
||||||
gpio_request(GPIO_FN_INTC_IRQ0, NULL);
|
gpio_request(GPIO_FN_INTC_IRQ0, NULL);
|
||||||
gpio_request(GPIO_FN_INTC_IRQ1, NULL);
|
gpio_request(GPIO_FN_INTC_IRQ1, NULL);
|
||||||
|
61
arch/sh/include/asm/hwblk.h
Normal file
61
arch/sh/include/asm/hwblk.h
Normal file
@@ -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 */
|
6
arch/sh/include/asm/lmb.h
Normal file
6
arch/sh/include/asm/lmb.h
Normal file
@@ -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. */
|
/* SH only supports software counters through this interface. */
|
||||||
static inline void set_perf_counter_pending(void) {}
|
static inline void set_perf_counter_pending(void) {}
|
||||||
|
|
||||||
|
#define PERF_COUNTER_INDEX_OFFSET 0
|
||||||
|
|
||||||
#endif /* __ASM_SH_PERF_COUNTER_H */
|
#endif /* __ASM_SH_PERF_COUNTER_H */
|
||||||
|
@@ -10,6 +10,15 @@ struct swsusp_arch_regs {
|
|||||||
struct pt_regs user_regs;
|
struct pt_regs user_regs;
|
||||||
unsigned long bank1_regs[8];
|
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
|
#endif
|
||||||
|
|
||||||
/* flags passed to assembly suspend code */
|
/* flags passed to assembly suspend code */
|
||||||
|
@@ -221,4 +221,18 @@ enum {
|
|||||||
GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
|
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__ */
|
#endif /* __ASM_SH7722_H__ */
|
||||||
|
@@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP) += ubc.o
|
|||||||
obj-$(CONFIG_SH_ADC) += adc.o
|
obj-$(CONFIG_SH_ADC) += adc.o
|
||||||
obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.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
|
||||||
|
130
arch/sh/kernel/cpu/hwblk.c
Normal file
130
arch/sh/kernel/cpu/hwblk.c
Normal file
@@ -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_SH7785) := clock-sh7785.o
|
||||||
clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
|
clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
|
||||||
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.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_SH7723) := clock-sh7723.o
|
||||||
clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
|
clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
|
||||||
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
|
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
|
||||||
|
@@ -22,6 +22,8 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <asm/clock.h>
|
#include <asm/clock.h>
|
||||||
|
#include <asm/hwblk.h>
|
||||||
|
#include <cpu/sh7722.h>
|
||||||
|
|
||||||
/* SH7722 registers */
|
/* SH7722 registers */
|
||||||
#define FRQCR 0xa4150000
|
#define FRQCR 0xa4150000
|
||||||
@@ -140,35 +142,37 @@ struct clk div6_clks[] = {
|
|||||||
SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
|
SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MSTP(_str, _parent, _reg, _bit, _flags) \
|
#define R_CLK &r_clk
|
||||||
SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags)
|
#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[] = {
|
static struct clk mstp_clks[] = {
|
||||||
MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
|
SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
|
||||||
MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
|
SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
|
||||||
MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0),
|
SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
|
||||||
MSTP("cmt0", &r_clk, MSTPCR0, 14, 0),
|
SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
|
||||||
MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0),
|
SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
|
||||||
MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0),
|
SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
|
||||||
MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0),
|
SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
|
||||||
MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0),
|
SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
|
||||||
MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0),
|
SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
|
||||||
|
|
||||||
MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0),
|
SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
|
||||||
MSTP("rtc0", &r_clk, MSTPCR1, 8, 0),
|
SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
|
||||||
|
|
||||||
MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0),
|
SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
|
||||||
MSTP("keysc0", &r_clk, MSTPCR2, 14, 0),
|
SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
|
||||||
MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0),
|
SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
|
||||||
MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0),
|
SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
|
||||||
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0),
|
SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
|
||||||
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0),
|
SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
|
||||||
MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
|
SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
|
||||||
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0),
|
SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
|
||||||
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0),
|
SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
|
||||||
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
|
SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT),
|
||||||
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
|
SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
|
||||||
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0),
|
SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
int __init arch_clk_init(void)
|
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));
|
ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
|
||||||
|
|
||||||
if (!ret)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
106
arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
Normal file
106
arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
Normal file
@@ -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
|
# Power Management & Sleep mode
|
||||||
obj-$(CONFIG_PM) += pm.o sleep.o
|
obj-$(CONFIG_PM) += pm.o sleep.o
|
||||||
|
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
|
||||||
|
102
arch/sh/kernel/cpu/shmobile/cpuidle.c
Normal file
102
arch/sh/kernel/cpu/shmobile/cpuidle.c
Normal file
@@ -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
|
* Power management support code for SuperH Mobile
|
||||||
*
|
*
|
||||||
@@ -32,20 +32,17 @@
|
|||||||
*
|
*
|
||||||
* R-standby mode is unsupported, but will be added in the future
|
* R-standby mode is unsupported, but will be added in the future
|
||||||
* U-standby mode is low priority since it needs bootloader hacks
|
* 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 char sh_mobile_standby[];
|
||||||
extern const unsigned int sh_mobile_standby_size;
|
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;
|
extern void *vbr_base;
|
||||||
void *onchip_mem = (void *)0xe5200000; /* ILRAM */
|
void *onchip_mem = (void *)ILRAM_BASE;
|
||||||
void (*standby_onchip_mem)(unsigned long) = onchip_mem;
|
void (*standby_onchip_mem)(unsigned long) = onchip_mem;
|
||||||
|
|
||||||
/* Note: Wake up from sleep may generate exceptions!
|
/* 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)
|
if (mode & SUSP_SH_SF)
|
||||||
asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
|
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 */
|
/* Let assembly snippet in on-chip memory handle the rest */
|
||||||
standby_onchip_mem(mode);
|
standby_onchip_mem(mode);
|
||||||
|
|
||||||
@@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = {
|
|||||||
|
|
||||||
static int __init sh_pm_init(void)
|
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);
|
suspend_set_ops(&sh_pm_ops);
|
||||||
|
sh_mobile_setup_cpuidle();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/lmb.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/page.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)
|
void __init setup_bootmem_allocator(unsigned long free_pfn)
|
||||||
{
|
{
|
||||||
unsigned long bootmap_size;
|
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
|
* Find a proper area for the bootmem bitmap. After this
|
||||||
* bootstrap step all allocations (until the page allocator
|
* bootstrap step all allocations (until the page allocator
|
||||||
* is intact) must be done via bootmem_alloc().
|
* 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);
|
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();
|
register_bootmem_low_pages();
|
||||||
|
|
||||||
node_set_online(0);
|
/* Reserve the sections we're already using. */
|
||||||
|
for (i = 0; i < lmb.reserved.cnt; i++)
|
||||||
/*
|
reserve_bootmem(lmb.reserved.region[i].base,
|
||||||
* Reserve the kernel text and
|
lmb_size_bytes(&lmb.reserved, i),
|
||||||
* 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,
|
|
||||||
BOOTMEM_DEFAULT);
|
BOOTMEM_DEFAULT);
|
||||||
|
|
||||||
|
node_set_online(0);
|
||||||
|
|
||||||
sparse_memory_present_with_active_regions(0);
|
sparse_memory_present_with_active_regions(0);
|
||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
@@ -296,12 +303,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
|
|||||||
static void __init setup_memory(void)
|
static void __init setup_memory(void)
|
||||||
{
|
{
|
||||||
unsigned long start_pfn;
|
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
|
* Partially used pages are not usable - thus
|
||||||
* we are rounding upwards:
|
* we are rounding upwards:
|
||||||
*/
|
*/
|
||||||
start_pfn = PFN_UP(__pa(_end));
|
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);
|
setup_bootmem_allocator(start_pfn);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -402,6 +434,7 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
nodes_clear(node_online_map);
|
nodes_clear(node_online_map);
|
||||||
|
|
||||||
/* Setup bootmem with available RAM */
|
/* Setup bootmem with available RAM */
|
||||||
|
lmb_init();
|
||||||
setup_memory();
|
setup_memory();
|
||||||
sparse_init();
|
sparse_init();
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <asm/clock.h>
|
#include <asm/clock.h>
|
||||||
|
#include <asm/hwblk.h>
|
||||||
#include <asm/rtc.h>
|
#include <asm/rtc.h>
|
||||||
|
|
||||||
/* Dummy RTC ops */
|
/* Dummy RTC ops */
|
||||||
@@ -96,6 +97,7 @@ void __init time_init(void)
|
|||||||
if (board_time_init)
|
if (board_time_init)
|
||||||
board_time_init();
|
board_time_init();
|
||||||
|
|
||||||
|
hwblk_init();
|
||||||
clk_init();
|
clk_init();
|
||||||
|
|
||||||
rtc_sh_get_time(&xtime);
|
rtc_sh_get_time(&xtime);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* Page fault handler for SH with an MMU.
|
* Page fault handler for SH with an MMU.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999 Niibe Yutaka
|
* 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:
|
* Based on linux/arch/i386/mm/fault.c:
|
||||||
* Copyright (C) 1995 Linus Torvalds
|
* Copyright (C) 1995 Linus Torvalds
|
||||||
@@ -25,18 +25,84 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_KPROBES
|
if (kprobes_built_in() && !user_mode(regs)) {
|
||||||
if (!user_mode(regs)) {
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
if (kprobe_running() && kprobe_fault_handler(regs, trap))
|
if (kprobe_running() && kprobe_fault_handler(regs, trap))
|
||||||
ret = 1;
|
ret = 1;
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
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,
|
* This routine handles page faults. It determines the address,
|
||||||
* and the problem, and then passes it off to one of the appropriate
|
* 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 writeaccess,
|
||||||
unsigned long address)
|
unsigned long address)
|
||||||
{
|
{
|
||||||
|
unsigned long vec;
|
||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
struct vm_area_struct * vma;
|
struct vm_area_struct * vma;
|
||||||
@@ -53,59 +120,30 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||||||
int fault;
|
int fault;
|
||||||
siginfo_t info;
|
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;
|
tsk = current;
|
||||||
|
mm = tsk->mm;
|
||||||
si_code = SEGV_MAPERR;
|
si_code = SEGV_MAPERR;
|
||||||
|
vec = lookup_exception_vector();
|
||||||
|
|
||||||
if (unlikely(address >= TASK_SIZE)) {
|
/*
|
||||||
/*
|
* We fault-in kernel-space virtual memory on-demand. The
|
||||||
* Synchronize this task's top level page-table
|
* 'reference' page table is init_mm.pgd.
|
||||||
* with the 'reference' page table.
|
*
|
||||||
*
|
* NOTE! We MUST NOT take any locks for this case. We may
|
||||||
* Do _not_ use "tsk" here. We might be inside
|
* be in an interrupt or a critical region, and should
|
||||||
* an interrupt in the middle of a task switch..
|
* only copy the information from the master page table,
|
||||||
*/
|
* nothing more.
|
||||||
int offset = pgd_index(address);
|
*/
|
||||||
pgd_t *pgd, *pgd_k;
|
if (unlikely(fault_in_kernel_space(address))) {
|
||||||
pud_t *pud, *pud_k;
|
if (vmalloc_fault(address) >= 0)
|
||||||
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);
|
|
||||||
return;
|
return;
|
||||||
}
|
if (notify_page_fault(regs, vec))
|
||||||
|
|
||||||
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);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
pmd = pmd_offset(pud, address);
|
goto bad_area_nosemaphore;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mm = tsk->mm;
|
if (unlikely(notify_page_fault(regs, vec)))
|
||||||
|
|
||||||
if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Only enable interrupts if they were on before the fault */
|
/* 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);
|
perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're in an interrupt or have no user
|
* If we're in an interrupt, have no user context or are running
|
||||||
* context, we must not take the fault..
|
* in an atomic region then we must not take the fault:
|
||||||
*/
|
*/
|
||||||
if (in_atomic() || !mm)
|
if (in_atomic() || !mm)
|
||||||
goto no_context;
|
goto no_context;
|
||||||
@@ -132,10 +170,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|||||||
goto bad_area;
|
goto bad_area;
|
||||||
if (expand_stack(vma, address))
|
if (expand_stack(vma, address))
|
||||||
goto bad_area;
|
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:
|
good_area:
|
||||||
si_code = SEGV_ACCERR;
|
si_code = SEGV_ACCERR;
|
||||||
if (writeaccess) {
|
if (writeaccess) {
|
||||||
@@ -173,10 +212,10 @@ survive:
|
|||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Something tried to access memory that isn't in our memory map..
|
* Something tried to access memory that isn't in our memory map..
|
||||||
* Fix it, but check if it's kernel or user first..
|
* Fix it, but check if it's kernel or user first..
|
||||||
*/
|
*/
|
||||||
bad_area:
|
bad_area:
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
|
#include <linux/lmb.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/numa.h>
|
#include <linux/numa.h>
|
||||||
#include <linux/pfn.h>
|
#include <linux/pfn.h>
|
||||||
@@ -26,6 +27,15 @@ EXPORT_SYMBOL_GPL(node_data);
|
|||||||
void __init setup_memory(void)
|
void __init setup_memory(void)
|
||||||
{
|
{
|
||||||
unsigned long free_pfn = PFN_UP(__pa(_end));
|
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,
|
* 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)
|
void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
unsigned long bootmap_pages, bootmap_start, bootmap_size;
|
unsigned long bootmap_pages;
|
||||||
unsigned long start_pfn, free_pfn, end_pfn;
|
unsigned long start_pfn, end_pfn;
|
||||||
|
unsigned long bootmem_paddr;
|
||||||
|
|
||||||
/* Don't allow bogus node assignment */
|
/* Don't allow bogus node assignment */
|
||||||
BUG_ON(nid > MAX_NUMNODES || nid == 0);
|
BUG_ON(nid > MAX_NUMNODES || nid == 0);
|
||||||
|
|
||||||
/*
|
start_pfn = start >> PAGE_SHIFT;
|
||||||
* 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;
|
|
||||||
end_pfn = end >> PAGE_SHIFT;
|
end_pfn = end >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
lmb_add(start, end - start);
|
||||||
|
|
||||||
__add_active_range(nid, start_pfn, end_pfn);
|
__add_active_range(nid, start_pfn, end_pfn);
|
||||||
|
|
||||||
/* Node-local pgdat */
|
/* Node-local pgdat */
|
||||||
NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
|
NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data),
|
||||||
free_pfn += PFN_UP(sizeof(struct pglist_data));
|
SMP_CACHE_BYTES, end_pfn));
|
||||||
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
|
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
|
||||||
|
|
||||||
NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
|
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 */
|
/* Node-local bootmap */
|
||||||
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
|
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
|
||||||
bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
|
bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
|
||||||
bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
|
PAGE_SIZE, end_pfn);
|
||||||
end_pfn);
|
init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
|
||||||
|
start_pfn, end_pfn);
|
||||||
|
|
||||||
free_bootmem_with_active_regions(nid, end_pfn);
|
free_bootmem_with_active_regions(nid, end_pfn);
|
||||||
|
|
||||||
/* Reserve the pgdat and bootmap space with the bootmem allocator */
|
/* Reserve the pgdat and bootmap space with the bootmem allocator */
|
||||||
reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
|
reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
|
||||||
sizeof(struct pglist_data), BOOTMEM_DEFAULT);
|
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);
|
bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
|
||||||
|
|
||||||
/* It's up */
|
/* 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)
|
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;
|
struct uart_port *port = ptr;
|
||||||
irqreturn_t ret = IRQ_NONE;
|
irqreturn_t ret = IRQ_NONE;
|
||||||
|
|
||||||
ssr_status = sci_in(port, SCxSR);
|
ssr_status = sci_in(port, SCxSR);
|
||||||
scr_status = sci_in(port, SCSCR);
|
scr_status = sci_in(port, SCSCR);
|
||||||
|
err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
|
||||||
|
|
||||||
/* Tx Interrupt */
|
/* Tx Interrupt */
|
||||||
if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE))
|
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))
|
if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE))
|
||||||
ret = sci_rx_interrupt(irq, ptr);
|
ret = sci_rx_interrupt(irq, ptr);
|
||||||
/* Error Interrupt */
|
/* Error Interrupt */
|
||||||
if ((ssr_status & 0x0080) && (scr_status & SCI_CTRL_FLAGS_REIE))
|
if ((ssr_status & 0x0080) && err_enabled)
|
||||||
ret = sci_er_interrupt(irq, ptr);
|
ret = sci_er_interrupt(irq, ptr);
|
||||||
/* Break Interrupt */
|
/* Break Interrupt */
|
||||||
if ((ssr_status & 0x0010) && (scr_status & SCI_CTRL_FLAGS_REIE))
|
if ((ssr_status & 0x0010) && err_enabled)
|
||||||
ret = sci_br_interrupt(irq, ptr);
|
ret = sci_br_interrupt(irq, ptr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
|
|||||||
MODULE_AUTHOR("Yoshihiro Shimoda");
|
MODULE_AUTHOR("Yoshihiro Shimoda");
|
||||||
MODULE_ALIAS("platform:m66592_udc");
|
MODULE_ALIAS("platform:m66592_udc");
|
||||||
|
|
||||||
#define DRIVER_VERSION "18 Oct 2007"
|
#define DRIVER_VERSION "26 Jun 2009"
|
||||||
|
|
||||||
/* module parameters */
|
/* module parameters */
|
||||||
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
|
#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
|
||||||
@@ -276,24 +276,27 @@ static int pipe_buffer_setting(struct m66592 *m66592,
|
|||||||
buf_bsize = 0;
|
buf_bsize = 0;
|
||||||
break;
|
break;
|
||||||
case M66592_BULK:
|
case M66592_BULK:
|
||||||
bufnum = m66592->bi_bufnum +
|
/* isochronous pipes may be used as bulk pipes */
|
||||||
(info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
|
if (info->pipe > M66592_BASE_PIPENUM_BULK)
|
||||||
m66592->bi_bufnum += 16;
|
bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
|
||||||
|
else
|
||||||
|
bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
|
||||||
|
|
||||||
|
bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
|
||||||
buf_bsize = 7;
|
buf_bsize = 7;
|
||||||
pipecfg |= M66592_DBLB;
|
pipecfg |= M66592_DBLB;
|
||||||
if (!info->dir_in)
|
if (!info->dir_in)
|
||||||
pipecfg |= M66592_SHTNAK;
|
pipecfg |= M66592_SHTNAK;
|
||||||
break;
|
break;
|
||||||
case M66592_ISO:
|
case M66592_ISO:
|
||||||
bufnum = m66592->bi_bufnum +
|
bufnum = M66592_BASE_BUFNUM +
|
||||||
(info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
|
(info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
|
||||||
m66592->bi_bufnum += 16;
|
|
||||||
buf_bsize = 7;
|
buf_bsize = 7;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
|
|
||||||
pr_err("m66592 pipe memory is insufficient(%d)\n",
|
if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
|
||||||
m66592->bi_bufnum);
|
pr_err("m66592 pipe memory is insufficient\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,17 +316,6 @@ static void pipe_buffer_release(struct m66592 *m66592,
|
|||||||
if (info->pipe == 0)
|
if (info->pipe == 0)
|
||||||
return;
|
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)) {
|
if (is_bulk_pipe(info->pipe)) {
|
||||||
m66592->bulk--;
|
m66592->bulk--;
|
||||||
} else if (is_interrupt_pipe(info->pipe))
|
} 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->timer.data = (unsigned long)m66592;
|
||||||
m66592->reg = reg;
|
m66592->reg = reg;
|
||||||
|
|
||||||
m66592->bi_bufnum = M66592_BASE_BUFNUM;
|
|
||||||
|
|
||||||
ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
|
ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
|
||||||
udc_name, m66592);
|
udc_name, m66592);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@@ -506,7 +506,6 @@ struct m66592 {
|
|||||||
int interrupt;
|
int interrupt;
|
||||||
int isochronous;
|
int isochronous;
|
||||||
int num_dma;
|
int num_dma;
|
||||||
int bi_bufnum; /* bulk and isochronous's bufnum */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
|
#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
|
||||||
|
@@ -337,10 +337,10 @@ config USB_R8A66597_HCD
|
|||||||
|
|
||||||
config SUPERH_ON_CHIP_R8A66597
|
config SUPERH_ON_CHIP_R8A66597
|
||||||
boolean "Enable SuperH on-chip R8A66597 USB"
|
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
|
help
|
||||||
This driver enables support for the on-chip R8A66597 in the
|
This driver enables support for the on-chip R8A66597 in the
|
||||||
SH7366 and SH7723 processors.
|
SH7366, SH7723 and SH7724 processors.
|
||||||
|
|
||||||
config USB_WHCI_HCD
|
config USB_WHCI_HCD
|
||||||
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
|
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
|
||||||
|
Reference in New Issue
Block a user