diff options
Diffstat (limited to 'arch')
92 files changed, 4338 insertions, 2317 deletions
diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c index f3cc1036e5b..0934e6fba60 100644 --- a/arch/arm26/kernel/irq.c +++ b/arch/arm26/kernel/irq.c @@ -141,7 +141,7 @@ int show_interrupts(struct seq_file *p, void *v) if (i < NR_IRQS) { action = irq_desc[i].action; if (!action) - continue; + goto out; seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) { @@ -152,6 +152,7 @@ int show_interrupts(struct seq_file *p, void *v) show_fiq_list(p, v); seq_printf(p, "Err: %10lu\n", irq_err_count); } +out: return 0; } diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 3c3371d4683..282e24d7932 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -527,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { set_stopped_child_used_math(tsk); - return copy_from_user(&task_threas_info(tsk)->fpstate, ufp, + return copy_from_user(&task_thread_info(tsk)->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff --git a/arch/i386/Makefile b/arch/i386/Makefile index bd2d53a9dd2..36bef6543ac 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -37,10 +37,7 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu -# -mregparm=3 works ok on gcc-3.0 and later -# -cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ - echo "-mregparm=3"; fi ;) +cflags-$(CONFIG_REGPARM) += -mregparm=3 # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # a lot more stack due to the lack of sharing of stacklots: diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 0fbbd4c1072..e11a09207ec 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -980,7 +980,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol) } /* per CPU init entry point to the driver */ -static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) +static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; cpumask_t oldmask = CPU_MASK_ALL; @@ -1141,7 +1141,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = { }; /* driver entry point for init */ -static int __init powernowk8_init(void) +static int __cpuinit powernowk8_init(void) { unsigned int i, supported_cpus = 0; diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 7df494b51a5..2700f01994b 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -268,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) pkmap_page_table = pte; } -static void __devinit free_new_highpage(struct page *page) +static void __meminit free_new_highpage(struct page *page) { set_page_count(page, 1); __free_page(page); diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index bd87cb6b7a8..2ea4b39efff 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -628,9 +628,11 @@ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, #include "perfmon_itanium.h" #include "perfmon_mckinley.h" +#include "perfmon_montecito.h" #include "perfmon_generic.h" static pmu_config_t *pmu_confs[]={ + &pmu_conf_mont, &pmu_conf_mck, &pmu_conf_ita, &pmu_conf_gen, /* must be last */ diff --git a/arch/ia64/kernel/perfmon_montecito.h b/arch/ia64/kernel/perfmon_montecito.h new file mode 100644 index 00000000000..cd06ac6a686 --- /dev/null +++ b/arch/ia64/kernel/perfmon_montecito.h @@ -0,0 +1,269 @@ +/* + * This file contains the Montecito PMU register description tables + * and pmc checker used by perfmon.c. + * + * Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P. + * Contributed by Stephane Eranian <eranian@hpl.hp.com> + */ +static int pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs); + +#define RDEP_MONT_ETB (RDEP(38)|RDEP(39)|RDEP(48)|RDEP(49)|RDEP(50)|RDEP(51)|RDEP(52)|RDEP(53)|RDEP(54)|\ + RDEP(55)|RDEP(56)|RDEP(57)|RDEP(58)|RDEP(59)|RDEP(60)|RDEP(61)|RDEP(62)|RDEP(63)) +#define RDEP_MONT_DEAR (RDEP(32)|RDEP(33)|RDEP(36)) +#define RDEP_MONT_IEAR (RDEP(34)|RDEP(35)) + +static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc4 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(4),0, 0, 0}, {0,0, 0, 0}}, +/* pmc5 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(5),0, 0, 0}, {0,0, 0, 0}}, +/* pmc6 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(6),0, 0, 0}, {0,0, 0, 0}}, +/* pmc7 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(7),0, 0, 0}, {0,0, 0, 0}}, +/* pmc8 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(8),0, 0, 0}, {0,0, 0, 0}}, +/* pmc9 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(9),0, 0, 0}, {0,0, 0, 0}}, +/* pmc10 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(10),0, 0, 0}, {0,0, 0, 0}}, +/* pmc11 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(11),0, 0, 0}, {0,0, 0, 0}}, +/* pmc12 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(12),0, 0, 0}, {0,0, 0, 0}}, +/* pmc13 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(13),0, 0, 0}, {0,0, 0, 0}}, +/* pmc14 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(14),0, 0, 0}, {0,0, 0, 0}}, +/* pmc15 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(15),0, 0, 0}, {0,0, 0, 0}}, +/* pmc16 */ { PFM_REG_NOTIMPL, }, +/* pmc17 */ { PFM_REG_NOTIMPL, }, +/* pmc18 */ { PFM_REG_NOTIMPL, }, +/* pmc19 */ { PFM_REG_NOTIMPL, }, +/* pmc20 */ { PFM_REG_NOTIMPL, }, +/* pmc21 */ { PFM_REG_NOTIMPL, }, +/* pmc22 */ { PFM_REG_NOTIMPL, }, +/* pmc23 */ { PFM_REG_NOTIMPL, }, +/* pmc24 */ { PFM_REG_NOTIMPL, }, +/* pmc25 */ { PFM_REG_NOTIMPL, }, +/* pmc26 */ { PFM_REG_NOTIMPL, }, +/* pmc27 */ { PFM_REG_NOTIMPL, }, +/* pmc28 */ { PFM_REG_NOTIMPL, }, +/* pmc29 */ { PFM_REG_NOTIMPL, }, +/* pmc30 */ { PFM_REG_NOTIMPL, }, +/* pmc31 */ { PFM_REG_NOTIMPL, }, +/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}}, +/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, +/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}}, +/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, + { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +static pfm_reg_desc_t pfm_mont_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_NOTIMPL, }, +/* pmd1 */ { PFM_REG_NOTIMPL, }, +/* pmd2 */ { PFM_REG_NOTIMPL, }, +/* pmd3 */ { PFM_REG_NOTIMPL, }, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(4),0, 0, 0}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(5),0, 0, 0}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(6),0, 0, 0}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(7),0, 0, 0}}, +/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(8),0, 0, 0}}, +/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(9),0, 0, 0}}, +/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(10),0, 0, 0}}, +/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(11),0, 0, 0}}, +/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(12),0, 0, 0}}, +/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(13),0, 0, 0}}, +/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(14),0, 0, 0}}, +/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(15),0, 0, 0}}, +/* pmd16 */ { PFM_REG_NOTIMPL, }, +/* pmd17 */ { PFM_REG_NOTIMPL, }, +/* pmd18 */ { PFM_REG_NOTIMPL, }, +/* pmd19 */ { PFM_REG_NOTIMPL, }, +/* pmd20 */ { PFM_REG_NOTIMPL, }, +/* pmd21 */ { PFM_REG_NOTIMPL, }, +/* pmd22 */ { PFM_REG_NOTIMPL, }, +/* pmd23 */ { PFM_REG_NOTIMPL, }, +/* pmd24 */ { PFM_REG_NOTIMPL, }, +/* pmd25 */ { PFM_REG_NOTIMPL, }, +/* pmd26 */ { PFM_REG_NOTIMPL, }, +/* pmd27 */ { PFM_REG_NOTIMPL, }, +/* pmd28 */ { PFM_REG_NOTIMPL, }, +/* pmd29 */ { PFM_REG_NOTIMPL, }, +/* pmd30 */ { PFM_REG_NOTIMPL, }, +/* pmd31 */ { PFM_REG_NOTIMPL, }, +/* pmd32 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(33)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd33 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd34 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(35),0, 0, 0}, {RDEP(37),0, 0, 0}}, +/* pmd35 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(34),0, 0, 0}, {RDEP(37),0, 0, 0}}, +/* pmd36 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(33),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd37 */ { PFM_REG_NOTIMPL, }, +/* pmd38 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd39 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd40 */ { PFM_REG_NOTIMPL, }, +/* pmd41 */ { PFM_REG_NOTIMPL, }, +/* pmd42 */ { PFM_REG_NOTIMPL, }, +/* pmd43 */ { PFM_REG_NOTIMPL, }, +/* pmd44 */ { PFM_REG_NOTIMPL, }, +/* pmd45 */ { PFM_REG_NOTIMPL, }, +/* pmd46 */ { PFM_REG_NOTIMPL, }, +/* pmd47 */ { PFM_REG_NOTIMPL, }, +/* pmd48 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd49 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd50 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd51 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd52 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd53 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd54 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd55 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd56 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd57 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd58 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd59 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd60 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd61 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd62 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd63 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, + { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +/* + * PMC reserved fields must have their power-up values preserved + */ +static int +pfm_mont_reserved(unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + unsigned long tmp1, tmp2, ival = *val; + + /* remove reserved areas from user value */ + tmp1 = ival & PMC_RSVD_MASK(cnum); + + /* get reserved fields values */ + tmp2 = PMC_DFL_VAL(cnum) & ~PMC_RSVD_MASK(cnum); + + *val = tmp1 | tmp2; + + DPRINT(("pmc[%d]=0x%lx, mask=0x%lx, reset=0x%lx, val=0x%lx\n", + cnum, ival, PMC_RSVD_MASK(cnum), PMC_DFL_VAL(cnum), *val)); + return 0; +} + +/* + * task can be NULL if the context is unloaded + */ +static int +pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + int ret = 0; + unsigned long val32 = 0, val38 = 0, val41 = 0; + unsigned long tmpval; + int check_case1 = 0; + int is_loaded; + + /* first preserve the reserved fields */ + pfm_mont_reserved(cnum, val, regs); + + tmpval = *val; + + /* sanity check */ + if (ctx == NULL) return -EINVAL; + + is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED; + + /* + * we must clear the debug registers if pmc41 has a value which enable + * memory pipeline event constraints. In this case we need to clear the + * the debug registers if they have not yet been accessed. This is required + * to avoid picking stale state. + * PMC41 is "active" if: + * one of the pmc41.cfg_dtagXX field is different from 0x3 + * AND + * at the corresponding pmc41.en_dbrpXX is set. + * AND + * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used) + */ + DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded)); + + if (cnum == 41 && is_loaded + && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval)); + + /* don't mix debug with perfmon */ + if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; + + /* + * a count of 0 will mark the debug registers if: + * AND + */ + ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs); + if (ret) return ret; + } + /* + * we must clear the (instruction) debug registers if: + * pmc38.ig_ibrpX is 0 (enabled) + * AND + * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used) + */ + if (cnum == 38 && is_loaded && ((tmpval & 0x492UL) != 0x492UL) && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc38=0x%lx has active pmc38 settings, clearing ibr\n", tmpval)); + + /* don't mix debug with perfmon */ + if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; + + /* + * a count of 0 will mark the debug registers as in use and also + * ensure that they are properly cleared. + */ + ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs); + if (ret) return ret; + + } + switch(cnum) { + case 32: val32 = *val; + val38 = ctx->ctx_pmcs[38]; + val41 = ctx->ctx_pmcs[41]; + check_case1 = 1; + break; + case 38: val38 = *val; + val32 = ctx->ctx_pmcs[32]; + val41 = ctx->ctx_pmcs[41]; + check_case1 = 1; + break; + case 41: val41 = *val; + val32 = ctx->ctx_pmcs[32]; + val38 = ctx->ctx_pmcs[38]; + check_case1 = 1; + break; + } + /* check illegal configuration which can produce inconsistencies in tagging + * i-side events in L1D and L2 caches + */ + if (check_case1) { + ret = (((val41 >> 45) & 0xf) == 0 && ((val32>>57) & 0x1) == 0) + && ((((val38>>1) & 0x3) == 0x2 || ((val38>>1) & 0x3) == 0) + || (((val38>>4) & 0x3) == 0x2 || ((val38>>4) & 0x3) == 0)); + if (ret) { + DPRINT(("invalid config pmc38=0x%lx pmc41=0x%lx pmc32=0x%lx\n", val38, val41, val32)); + return -EINVAL; + } + } + *val = tmpval; + return 0; +} + +/* + * impl_pmcs, impl_pmds are computed at runtime to minimize errors! + */ +static pmu_config_t pmu_conf_mont={ + .pmu_name = "Montecito", + .pmu_family = 0x20, + .flags = PFM_PMU_IRQ_RESEND, + .ovfl_val = (1UL << 47) - 1, + .pmd_desc = pfm_mont_pmd_desc, + .pmc_desc = pfm_mont_pmc_desc, + .num_ibrs = 8, + .num_dbrs = 8, + .use_rr_dbregs = 1 /* debug register are use for range retrictions */ +}; diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index e3215ba64ff..b38b6d213c1 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -635,3 +635,39 @@ mem_init (void) ia32_mem_init(); #endif } + +#ifdef CONFIG_MEMORY_HOTPLUG +void online_page(struct page *page) +{ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + totalram_pages++; + num_physpages++; +} + +int add_memory(u64 start, u64 size) +{ + pg_data_t *pgdat; + struct zone *zone; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + int ret; + + pgdat = NODE_DATA(0); + + zone = pgdat->node_zones + ZONE_NORMAL; + ret = __add_pages(zone, start_pfn, nr_pages); + + if (ret) + printk("%s: Problem encountered in __add_pages() as ret=%d\n", + __FUNCTION__, ret); + + return ret; +} + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +#endif diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 30dbc98bf0b..d27ecdcb6fc 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -454,14 +454,13 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx) return 0; } -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +static void __devinit +pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) { struct pci_bus_region region; int i; - int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \ - PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES; - for (i = 0; i < limit; i++) { + for (i = start; i < limit; i++) { if (!dev->resource[i].flags) continue; region.start = dev->resource[i].start; @@ -472,6 +471,16 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) } } +static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +{ + pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES); +} + +static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev) +{ + pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES); +} + /* * Called after each bus is probed, but before its children are examined. */ @@ -482,7 +491,7 @@ pcibios_fixup_bus (struct pci_bus *b) if (b->self) { pci_read_bridge_bases(b); - pcibios_fixup_device_resources(b->self); + pcibios_fixup_bridge_resources(b->self); } list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 4d417c30120..7c88e9a5851 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h @@ -40,8 +40,8 @@ struct sn_flush_device_common { unsigned long sfdl_force_int_addr; unsigned long sfdl_flush_value; volatile unsigned long *sfdl_flush_addr; - uint32_t sfdl_persistent_busnum; - uint32_t sfdl_persistent_segment; + u32 sfdl_persistent_busnum; + u32 sfdl_persistent_segment; struct pcibus_info *sfdl_pcibus_info; }; @@ -56,7 +56,7 @@ struct sn_flush_device_kernel { */ struct sn_flush_nasid_entry { struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num - uint64_t iio_itte[8]; + u64 iio_itte[8]; }; struct hubdev_info { @@ -70,8 +70,8 @@ struct hubdev_info { void *hdi_nodepda; void *hdi_node_vertex; - uint32_t max_segment_number; - uint32_t max_pcibus_number; + u32 max_segment_number; + u32 max_pcibus_number; }; extern void hubdev_init_node(nodepda_t *, cnodeid_t); diff --git a/arch/ia64/sn/include/xtalk/xbow.h b/arch/ia64/sn/include/xtalk/xbow.h index ec56b3432f1..90f37a4133d 100644 --- a/arch/ia64/sn/include/xtalk/xbow.h +++ b/arch/ia64/sn/include/xtalk/xbow.h @@ -3,7 +3,8 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997,2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997,2000-2006 Silicon Graphics, Inc. All Rights + * Reserved. */ #ifndef _ASM_IA64_SN_XTALK_XBOW_H #define _ASM_IA64_SN_XTALK_XBOW_H @@ -21,94 +22,94 @@ /* Register set for each xbow link */ typedef volatile struct xb_linkregs_s { -/* +/* * we access these through synergy unswizzled space, so the address * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) * That's why we put the register first and filler second. */ - uint32_t link_ibf; - uint32_t filler0; /* filler for proper alignment */ - uint32_t link_control; - uint32_t filler1; - uint32_t link_status; - uint32_t filler2; - uint32_t link_arb_upper; - uint32_t filler3; - uint32_t link_arb_lower; - uint32_t filler4; - uint32_t link_status_clr; - uint32_t filler5; - uint32_t link_reset; - uint32_t filler6; - uint32_t link_aux_status; - uint32_t filler7; + u32 link_ibf; + u32 filler0; /* filler for proper alignment */ + u32 link_control; + u32 filler1; + u32 link_status; + u32 filler2; + u32 link_arb_upper; + u32 filler3; + u32 link_arb_lower; + u32 filler4; + u32 link_status_clr; + u32 filler5; + u32 link_reset; + u32 filler6; + u32 link_aux_status; + u32 filler7; } xb_linkregs_t; typedef volatile struct xbow_s { - /* standard widget configuration 0x000000-0x000057 */ - struct widget_cfg xb_widget; /* 0x000000 */ - - /* helper fieldnames for accessing bridge widget */ - -#define xb_wid_id xb_widget.w_id -#define xb_wid_stat xb_widget.w_status -#define xb_wid_err_upper xb_widget.w_err_upper_addr -#define xb_wid_err_lower xb_widget.w_err_lower_addr -#define xb_wid_control xb_widget.w_control -#define xb_wid_req_timeout xb_widget.w_req_timeout -#define xb_wid_int_upper xb_widget.w_intdest_upper_addr -#define xb_wid_int_lower xb_widget.w_intdest_lower_addr -#define xb_wid_err_cmdword xb_widget.w_err_cmd_word -#define xb_wid_llp xb_widget.w_llp_cfg -#define xb_wid_stat_clr xb_widget.w_tflush - -/* + /* standard widget configuration 0x000000-0x000057 */ + struct widget_cfg xb_widget; /* 0x000000 */ + + /* helper fieldnames for accessing bridge widget */ + +#define xb_wid_id xb_widget.w_id +#define xb_wid_stat xb_widget.w_status +#define xb_wid_err_upper xb_widget.w_err_upper_addr +#define xb_wid_err_lower xb_widget.w_err_lower_addr +#define xb_wid_control xb_widget.w_control +#define xb_wid_req_timeout xb_widget.w_req_timeout +#define xb_wid_int_upper xb_widget.w_intdest_upper_addr +#define xb_wid_int_lower xb_widget.w_intdest_lower_addr +#define xb_wid_err_cmdword xb_widget.w_err_cmd_word +#define xb_wid_llp xb_widget.w_llp_cfg +#define xb_wid_stat_clr xb_widget.w_tflush + +/* * we access these through synergy unswizzled space, so the address * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) * That's why we put the register first and filler second. */ - /* xbow-specific widget configuration 0x000058-0x0000FF */ - uint32_t xb_wid_arb_reload; /* 0x00005C */ - uint32_t _pad_000058; - uint32_t xb_perf_ctr_a; /* 0x000064 */ - uint32_t _pad_000060; - uint32_t xb_perf_ctr_b; /* 0x00006c */ - uint32_t _pad_000068; - uint32_t xb_nic; /* 0x000074 */ - uint32_t _pad_000070; - - /* Xbridge only */ - uint32_t xb_w0_rst_fnc; /* 0x00007C */ - uint32_t _pad_000078; - uint32_t xb_l8_rst_fnc; /* 0x000084 */ - uint32_t _pad_000080; - uint32_t xb_l9_rst_fnc; /* 0x00008c */ - uint32_t _pad_000088; - uint32_t xb_la_rst_fnc; /* 0x000094 */ - uint32_t _pad_000090; - uint32_t xb_lb_rst_fnc; /* 0x00009c */ - uint32_t _pad_000098; - uint32_t xb_lc_rst_fnc; /* 0x0000a4 */ - uint32_t _pad_0000a0; - uint32_t xb_ld_rst_fnc; /* 0x0000ac */ - uint32_t _pad_0000a8; - uint32_t xb_le_rst_fnc; /* 0x0000b4 */ - uint32_t _pad_0000b0; - uint32_t xb_lf_rst_fnc; /* 0x0000bc */ - uint32_t _pad_0000b8; - uint32_t xb_lock; /* 0x0000c4 */ - uint32_t _pad_0000c0; - uint32_t xb_lock_clr; /* 0x0000cc */ - uint32_t _pad_0000c8; - /* end of Xbridge only */ - uint32_t _pad_0000d0[12]; - - /* Link Specific Registers, port 8..15 0x000100-0x000300 */ - xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; -#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] - + /* xbow-specific widget configuration 0x000058-0x0000FF */ + u32 xb_wid_arb_reload; /* 0x00005C */ + u32 _pad_000058; + u32 xb_perf_ctr_a; /* 0x000064 */ + u32 _pad_000060; + u32 xb_perf_ctr_b; /* 0x00006c */ + u32 _pad_000068; + u32 xb_nic; /* 0x000074 */ + u32 _pad_000070; + + /* Xbridge only */ + u32 xb_w0_rst_fnc; /* 0x00007C */ + u32 _pad_000078; + u32 xb_l8_rst_fnc; /* 0x000084 */ + u32 _pad_000080; + u32 xb_l9_rst_fnc; /* 0x00008c */ + u32 _pad_000088; + u32 xb_la_rst_fnc; /* 0x000094 */ + u32 _pad_000090; + u32 xb_lb_rst_fnc; /* 0x00009c */ + u32 _pad_000098; + u32 xb_lc_rst_fnc; /* 0x0000a4 */ + u32 _pad_0000a0; + u32 xb_ld_rst_fnc; /* 0x0000ac */ + u32 _pad_0000a8; + u32 xb_le_rst_fnc; /* 0x0000b4 */ + u32 _pad_0000b0; + u32 xb_lf_rst_fnc; /* 0x0000bc */ + u32 _pad_0000b8; + u32 xb_lock; /* 0x0000c4 */ + u32 _pad_0000c0; + u32 xb_lock_clr; /* 0x0000cc */ + u32 _pad_0000c8; + /* end of Xbridge only */ + u32 _pad_0000d0[12]; + + /* Link Specific Registers, port 8..15 0x000100-0x000300 */ + xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; } xbow_t; +#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] + #define XB_FLAGS_EXISTS 0x1 /* device exists */ #define XB_FLAGS_MASTER 0x2 #define XB_FLAGS_SLAVE 0x0 @@ -160,7 +161,7 @@ typedef volatile struct xbow_s { /* End of Xbridge only */ /* used only in ide, but defined here within the reserved portion */ -/* of the widget0 address space (before 0xf4) */ +/* of the widget0 address space (before 0xf4) */ #define XBOW_WID_UNDEF 0xe4 /* xbow link register set base, legal value for x is 0x8..0xf */ @@ -179,29 +180,37 @@ typedef volatile struct xbow_s { /* link_control(x) */ #define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */ - /* reserved: 0x40000000 */ +/* reserved: 0x40000000 */ #define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */ -#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer level */ -#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 bit mode */ -#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP packet */ -#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit mask */ -#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit shift */ -#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination */ -#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input buffer */ - /* reserved: 0x0000fe00 */ +#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer + level */ +#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 + bit mode */ +#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP + packet */ +#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit + mask */ +#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit + shift */ +#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination + */ +#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input + buffer */ +/* reserved: 0x0000fe00 */ #define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */ #define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */ #define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */ #define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */ #define XB_CTRL_RCV_IE 0x00000010 /* receive */ #define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */ - /* reserved: 0x00000004 */ -#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request timeout */ +/* reserved: 0x00000004 */ +#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request + timeout */ #define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */ /* link_status(x) */ #define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE - /* reserved: 0x7ff80000 */ +/* reserved: 0x7ff80000 */ #define XB_STAT_MULTI_ERR 0x00040000 /* multi error */ #define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE #define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE @@ -211,7 +220,7 @@ typedef volatile struct xbow_s { #define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE #define XB_STAT_RCV_ERR XB_CTRL_RCV_IE #define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE - /* reserved: 0x00000004 */ +/* reserved: 0x00000004 */ #define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE #define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE @@ -222,7 +231,7 @@ typedef volatile struct xbow_s { #define XB_AUX_LINKFAIL_RST_BAD 0x00000040 #define XB_AUX_STAT_PRESENT 0x00000020 #define XB_AUX_STAT_PORT_WIDTH 0x00000010 - /* reserved: 0x0000000f */ +/* reserved: 0x0000000f */ /* * link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper @@ -238,7 +247,8 @@ typedef volatile struct xbow_s { /* XBOW_WID_STAT */ #define XB_WID_STAT_LINK_INTR_SHFT (24) #define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT) -#define XB_WID_STAT_LINK_INTR(x) (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) +#define XB_WID_STAT_LINK_INTR(x) \ + (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) #define XB_WID_STAT_WIDGET0_INTR 0x00800000 #define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */ #define XB_WID_STAT_REG_ACC_ERR 0x00000020 @@ -264,7 +274,7 @@ typedef volatile struct xbow_s { #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ #define XBOW_WIDGET_MFGR_NUM 0x0 #define XXBOW_WIDGET_MFGR_NUM 0x0 -#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ +#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ #define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */ #define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */ @@ -279,13 +289,13 @@ typedef volatile struct xbow_s { #define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */ #define IS_XBRIDGE_XBOW(wid) \ - (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ - XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) + (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ + XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) #define IS_PIC_XBOW(wid) \ - (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ - XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) + (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ + XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) #define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv) -#endif /* _ASM_IA64_SN_XTALK_XBOW_H */ +#endif /* _ASM_IA64_SN_XTALK_XBOW_H */ diff --git a/arch/ia64/sn/include/xtalk/xwidgetdev.h b/arch/ia64/sn/include/xtalk/xwidgetdev.h index c5f4bc5cc03..2800eda0fd6 100644 --- a/arch/ia64/sn/include/xtalk/xwidgetdev.h +++ b/arch/ia64/sn/include/xtalk/xwidgetdev.h @@ -25,28 +25,28 @@ /* widget configuration registers */ struct widget_cfg{ - uint32_t w_id; /* 0x04 */ - uint32_t w_pad_0; /* 0x00 */ - uint32_t w_status; /* 0x0c */ - uint32_t w_pad_1; /* 0x08 */ - uint32_t w_err_upper_addr; /* 0x14 */ - uint32_t w_pad_2; /* 0x10 */ - uint32_t w_err_lower_addr; /* 0x1c */ - uint32_t w_pad_3; /* 0x18 */ - uint32_t w_control; /* 0x24 */ - uint32_t w_pad_4; /* 0x20 */ - uint32_t w_req_timeout; /* 0x2c */ - uint32_t w_pad_5; /* 0x28 */ - uint32_t w_intdest_upper_addr; /* 0x34 */ - uint32_t w_pad_6; /* 0x30 */ - uint32_t w_intdest_lower_addr; /* 0x3c */ - uint32_t w_pad_7; /* 0x38 */ - uint32_t w_err_cmd_word; /* 0x44 */ - uint32_t w_pad_8; /* 0x40 */ - uint32_t w_llp_cfg; /* 0x4c */ - uint32_t w_pad_9; /* 0x48 */ - uint32_t w_tflush; /* 0x54 */ - uint32_t w_pad_10; /* 0x50 */ + u32 w_id; /* 0x04 */ + u32 w_pad_0; /* 0x00 */ + u32 w_status; /* 0x0c */ + u32 w_pad_1; /* 0x08 */ + u32 w_err_upper_addr; /* 0x14 */ + u32 w_pad_2; /* 0x10 */ + u32 w_err_lower_addr; /* 0x1c */ + u32 w_pad_3; /* 0x18 */ + u32 w_control; /* 0x24 */ + u32 w_pad_4; /* 0x20 */ + u32 w_req_timeout; /* 0x2c */ + u32 w_pad_5; /* 0x28 */ + u32 w_intdest_upper_addr; /* 0x34 */ + u32 w_pad_6; /* 0x30 */ + u32 w_intdest_lower_addr; /* 0x3c */ + u32 w_pad_7; /* 0x38 */ + u32 w_err_cmd_word; /* 0x44 */ + u32 w_pad_8; /* 0x40 */ + u32 w_llp_cfg; /* 0x4c */ + u32 w_pad_9; /* 0x48 */ + u32 w_tflush; /* 0x54 */ + u32 w_pad_10; /* 0x50 */ }; /* @@ -63,7 +63,7 @@ struct xwidget_info{ struct xwidget_hwid xwi_hwid; /* Widget Identification */ char xwi_masterxid; /* Hub's Widget Port Number */ void *xwi_hubinfo; /* Hub's provider private info */ - uint64_t *xwi_hub_provider; /* prom provider functions */ + u64 *xwi_hub_provider; /* prom provider functions */ void *xwi_vertex; }; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 258d9d7aff9..233d55115d3 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -132,8 +132,8 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) * Retrieve the pci device information given the bus and device|function number. */ static inline u64 -sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, - u64 sn_irq_info) +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, + u64 sn_irq_info) { struct ia64_sal_retval ret_stuff; ret_stuff.status = 0; @@ -141,7 +141,7 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, - (u64) segment, (u64) bus_number, (u64) devfn, + (u64) segment, (u64) bus_number, (u64) devfn, (u64) pci_dev, sn_irq_info, 0, 0); return ret_stuff.v0; @@ -268,7 +268,7 @@ static void sn_fixup_ionodes(void) */ static void sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, - int64_t * pci_addrs) + s64 * pci_addrs) { struct pci_controller *controller = PCI_CONTROLLER(dev->bus); unsigned int i; @@ -328,7 +328,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev) struct pci_bus *host_pci_bus; struct pci_dev *host_pci_dev; struct pcidev_info *pcidev_info; - int64_t pci_addrs[PCI_ROM_RESOURCE + 1]; + s64 pci_addrs[PCI_ROM_RESOURCE + 1]; struct sn_irq_info *sn_irq_info; unsigned long size; unsigned int bus_no, devfn; diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 01d18b7b5bb..ec37084bdc1 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -28,7 +28,7 @@ extern int sn_ioif_inited; static struct list_head **sn_irq_lh; static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ -static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget, +static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, u64 sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) @@ -123,7 +123,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, sn_irq_lh[irq], list) { - uint64_t bridge; + u64 bridge; int local_widget, status; nasid_t local_nasid; struct sn_irq_info *new_irq_info; @@ -134,7 +134,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) break; memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); - bridge = (uint64_t) new_irq_info->irq_bridge; + bridge = (u64) new_irq_info->irq_bridge; if (!bridge) { kfree(new_irq_info); break; /* irq is not a device interrupt */ @@ -349,10 +349,10 @@ static void force_interrupt(int irq) */ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) { - uint64_t regval; + u64 regval; int irr_reg_num; int irr_bit; - uint64_t irr_reg; + u64 irr_reg; struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 6a7939b16a1..d263d3e8fbb 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -245,7 +245,7 @@ static int cx_device_reload(struct cx_dev *cx_dev) cx_dev->bt); } -static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget, +static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget, u64 sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) @@ -302,7 +302,7 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq, void tiocx_irq_free(struct sn_irq_info *sn_irq_info) { - uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; + u64 bridge = (u64) sn_irq_info->irq_bridge; nasid_t nasid = NASID_GET(bridge); int widget; @@ -313,12 +313,12 @@ void tiocx_irq_free(struct sn_irq_info *sn_irq_info) } } -uint64_t tiocx_dma_addr(uint64_t addr) +u64 tiocx_dma_addr(u64 addr) { return PHYS_TO_TIODMA(addr); } -uint64_t tiocx_swin_base(int nasid) +u64 tiocx_swin_base(int nasid) { return TIO_SWIN_BASE(nasid, TIOCX_CORELET); } @@ -335,8 +335,8 @@ EXPORT_SYMBOL(tiocx_swin_base); static void tio_conveyor_set(nasid_t nasid, int enable_flag) { - uint64_t ice_frz; - uint64_t disable_cb = (1ull << 61); + u64 ice_frz; + u64 disable_cb = (1ull << 61); if (!(nasid & 1)) return; @@ -388,7 +388,7 @@ static int is_fpga_tio(int nasid, int *bt) static int bitstream_loaded(nasid_t nasid) { - uint64_t cx_credits; + u64 cx_credits; cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3); cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK; @@ -404,14 +404,14 @@ static int tiocx_reload(struct cx_dev *cx_dev) nasid_t nasid = cx_dev->cx_id.nasid; if (bitstream_loaded(nasid)) { - uint64_t cx_id; + u64 cx_id; int rv; rv = ia64_sn_sysctl_tio_clock_reset(nasid); if (rv) { printk(KERN_ALERT "CX port JTAG reset failed.\n"); } else { - cx_id = *(volatile uint64_t *) + cx_id = *(volatile u64 *) (TIO_SWIN_BASE(nasid, TIOCX_CORELET) + WIDGET_ID); part_num = XWIDGET_PART_NUM(cx_id); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index d1647b863e6..aa3fa5152a3 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c @@ -18,10 +18,10 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ * mark_ate: Mark the ate as either free or inuse. */ static void mark_ate(struct ate_resource *ate_resource, int start, int number, - uint64_t value) + u64 value) { - uint64_t *ate = ate_resource->ate; + u64 *ate = ate_resource->ate; int index; int length = 0; @@ -38,7 +38,7 @@ static int find_free_ate(struct ate_resource *ate_resource, int start, int count) { - uint64_t *ate = ate_resource->ate; + u64 *ate = ate_resource->ate; int index; int start_free; @@ -119,7 +119,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) { int status = 0; - uint64_t flag; + u64 flag; flag = pcibr_lock(pcibus_info); status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); @@ -139,7 +139,7 @@ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) * Setup an Address Translation Entry as specified. Use either the Bridge * internal maps or the external map RAM, as appropriate. */ -static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, +static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { if (ate_index < pcibus_info->pbi_int_ate_size) { @@ -153,7 +153,7 @@ static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, */ void inline ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, - volatile uint64_t ate) + volatile u64 ate) { while (count-- > 0) { if (ate_index < pcibus_info->pbi_int_ate_size) { @@ -171,9 +171,9 @@ ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) { - volatile uint64_t ate; + volatile u64 ate; int count; - uint64_t flags; + u64 flags; if (pcibr_invalidate_ate) { /* For debugging purposes, clear the valid bit in the ATE */ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index e68332d9317..54ce5b7ceed 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -41,21 +41,21 @@ extern int sn_ioif_inited; static dma_addr_t pcibr_dmamap_ate32(struct pcidev_info *info, - uint64_t paddr, size_t req_size, uint64_t flags) + u64 paddr, size_t req_size, u64 flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; - uint8_t internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> + u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> pdi_linux_pcidev->devfn)) - 1; int ate_count; int ate_index; - uint64_t ate_flags = flags | PCI32_ATE_V; - uint64_t ate; - uint64_t pci_addr; - uint64_t xio_addr; - uint64_t offset; + u64 ate_flags = flags | PCI32_ATE_V; + u64 ate; + u64 pci_addr; + u64 xio_addr; + u64 offset; /* PIC in PCI-X mode does not supports 32bit PageMap mode */ if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) { @@ -109,12 +109,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info, } static dma_addr_t -pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, - uint64_t dma_attributes) +pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, + u64 dma_attributes) { struct pcibus_info *pcibus_info = (struct pcibus_info *) ((info->pdi_host_pcidev_info)->pdi_pcibus_info); - uint64_t pci_addr; + u64 pci_addr; /* Translate to Crosstalk View of Physical Address */ pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : @@ -127,7 +127,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, /* Handle Bridge Chipset differences */ if (IS_PIC_SOFT(pcibus_info)) { pci_addr |= - ((uint64_t) pcibus_info-> + ((u64) pcibus_info-> pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); } else pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; @@ -142,17 +142,17 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, static dma_addr_t pcibr_dmatrans_direct32(struct pcidev_info * info, - uint64_t paddr, size_t req_size, uint64_t flags) + u64 paddr, size_t req_size, u64 flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; - uint64_t xio_addr; + u64 xio_addr; - uint64_t xio_base; - uint64_t offset; - uint64_t endoff; + u64 xio_base; + u64 offset; + u64 endoff; if (IS_PCIX(pcibus_info)) { return 0; @@ -209,14 +209,14 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction) * unlike the PIC Device(x) Write Request Buffer Flush register. */ -void sn_dma_flush(uint64_t addr) +void sn_dma_flush(u64 addr) { nasid_t nasid; int is_tio; int wid_num; int i, j; - uint64_t flags; - uint64_t itte; + u64 flags; + u64 itte; struct hubdev_info *hubinfo; volatile struct sn_flush_device_kernel *p; volatile struct sn_flush_device_common *common; @@ -299,8 +299,8 @@ void sn_dma_flush(uint64_t addr) * If CE ever needs the sn_dma_flush mechanism, we will have * to account for that here and in tioce_bus_fixup(). */ - uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); - uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id); + u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); + u32 revnum = XWIDGET_PART_REV_NUM(tio_id); /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { @@ -315,7 +315,7 @@ void sn_dma_flush(uint64_t addr) *common->sfdl_flush_addr = 0; /* force an interrupt. */ - *(volatile uint32_t *)(common->sfdl_force_int_addr) = 1; + *(volatile u32 *)(common->sfdl_force_int_addr) = 1; /* wait for the interrupt to come back. */ while (*(common->sfdl_flush_addr) != 0x10f) diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index e328e948175..77a1262751d 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -23,7 +23,7 @@ int sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -40,7 +40,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, void *resp) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -56,7 +56,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, static int sal_pcibr_error_interrupt(struct pcibus_info *soft) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; int segment; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -159,9 +159,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = - kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL); + kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); memset(soft->pbi_int_ate_resource.ate, 0, - (soft->pbi_int_ate_size * sizeof(uint64_t))); + (soft->pbi_int_ate_size * sizeof(u64))); if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { /* TIO PCI Bridge: find nearest node with CPUs */ @@ -203,7 +203,7 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; int bit = sn_irq_info->irq_int_bit; - uint64_t xtalk_addr = sn_irq_info->irq_xtalkaddr; + u64 xtalk_addr = sn_irq_info->irq_xtalkaddr; pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (pcidev_info) { diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 79fdb91d725..8b8bbd51d43 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c @@ -23,7 +23,7 @@ union br_ptr { /* * Control Register Access -- Read/Write 0000_0020 */ -void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -43,7 +43,7 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) } } -void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -66,10 +66,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) /* * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050 */ -uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) +u64 pcireg_tflush_get(struct pcibus_info *pcibus_info) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -96,10 +96,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) /* * Interrupt Status Register Access -- Read Only 0000_0100 */ -uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) +u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -121,7 +121,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) /* * Interrupt Enable Register Access -- Read/Write 0000_0108 */ -void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -141,7 +141,7 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) } } -void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -165,7 +165,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168 */ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, - uint64_t addr) + u64 addr) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -217,10 +217,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) /* * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258 */ -uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) +u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -242,7 +242,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) } void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, - uint64_t val) + u64 val) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -262,10 +262,10 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, } } -uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) +u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t __iomem *ret = NULL; + u64 __iomem *ret = NULL; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 27aa1842dac..7571a402552 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -16,7 +16,7 @@ #include <asm/sn/pcibus_provider_defs.h> #include <asm/sn/tioca_provider.h> -uint32_t tioca_gart_found; +u32 tioca_gart_found; EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */ LIST_HEAD(tioca_list); @@ -34,8 +34,8 @@ static int tioca_gart_init(struct tioca_kernel *); static int tioca_gart_init(struct tioca_kernel *tioca_kern) { - uint64_t ap_reg; - uint64_t offset; + u64 ap_reg; + u64 offset; struct page *tmp; struct tioca_common *tioca_common; struct tioca __iomem *ca_base; @@ -214,7 +214,7 @@ void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) { int cap_ptr; - uint32_t reg; + u32 reg; struct tioca __iomem *tioca_base; struct pci_dev *pdev; struct tioca_common *common; @@ -276,7 +276,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */ * We will always use 0x1 * 55:55 - Swap bytes Currently unused */ -static uint64_t +static u64 tioca_dma_d64(unsigned long paddr) { dma_addr_t bus_addr; @@ -318,15 +318,15 @@ tioca_dma_d64(unsigned long paddr) * and so a given CA can only directly target nodes in the range * xxx - xxx+255. */ -static uint64_t -tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) +static u64 +tioca_dma_d48(struct pci_dev *pdev, u64 paddr) { struct tioca_common *tioca_common; struct tioca __iomem *ca_base; - uint64_t ct_addr; + u64 ct_addr; dma_addr_t bus_addr; - uint32_t node_upper; - uint64_t agp_dma_extn; + u32 node_upper; + u64 agp_dma_extn; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; @@ -367,10 +367,10 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) * dma_addr_t is guarenteed to be contiguous in CA bus space. */ static dma_addr_t -tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size) +tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) { int i, ps, ps_shift, entry, entries, mapsize, last_entry; - uint64_t xio_addr, end_xio_addr; + u64 xio_addr, end_xio_addr; struct tioca_common *tioca_common; struct tioca_kernel *tioca_kern; dma_addr_t bus_addr = 0; @@ -514,10 +514,10 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * The mapping mode used is based on the devices dma_mask. As a last resort * use the GART mapped mode. */ -static uint64_t -tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +static u64 +tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) { - uint64_t mapaddr; + u64 mapaddr; /* * If card is 64 or 48 bit addresable, use a direct mapping. 32 @@ -554,8 +554,8 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) { struct tioca_common *soft = arg; struct ia64_sal_retval ret_stuff; - uint64_t segment; - uint64_t busnum; + u64 segment; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -620,7 +620,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont INIT_LIST_HEAD(&tioca_kern->ca_dmamaps); tioca_kern->ca_closest_node = nasid_to_cnodeid(tioca_common->ca_closest_nasid); - tioca_common->ca_kernel_private = (uint64_t) tioca_kern; + tioca_common->ca_kernel_private = (u64) tioca_kern; bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment, tioca_common->ca_common.bs_persist_busnum); diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index dda196c9e32..e52831ed93e 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -81,10 +81,10 @@ * 61 - 0 since this is not an MSI transaction * 60:54 - reserved, MBZ */ -static uint64_t +static u64 tioce_dma_d64(unsigned long ct_addr) { - uint64_t bus_addr; + u64 bus_addr; bus_addr = ct_addr | (1UL << 63); @@ -141,9 +141,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, * length, and if enough resources exist, fill in the ATE's and construct a * tioce_dmamap struct to track the mapping. */ -static uint64_t +static u64 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, - uint64_t ct_addr, int len) + u64 ct_addr, int len) { int i; int j; @@ -152,11 +152,11 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, int entries; int nates; int pagesize; - uint64_t *ate_shadow; - uint64_t *ate_reg; - uint64_t addr; + u64 *ate_shadow; + u64 *ate_reg; + u64 addr; struct tioce *ce_mmr; - uint64_t bus_base; + u64 bus_base; struct tioce_dmamap *map; ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; @@ -224,7 +224,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, addr = ct_addr; for (j = 0; j < nates; j++) { - uint64_t ate; + u64 ate; ate = ATE_MAKE(addr, pagesize); ate_shadow[i + j] = ate; @@ -252,15 +252,15 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, * * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. */ -static uint64_t -tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) +static u64 +tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) { int dma_ok; int port; struct tioce *ce_mmr; struct tioce_kernel *ce_kern; - uint64_t ct_upper; - uint64_t ct_lower; + u64 ct_upper; + u64 ct_lower; dma_addr_t bus_addr; ct_upper = ct_addr & ~0x3fffffffUL; @@ -269,7 +269,7 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); if (ce_kern->ce_port[port].dirmap_refcnt == 0) { - uint64_t tmp; + u64 tmp; ce_kern->ce_port[port].dirmap_shadow = ct_upper; writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); @@ -295,10 +295,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) * Given a TIOCE bus address, set the appropriate bit to indicate barrier * attributes. */ -static uint64_t -tioce_dma_barrier(uint64_t bus_addr, int on) +static u64 +tioce_dma_barrier(u64 bus_addr, int on) { - uint64_t barrier_bit; + u64 barrier_bit; /* barrier not supported in M40/M40S mode */ if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr)) @@ -351,7 +351,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { - uint64_t last; + u64 last; last = map->pci_start + map->nbytes - 1; if (bus_addr >= map->pci_start && bus_addr <= last) @@ -385,17 +385,17 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * This is the main wrapper for mapping host physical pages to CE PCI space. * The mapping mode used is based on the device's dma_mask. */ -static uint64_t -tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, +static u64 +tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int barrier) { unsigned long flags; - uint64_t ct_addr; - uint64_t mapaddr = 0; + u64 ct_addr; + u64 mapaddr = 0; struct tioce_kernel *ce_kern; struct tioce_dmamap *map; int port; - uint64_t dma_mask; + u64 dma_mask; dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask; @@ -425,7 +425,7 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, * address bits than this device can support. */ list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { - uint64_t last; + u64 last; last = map->ct_start + map->nbytes - 1; if (ct_addr >= map->ct_start && @@ -501,8 +501,8 @@ dma_map_done: * Simply call tioce_do_dma_map() to create a map with the barrier bit clear * in the address. */ -static uint64_t -tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +static u64 +tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) { return tioce_do_dma_map(pdev, paddr, byte_count, 0); } @@ -515,8 +515,8 @@ tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) * * Simply call tioce_do_dma_map() to create a map with the barrier bit set * in the address. - */ static uint64_t -tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) + */ static u64 +tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) { return tioce_do_dma_map(pdev, paddr, byte_count, 1); } @@ -551,7 +551,7 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) tioce_kern_init(struct tioce_common *tioce_common) { int i; - uint32_t tmp; + u32 tmp; struct tioce *tioce_mmr; struct tioce_kernel *tioce_kern; @@ -563,7 +563,7 @@ tioce_kern_init(struct tioce_common *tioce_common) tioce_kern->ce_common = tioce_common; spin_lock_init(&tioce_kern->ce_lock); INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list); - tioce_common->ce_kernel_private = (uint64_t) tioce_kern; + tioce_common->ce_kernel_private = (u64) tioce_kern; /* * Determine the secondary bus number of the port2 logical PPB. @@ -575,7 +575,7 @@ tioce_kern_init(struct tioce_common *tioce_common) raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, tioce_common->ce_pcibus.bs_persist_busnum, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); - tioce_kern->ce_port1_secondary = (uint8_t) tmp; + tioce_kern->ce_port1_secondary = (u8) tmp; /* * Set PMU pagesize to the largest size available, and zero out @@ -615,7 +615,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct tioce_common *ce_common; struct tioce *ce_mmr; - uint64_t force_int_val; + u64 force_int_val; if (!sn_irq_info->irq_bridge) return; @@ -687,7 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) struct tioce_common *ce_common; struct tioce *ce_mmr; int bit; - uint64_t vector; + u64 vector; pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (!pcidev_info) @@ -699,7 +699,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) bit = sn_irq_info->irq_int_bit; __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); - vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; + vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; vector |= sn_irq_info->irq_xtalkaddr; writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index ae2ba67b7ef..5e37df3111a 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -12,6 +12,9 @@ #include <linux/reboot.h> #include <asm/reboot.h> +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + /* * Urgs ... Too many MIPS machines to handle this in a generic way. * So handle all using function pointers to machine specific @@ -33,6 +36,9 @@ void machine_halt(void) void machine_power_off(void) { + if (pm_power_off) + pm_power_off(); + _machine_power_off(); } diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8cf6d437a63..01bc7d589af 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -33,9 +33,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_IOMAP + bool + config ARCH_MAY_HAVE_PC_FDC bool - default y source "init/Kconfig" @@ -53,24 +55,28 @@ config SH_SOLUTION_ENGINE config SH_7751_SOLUTION_ENGINE bool "SolutionEngine7751" + select CPU_SUBTYPE_SH7751 help Select 7751 SolutionEngine if configuring for a Hitachi SH7751 evaluation board. config SH_7300_SOLUTION_ENGINE bool "SolutionEngine7300" + select CPU_SUBTYPE_SH7300 help Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V) evaluation board. config SH_73180_SOLUTION_ENGINE bool "SolutionEngine73180" + select CPU_SUBTYPE_SH73180 help Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3) evaluation board. config SH_7751_SYSTEMH bool "SystemH7751R" + select CPU_SUBTYPE_SH7751R help Select SystemH if you are configuring for a Renesas SystemH 7751R evaluation board. @@ -81,27 +87,13 @@ config SH_STB1_HARP config SH_STB1_OVERDRIVE bool "STB1_Overdrive" -config SH_HP620 - bool "HP620" +config SH_HP6XX + bool "HP6XX" help - Select HP620 if configuring for a HP jornada HP620. + Select HP6XX if configuring for a HP jornada HP6xx. More information (hardware only) at <http://www.hp.com/jornada/>. -config SH_HP680 - bool "HP680" - help - Select HP680 if configuring for a HP Jornada HP680. - More information (hardware only) at - <http://www.hp.com/jornada/products/680/>. - -config SH_HP690 - bool "HP690" - help - Select HP690 if configuring for a HP Jornada HP690. - More information (hardware only) - at <http://www.hp.com/jornada/products/680/>. - config SH_CQREEK bool "CqREEK" help @@ -123,11 +115,13 @@ config SH_EC3104 config SH_SATURN bool "Saturn" + select CPU_SUBTYPE_SH7604 help Select Saturn if configuring for a SEGA Saturn. config SH_DREAMCAST bool "Dreamcast" + select CPU_SUBTYPE_SH7091 help Select Dreamcast if configuring for a SEGA Dreamcast. More information at @@ -142,6 +136,7 @@ config SH_BIGSUR config SH_SH2000 bool "SH2000" + select CPU_SUBTYPE_SH7709 help SH-2000 is a single-board computer based around SH7709A chip intended for embedded applications. @@ -153,20 +148,22 @@ config SH_ADX bool "ADX" config SH_MPC1211 - bool "MPC1211" + bool "Interface MPC1211" + help + CTP/PCI-SH02 is a CPU module computer that is produced + by Interface Corporation. + More information at <http://www.interface.co.jp> config SH_SH03 - bool "SH03" + bool "Interface CTP/PCI-SH03" help - CTP/PCI-SH03 is a CPU module computer that produced + CTP/PCI-SH03 is a CPU module computer that is produced by Interface Corporation. - It is compact and excellent in durability. - It will play an active part in your factory or laboratory - as a FA computer. More information at <http://www.interface.co.jp> config SH_SECUREEDGE5410 bool "SecureEdge5410" + select CPU_SUBTYPE_SH7751R help Select SecureEdge5410 if configuring for a SnapGear SH board. This includes both the OEM SecureEdge products as well as the @@ -174,25 +171,49 @@ config SH_SECUREEDGE5410 config SH_HS7751RVOIP bool "HS7751RVOIP" + select CPU_SUBTYPE_SH7751R help Select HS7751RVOIP if configuring for a Renesas Technology Sales VoIP board. config SH_RTS7751R2D bool "RTS7751R2D" + select CPU_SUBTYPE_SH7751R help Select RTS7751R2D if configuring for a Renesas Technology Sales SH-Graphics board. +config SH_R7780RP + bool "R7780RP-1" + select CPU_SUBTYPE_SH7780 + help + Select R7780RP-1 if configuring for a Renesas Solutions + HIGHLANDER board. + config SH_EDOSK7705 bool "EDOSK7705" + select CPU_SUBTYPE_SH7705 config SH_SH4202_MICRODEV bool "SH4-202 MicroDev" + select CPU_SUBTYPE_SH4_202 help Select SH4-202 MicroDev if configuring for a SuperH MicroDev board with an SH4-202 CPU. +config SH_LANDISK + bool "LANDISK" + select CPU_SUBTYPE_SH7751R + help + I-O DATA DEVICE, INC. "LANDISK Series" support. + +config SH_TITAN + bool "TITAN" + select CPU_SUBTYPE_SH7751R + help + Select Titan if you are configuring for a Nimble Microsystems + NetEngine NP51R. + config SH_UNKNOWN bool "BareCPU" help @@ -207,168 +228,27 @@ config SH_UNKNOWN endchoice -choice - prompt "Processor family" - default CPU_SH4 - help - This option determines the CPU family to compile for. Supported - targets are SH-2, SH-3, and SH-4. These options are independent of - CPU functionality. As such, SH-DSP users will still want to select - their respective processor family in addition to the DSP support - option. - -config CPU_SH2 - bool "SH-2" - select SH_WRITETHROUGH - -config CPU_SH3 - bool "SH-3" - -config CPU_SH4 - bool "SH-4" - -endchoice - -choice - prompt "Processor subtype" - -config CPU_SUBTYPE_SH7604 - bool "SH7604" - depends on CPU_SH2 - help - Select SH7604 if you have SH7604 - -config CPU_SUBTYPE_SH7300 - bool "SH7300" - depends on CPU_SH3 - -config CPU_SUBTYPE_SH7705 - bool "SH7705" - depends on CPU_SH3 - -config CPU_SUBTYPE_SH7707 - bool "SH7707" - depends on CPU_SH3 - help - Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. - -config CPU_SUBTYPE_SH7708 - bool "SH7708" - depends on CPU_SH3 - help - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - -config CPU_SUBTYPE_SH7709 - bool "SH7709" - depends on CPU_SH3 - help - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - -config CPU_SUBTYPE_SH7750 - bool "SH7750" - depends on CPU_SH4 - help - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - -config CPU_SUBTYPE_SH7751 - bool "SH7751/SH7751R" - depends on CPU_SH4 - help - Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, - or if you have a HD6417751R CPU. - -config CPU_SUBTYPE_SH7760 - bool "SH7760" - depends on CPU_SH4 - -config CPU_SUBTYPE_SH73180 - bool "SH73180" - depends on CPU_SH4 - -config CPU_SUBTYPE_ST40STB1 - bool "ST40STB1 / ST40RA" - depends on CPU_SH4 - help - Select ST40STB1 if you have a ST40RA CPU. - This was previously called the ST40STB1, hence the option name. - -config CPU_SUBTYPE_ST40GX1 - bool "ST40GX1" - depends on CPU_SH4 - help - Select ST40GX1 if you have a ST40GX1 CPU. - -config CPU_SUBTYPE_SH4_202 - bool "SH4-202" - depends on CPU_SH4 - -endchoice - -config SH7705_CACHE_32KB - bool "Enable 32KB cache size for SH7705" - depends on CPU_SUBTYPE_SH7705 - default y - -config MMU - bool "Support for memory management hardware" - depends on !CPU_SH2 - default y - help - Early SH processors (such as the SH7604) lack an MMU. In order to - boot on these systems, this option must not be set. - - On other systems (such as the SH-3 and 4) where an MMU exists, - turning this off will boot the kernel on these machines with the - MMU implicitly switched off. - -choice - prompt "HugeTLB page size" - depends on HUGETLB_PAGE && CPU_SH4 && MMU - default HUGETLB_PAGE_SIZE_64K - -config HUGETLB_PAGE_SIZE_64K - bool "64K" - -config HUGETLB_PAGE_SIZE_1MB - bool "1MB" - -endchoice - -config CMDLINE_BOOL - bool "Default bootloader kernel arguments" - -config CMDLINE - string "Initial kernel command string" - depends on CMDLINE_BOOL - default "console=ttySC1,115200" +source "arch/sh/mm/Kconfig" -# Platform-specific memory start and size definitions config MEMORY_START - hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV - default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705) + hex "Physical memory start address" + default "0x08000000" ---help--- Computers built with Hitachi SuperH processors always map the ROM starting at address zero. But the processor does not specify the range that RAM takes. The physical memory (RAM) start address will be automatically - set to 08000000, unless you selected one of the following - processor types: SolutionEngine, Overdrive, HP620, HP680, HP690, - in which case the start address will be set to 0c000000. + set to 08000000. Other platforms, such as the Solution Engine + boards typically map RAM at 0C000000. - Tweak this only when porting to a new machine which is not already - known by the config system. Changing it from the known correct + Tweak this only when porting to a new machine which does not + already have a defconfig. Changing it from the known correct value on any of the known systems will only lead to disaster. config MEMORY_SIZE - hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) - default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705 - default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) - default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV) - default "0x08000000" if SH_MPC1211 || SH_SH03 + hex "Physical memory size" + default "0x00400000" help This sets the default memory size assumed by your SH kernel. It can be overridden as normal by the 'mem=' argument on the kernel command @@ -376,21 +256,6 @@ config MEMORY_SIZE as 0x00400000 which was the default value before this became configurable. -config MEMORY_SET - bool - depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705) - default y - help - This is an option about which you will never be asked a question. - Therefore, I conclude that you do not exist - go away. - - There is a grue here. - -# If none of the above have set memory start/size, ask the user. -config MEMORY_OVERRIDE - bool "Override default load address and memory size" - -# XXX: break these out into the board-specific configs below config CF_ENABLER bool "Compact Flash Enabler support" depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03 @@ -434,10 +299,21 @@ config CF_BASE_ADDR default "0xb8000000" if CF_AREA6 default "0xb4000000" if CF_AREA5 +menu "Processor features" + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + help + Some SuperH machines can be configured for either little or big + endian byte order. These modes require different kernels. Say Y if + your machine is little endian, N if it's a big endian machine. + # The SH7750 RTC module is disabled in the Dreamcast config SH_RTC bool - depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE + depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \ + !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \ + !SH_R7780RP default y help Selecting this option will allow the Linux kernel to emulate @@ -476,104 +352,131 @@ config SH_ADC If unsure, say N. -config SH_HP600 +config SH_STORE_QUEUES + bool "Support for Store Queues" + depends on CPU_SH4 + help + Selecting this option will enable an in-kernel API for manipulating + the store queues integrated in the SH-4 processors. + +config CPU_HAS_INTEVT bool - depends on SH_HP620 || SH_HP680 || SH_HP690 - default y -config CPU_SUBTYPE_ST40 - bool - depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1 - default y +config CPU_HAS_PINT_IRQ + bool -source "mm/Kconfig" +config CPU_HAS_INTC2_IRQ + bool -config ZERO_PAGE_OFFSET - hex "Zero page offset" - default "0x00001000" if !(SH_MPC1211 || SH_SH03) - default "0x00004000" if SH_MPC1211 || SH_SH03 +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 + default y help - This sets the default offset of zero page. + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. -# XXX: needs to lose subtype for system type -config ST40_LMI_MEMORY - bool "Memory on LMI" - depends on CPU_SUBTYPE_ST40STB1 + See <file:Documentation/sh/register-banks.txt> for further + information on SR.RB and register banking in the kernel in general. -config MEMORY_START - hex - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0x08000000" +endmenu -config MEMORY_SIZE - hex - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0x00400000" +menu "Timer support" -config MEMORY_SET - bool - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY +config SH_TMU + bool "TMU timer support" default y - -config BOOT_LINK_OFFSET - hex "Link address offset for booting" - default "0x00800000" help - This option allows you to set the link address offset of the zImage. - This can be useful if you are on a board which has a small amount of - memory. + This enables the use of the TMU as the system timer. -config CPU_LITTLE_ENDIAN - bool "Little Endian" - help - Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. Say Y if - your machine is little endian, N if it's a big endian machine. +endmenu -config PREEMPT - bool "Preemptible Kernel (EXPERIMENTAL)" - depends on EXPERIMENTAL +source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" -config UBC_WAKEUP - bool "Wakeup UBC on startup" +source "arch/sh/boards/renesas/rts7751r2d/Kconfig" + +config SH_PCLK_FREQ_BOOL + bool "Set default pclk frequency" + default y if !SH_RTC + default n + +config SH_PCLK_FREQ + int "Peripheral clock frequency (in Hz)" + depends on SH_PCLK_FREQ_BOOL + default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 + default "60000000" if CPU_SUBTYPE_SH7751 + default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760 + default "27000000" if CPU_SUBTYPE_SH73180 + default "66000000" if CPU_SUBTYPE_SH4_202 help - Selecting this option will wakeup the User Break Controller (UBC) on - startup. Although the UBC is left in an awake state when the processor - comes up, some boot loaders misbehave by putting the UBC to sleep in a - power saving state, which causes issues with things like ptrace(). + This option is used to specify the peripheral clock frequency. + This is necessary for determining the reference clock value on + platforms lacking an RTC. - If unsure, say N. +menu "CPU Frequency scaling" + +source "drivers/cpufreq/Kconfig" -config SH_WRITETHROUGH - bool "Use write-through caching" - default y if CPU_SH2 +config SH_CPU_FREQ + tristate "SuperH CPU Frequency driver" + depends on CPU_FREQ + select CPU_FREQ_TABLE help - Selecting this option will configure the caches in write-through - mode, as opposed to the default write-back configuration. + This adds the cpufreq driver for SuperH. At present, only + the SH-4 is supported. - Since there's sill some aliasing issues on SH-4, this option will - unfortunately still require the majority of flushing functions to - be implemented to deal with aliasing. + For details, take a look at <file:Documentation/cpu-freq>. If unsure, say N. -config SH_OCRAM - bool "Operand Cache RAM (OCRAM) support" +endmenu + +source "arch/sh/drivers/dma/Kconfig" + +source "arch/sh/cchips/Kconfig" + +config HEARTBEAT + bool "Heartbeat LED" + depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \ + SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \ + SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \ + SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \ + SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK help - Selecting this option will automatically tear down the number of - sets in the dcache by half, which in turn exposes a memory range. + Use the power-on LED on your machine as a load meter. The exact + behavior is platform-dependent, but normally the flash frequency is + a hyperbolic function of the 5-minute load average. - The addresses for the OC RAM base will vary according to the - processor version. Consult vendor documentation for specifics. +endmenu - If unsure, say N. +config ISA_DMA_API + bool + depends on MPC1211 + default y -config SH_STORE_QUEUES - bool "Support for Store Queues" - depends on CPU_SH4 +menu "Kernel features" + +config KEXEC + bool "kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL help - Selecting this option will enable an in-kernel API for manipulating - the store queues integrated in the SH-4 processors. + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + +config PREEMPT + bool "Preemptible Kernel (EXPERIMENTAL)" + depends on EXPERIMENTAL config SMP bool "Symmetric multi-processing support" @@ -610,87 +513,58 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. -config HS7751RVOIP_CODEC - bool "Support VoIP Codec section" - depends on SH_HS7751RVOIP - help - Selecting this option will support CODEC section. - -config RTS7751R2D_REV11 - bool "RTS7751R2D Rev. 1.1 board support" - depends on SH_RTS7751R2D - help - Selecting this option will support version rev. 1.1. - -config SH_PCLK_CALC - bool - default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180 +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 default y help - This option will cause the PCLK value to be probed at run-time. It - will display a notification if the probed value has greater than a - 1% variance of the hardcoded CONFIG_SH_PCLK_FREQ. + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. -config SH_PCLK_FREQ - int "Peripheral clock frequency (in Hz)" - default "50000000" if CPU_SUBTYPE_SH7750 - default "60000000" if CPU_SUBTYPE_SH7751 - default "33333333" if CPU_SUBTYPE_SH7300 - default "27000000" if CPU_SUBTYPE_SH73180 - default "66000000" if CPU_SUBTYPE_SH4_202 - default "1193182" - help - This option is used to specify the peripheral clock frequency. This - option must be set for each processor in order for the kernel to - function reliably. If no sane default exists, we use a default from - the legacy i8254. Any discrepancies will be reported on boot time - with an auto-probed frequency which should be considered the proper - value for your hardware. + See <file:Documentation/sh/register-banks.txt> for further + information on SR.RB and register banking in the kernel in general. -menu "CPU Frequency scaling" +endmenu -source "drivers/cpufreq/Kconfig" +menu "Boot options" -config SH_CPU_FREQ - tristate "SuperH CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE +config ZERO_PAGE_OFFSET + hex "Zero page offset" + default "0x00004000" if SH_MPC1211 || SH_SH03 + default "0x00001000" help - This adds the cpufreq driver for SuperH. At present, only - the SH-4 is supported. - - For details, take a look at <file:Documentation/cpu-freq>. - - If unsure, say N. + This sets the default offset of zero page. -endmenu +config BOOT_LINK_OFFSET + hex "Link address offset for booting" + default "0x00800000" + help + This option allows you to set the link address offset of the zImage. + This can be useful if you are on a board which has a small amount of + memory. -source "arch/sh/drivers/dma/Kconfig" +config UBC_WAKEUP + bool "Wakeup UBC on startup" + help + Selecting this option will wakeup the User Break Controller (UBC) on + startup. Although the UBC is left in an awake state when the processor + comes up, some boot loaders misbehave by putting the UBC to sleep in a + power saving state, which causes issues with things like ptrace(). -source "arch/sh/cchips/Kconfig" + If unsure, say N. -config HEARTBEAT - bool "Heartbeat LED" - depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV - help - Use the power-on LED on your machine as a load meter. The exact - behavior is platform-dependent, but normally the flash frequency is - a hyperbolic function of the 5-minute load average. +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" -config RTC_9701JE - tristate "EPSON RTC-9701JE support" - depends on SH_RTS7751R2D - help - Selecting this option will support EPSON RTC-9701JE. +config CMDLINE + string "Initial kernel command string" + depends on CMDLINE_BOOL + default "console=ttySC1,115200" endmenu -config ISA_DMA_API - bool - depends on MPC1211 - default y - -menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" +menu "Bus options" # Even on SuperH devices which don't have an ISA bus, # this variable helps the PCMCIA modules handle @@ -701,7 +575,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" # PCMCIA outright. -- PFM. config ISA bool - default y if PCMCIA || SMC91X + default y if PCMCIA help Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff @@ -735,10 +609,9 @@ config MCA config SBUS bool -config MAPLE - tristate "Maple Bus support" - depends on SH_DREAMCAST - default y +config SUPERHYWAY + tristate "SuperHyway Bus support" + depends on CPU_SUBTYPE_SH4_202 source "arch/sh/drivers/pci/Kconfig" diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 3fab181da36..8fb31ab2c02 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -17,7 +17,7 @@ config SH_STANDARD_BIOS config EARLY_SCIF_CONSOLE bool "Use early SCIF console" - depends on CPU_SH4 + depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS config EARLY_PRINTK bool "Early printk support" diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 67192d6b00d..08c9515c480 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -17,10 +17,30 @@ cflags-y := -mb cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml +isa-y := any +isa-$(CONFIG_CPU_SH2) := sh2 +isa-$(CONFIG_CPU_SH3) := sh3 +isa-$(CONFIG_CPU_SH4) := sh4 +isa-$(CONFIG_CPU_SH4A) := sh4a +isa-$(CONFIG_CPU_SH2A) := sh2a + +isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp + +ifndef CONFIG_MMU +isa-y := $(isa-y)-nommu +endif + +ifndef CONFIG_SH_FPU +isa-y := $(isa-y)-nofpu +endif + +cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) + cflags-$(CONFIG_CPU_SH2) += -m2 cflags-$(CONFIG_CPU_SH3) += -m3 cflags-$(CONFIG_CPU_SH4) += -m4 \ $(call cc-option,-mno-implicit-fp,-m4-nofpu) +cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -67,9 +87,7 @@ machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180 machdir-$(CONFIG_SH_STB1_HARP) := harp machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive -machdir-$(CONFIG_SH_HP620) := hp6xx/hp620 -machdir-$(CONFIG_SH_HP680) := hp6xx/hp680 -machdir-$(CONFIG_SH_HP690) := hp6xx/hp690 +machdir-$(CONFIG_SH_HP6XX) := hp6xx machdir-$(CONFIG_SH_CQREEK) := cqreek machdir-$(CONFIG_SH_DMIDA) := dmida machdir-$(CONFIG_SH_EC3104) := ec3104 @@ -119,31 +137,39 @@ boot := arch/sh/boot CPPFLAGS_vmlinux.lds := -traditional +ifneq ($(KBUILD_SRC),) +incdir-prefix := $(srctree)/include/asm-sh/ +else +incdir-prefix := +endif + # Update machine arch and proc symlinks if something which affects # them changed. We use .arch and .mach to indicate when they were # updated last, otherwise make uses the target directory mtime. include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER @echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)' -ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p include/asm-sh - $(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu -else - $(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu -endif + $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi + $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu @touch $@ +# Most boards have their own mach directories. For the ones that +# don't, just reference the parent directory so the semantics are +# kept roughly the same. + include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER - @echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)' -ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p include/asm-sh - $(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach -else - $(Q)ln -fsn $(incdir-y) include/asm-sh/mach -endif + @echo -n ' SYMLINK include/asm-sh/mach -> ' + $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi + $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \ + echo -e 'include/asm-sh/$(incdir-y)'; \ + ln -fsn $(incdir-prefix)$(incdir-y) \ + include/asm-sh/mach; \ + else \ + echo -e 'include/asm-sh'; \ + ln -fsn $(incdir-prefix) include/asm-sh/mach; \ + fi @touch $@ - archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach .PHONY: maketools FORCE diff --git a/arch/sh/boards/hp6xx/Makefile b/arch/sh/boards/hp6xx/Makefile new file mode 100644 index 00000000000..927fe0aa5df --- /dev/null +++ b/arch/sh/boards/hp6xx/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the HP6xx specific parts of the kernel +# + +obj-y := mach.o setup.o + diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile deleted file mode 100644 index 20691dbce34..00000000000 --- a/arch/sh/boards/hp6xx/hp620/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP620 specific parts of the kernel -# - -obj-y := mach.o setup.o - diff --git a/arch/sh/boards/hp6xx/hp620/mach.c b/arch/sh/boards/hp6xx/hp620/mach.c deleted file mode 100644 index 0392d82b4a7..00000000000 --- a/arch/sh/boards/hp6xx/hp620/mach.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp620/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP620 - */ - -#include <linux/init.h> - -#include <asm/machvec.h> -#include <asm/rtc.h> -#include <asm/machvec_init.h> - -#include <asm/io.h> -#include <asm/hd64461/hd64461.h> -#include <asm/irq.h> - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_hp620 __initmv = { - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_irq_demux = hd64461_irq_demux, -}; -ALIAS_MV(hp620) diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c deleted file mode 100644 index 045fc5da727..00000000000 --- a/arch/sh/boards/hp6xx/hp620/setup.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp620/setup.c - * - * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson - * - * May be copied or modified under the terms of the GNU General Public - * License. See Linux/COPYING for more information. - * - * Setup code for an HP620. - * Due to similiarity with hp680/hp690 same inits are done (for now) - */ - -#include <linux/config.h> -#include <linux/init.h> -#include <asm/hd64461/hd64461.h> -#include <asm/io.h> -#include <asm/hp6xx/hp6xx.h> -#include <asm/cpu/dac.h> - -const char *get_system_type(void) -{ - return "HP620"; -} - -int __init platform_setup(void) -{ - u16 v; - - v = inw(HD64461_STBCR); - v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST | - HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST | - HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST | - HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST | - HD64461_STBCR_SAFECKE_IST; - outw(v, HD64461_STBCR); - - v = inw(HD64461_GPADR); - v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0; - outw(v, HD64461_GPADR); - - sh_dac_disable(DAC_SPEAKER_VOLUME); - - return 0; -} - diff --git a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile deleted file mode 100644 index 0beef11d9b1..00000000000 --- a/arch/sh/boards/hp6xx/hp680/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP680 specific parts of the kernel -# - -obj-y := mach.o setup.o - diff --git a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile deleted file mode 100644 index fbbe95e75f8..00000000000 --- a/arch/sh/boards/hp6xx/hp690/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP690 specific parts of the kernel -# - -obj-y := mach.o - diff --git a/arch/sh/boards/hp6xx/hp690/mach.c b/arch/sh/boards/hp6xx/hp690/mach.c deleted file mode 100644 index 2a4c68783cd..00000000000 --- a/arch/sh/boards/hp6xx/hp690/mach.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp690/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP690 - */ - -#include <linux/init.h> - -#include <asm/machvec.h> -#include <asm/rtc.h> -#include <asm/machvec_init.h> - -#include <asm/io.h> -#include <asm/hd64461/hd64461.h> -#include <asm/irq.h> - -struct sh_machine_vector mv_hp690 __initmv = { - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_irq_demux = hd64461_irq_demux, -}; -ALIAS_MV(hp690) diff --git a/arch/sh/boards/hp6xx/hp680/mach.c b/arch/sh/boards/hp6xx/mach.c index d7348613604..08dbba910f7 100644 --- a/arch/sh/boards/hp6xx/hp680/mach.c +++ b/arch/sh/boards/hp6xx/mach.c @@ -1,5 +1,5 @@ /* - * linux/arch/sh/boards/hp6xx/hp680/mach.c + * linux/arch/sh/boards/hp6xx/mach.c * * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) * @@ -8,19 +8,12 @@ * * Machine vector for the HP680 */ - -#include <linux/init.h> - #include <asm/machvec.h> -#include <asm/rtc.h> -#include <asm/machvec_init.h> - +#include <asm/hd64461.h> #include <asm/io.h> -#include <asm/hd64461/hd64461.h> -#include <asm/hp6xx/io.h> #include <asm/irq.h> -struct sh_machine_vector mv_hp680 __initmv = { +struct sh_machine_vector mv_hp6xx __initmv = { .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM, .mv_inb = hd64461_inb, @@ -50,4 +43,4 @@ struct sh_machine_vector mv_hp680 __initmv = { .mv_irq_demux = hd64461_irq_demux, }; -ALIAS_MV(hp680) +ALIAS_MV(hp6xx) diff --git a/arch/sh/boards/hp6xx/hp680/setup.c b/arch/sh/boards/hp6xx/setup.c index 4170190f264..6d94a8e2e67 100644 --- a/arch/sh/boards/hp6xx/hp680/setup.c +++ b/arch/sh/boards/hp6xx/setup.c @@ -11,18 +11,19 @@ #include <linux/config.h> #include <linux/init.h> -#include <asm/hd64461/hd64461.h> #include <asm/io.h> +#include <asm/hd64461.h> #include <asm/hp6xx/hp6xx.h> #include <asm/cpu/dac.h> const char *get_system_type(void) { - return "HP680"; + return "HP6xx"; } int __init platform_setup(void) { + u8 v8; u16 v; v = inw(HD64461_STBCR); v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST | @@ -30,12 +31,25 @@ int __init platform_setup(void) HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST | HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST | HD64461_STBCR_SAFECKE_IST; +#ifndef CONFIG_HD64461_ENABLER + v |= HD64461_STBCR_SPC1ST; +#endif outw(v, HD64461_STBCR); v = inw(HD64461_GPADR); v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0; outw(v, HD64461_GPADR); + outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR); + +#ifndef CONFIG_HD64461_ENABLER + outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR); +#endif + + sh_dac_output(0, DAC_SPEAKER_VOLUME); sh_dac_disable(DAC_SPEAKER_VOLUME); + v8 = ctrl_inb(DACR); + v8 &= ~DACR_DAE; + ctrl_outb(v8,DACR); return 0; } diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile index 1762b59e927..245f03baf76 100644 --- a/arch/sh/boards/overdrive/Makefile +++ b/arch/sh/boards/overdrive/Makefile @@ -2,7 +2,7 @@ # Makefile for the STMicroelectronics Overdrive specific parts of the kernel # -obj-y := mach.o setup.o io.o irq.o led.o time.o +obj-y := mach.o setup.o io.o irq.o led.o obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c index a36ce0284ed..94f6165d33b 100644 --- a/arch/sh/boards/overdrive/setup.c +++ b/arch/sh/boards/overdrive/setup.c @@ -17,8 +17,6 @@ #include <asm/overdrive/overdrive.h> #include <asm/overdrive/fpga.h> -extern void od_time_init(void); - const char *get_system_type(void) { return "SH7750 Overdrive"; @@ -31,11 +29,9 @@ int __init platform_setup(void) { #ifdef CONFIG_PCI init_overdrive_fpga(); - galileo_init(); + galileo_init(); #endif - board_time_init = od_time_init; - /* Enable RS232 receive buffers */ writel(0x1e, OVERDRIVE_CTRL); } diff --git a/arch/sh/boards/overdrive/time.c b/arch/sh/boards/overdrive/time.c deleted file mode 100644 index 68533690e09..00000000000 --- a/arch/sh/boards/overdrive/time.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * arch/sh/boards/overdrive/time.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * STMicroelectronics Overdrive Support. - */ - -void od_time_init(void) -{ - struct frqcr_data { - unsigned short frqcr; - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; - }; - - static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, - }; - - struct memclk_data { - unsigned char multiplier; - unsigned char divisor; - }; - static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 - }; - - unsigned long pvr; - - /* - * This should probably be moved into the SH3 probing code, and then - * use the processor structure to determine which CPU we are running - * on. - */ - pvr = ctrl_inl(CCN_PVR); - printk("PVR %08x\n", pvr); - - if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) { - /* - * Unfortunatly the STB1 FRQCR values are different from the - * 7750 ones. - */ - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; - - for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) { - d = &st40_frqcr_table[a]; - if (d->frqcr == (frqcr & 0x1ff)) - break; - } - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; - printk("ERROR: Unrecognised FRQCR value, using default multipliers\n"); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - current_cpu_data.master_clock = current_cpu_data.module_clock * - d->factor[2].divisor / - d->factor[2].multiplier; - current_cpu_data.bus_clock = current_cpu_data.master_clock * - d->factor[1].multiplier / - d->factor[1].divisor; - current_cpu_data.memory_clock = current_cpu_data.master_clock * - e->multiplier / e->divisor; - current_cpu_data.cpu_clock = current_cpu_data.master_clock * - d->factor[0].multiplier / - d->factor[0].divisor; -} - diff --git a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp6xx_defconfig index c85d3655b53..b36f102cec8 100644 --- a/arch/sh/configs/hp680_defconfig +++ b/arch/sh/configs/hp6xx_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-sh -# Wed Mar 2 15:09:41 2005 +# Linux kernel version: 2.6.15-sh +# Wed Jan 4 15:32:56 2006 # CONFIG_SUPERH=y CONFIG_UID16=y @@ -17,31 +17,36 @@ CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -49,6 +54,24 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_MODULES is not set # +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# # System type # # CONFIG_SH_SOLUTION_ENGINE is not set @@ -58,9 +81,7 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_STB1_HARP is not set # CONFIG_SH_STB1_OVERDRIVE is not set -# CONFIG_SH_HP620 is not set -CONFIG_SH_HP680=y -# CONFIG_SH_HP690 is not set +CONFIG_SH_HP6XX=y # CONFIG_SH_CQREEK is not set # CONFIG_SH_DMIDA is not set # CONFIG_SH_EC3104 is not set @@ -77,43 +98,90 @@ CONFIG_SH_HP680=y # CONFIG_SH_RTS7751R2D is not set # CONFIG_SH_EDOSK7705 is not set # CONFIG_SH_SH4202_MICRODEV is not set +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set # CONFIG_SH_UNKNOWN is not set -# CONFIG_CPU_SH2 is not set + +# +# Processor selection +# CONFIG_CPU_SH3=y -# CONFIG_CPU_SH4 is not set + +# +# SH-2 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7604 is not set + +# +# SH-3 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set # CONFIG_CPU_SUBTYPE_SH7708 is not set CONFIG_CPU_SUBTYPE_SH7709=y + +# +# SH-4 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set # CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set # CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# ST40 Processor Support +# # CONFIG_CPU_SUBTYPE_ST40STB1 is not set # CONFIG_CPU_SUBTYPE_ST40GX1 is not set -# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# Memory management options +# CONFIG_MMU=y -# CONFIG_CMDLINE_BOOL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x00400000 -CONFIG_MEMORY_SET=y -# CONFIG_MEMORY_OVERRIDE is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SH_RTC=y # CONFIG_SH_DSP is not set CONFIG_SH_ADC=y -CONFIG_SH_HP600=y -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_PREEMPT is not set -# CONFIG_UBC_WAKEUP is not set -# CONFIG_SH_WRITETHROUGH is not set -# CONFIG_SH_OCRAM is not set -# CONFIG_SMP is not set -CONFIG_SH_PCLK_CALC=y -CONFIG_SH_PCLK_FREQ=1193182 + +# +# Timer support +# +CONFIG_SH_TMU=y +CONFIG_SH_PCLK_FREQ_BOOL=y +CONFIG_SH_PCLK_FREQ=22110000 # # CPU Frequency scaling @@ -123,7 +191,10 @@ CONFIG_SH_PCLK_FREQ=1193182 # # DMA support # -# CONFIG_SH_DMA is not set +CONFIG_SH_DMA=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=4 +# CONFIG_NR_DMA_CHANNELS_BOOL is not set +# CONFIG_DMA_PAGE_OPS is not set # # Companion Chips @@ -132,21 +203,47 @@ CONFIG_HD6446X_SERIES=y CONFIG_HD64461=y # CONFIG_HD64465 is not set CONFIG_HD64461_IRQ=36 -# CONFIG_HD64461_ENABLER is not set +CONFIG_HD64461_IOBASE=0xb0000000 +CONFIG_HD64461_ENABLER=y + +# +# Kernel features +# +# CONFIG_KEXEC is not set +# CONFIG_PREEMPT is not set +# CONFIG_SMP is not set # -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# Boot options # +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +CONFIG_ISA=y # CONFIG_PCI is not set # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y # # PC-card bridges # +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_HD64461_PCMCIA=y +CONFIG_HD64461_PCMCIA_SOCKETS=1 +CONFIG_PCMCIA_PROBE=y # # PCI Hotplug Support @@ -160,9 +257,9 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # -# SH initrd options +# Networking # -# CONFIG_EMBEDDED_RAMDISK is not set +# CONFIG_NET is not set # # Device Drivers @@ -173,7 +270,11 @@ CONFIG_BINFMT_ELF=y # # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# # # Memory Technology Devices (MTD) @@ -188,30 +289,20 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # +# CONFIG_PNP is not set # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set # -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y - -# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -224,6 +315,7 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -235,6 +327,7 @@ CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDE_GENERIC=y CONFIG_IDE_SH=y # CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -242,9 +335,15 @@ CONFIG_IDE_SH=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set @@ -252,6 +351,7 @@ CONFIG_IDE_SH=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -263,9 +363,8 @@ CONFIG_IDE_SH=y # # -# Networking support +# Network device support # -# CONFIG_NET is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -296,17 +395,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_EVBUG is not set # -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_RAW is not set - -# # Input Device Drivers # # CONFIG_INPUT_KEYBOARD is not set @@ -316,6 +404,15 @@ CONFIG_SERIO=y # CONFIG_INPUT_MISC is not set # +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# # Character devices # CONFIG_VT=y @@ -353,10 +450,22 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set # CONFIG_RAW_DRIVER is not set # +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# # I2C support # # CONFIG_I2C is not set @@ -367,10 +476,21 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_W1 is not set # +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -383,27 +503,35 @@ CONFIG_LEGACY_PTY_COUNT=256 # Graphics support # CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_EPSON1355 is not set +# CONFIG_FB_S1D13XXX is not set CONFIG_FB_HIT=y # CONFIG_FB_VIRTUAL is not set # # Console display driver support # -# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_FONTS=y # CONFIG_FONT_8x8 is not set # CONFIG_FONT_8x16 is not set # CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set CONFIG_FONT_PEARL_8x8=y # CONFIG_FONT_ACORN_8x8 is not set # CONFIG_FONT_MINI_4x6 is not set # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set # # Logo configuration @@ -414,7 +542,22 @@ CONFIG_FONT_PEARL_8x8=y # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_OBSOLETE_OSS_DRIVER is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_SH_DAC_AUDIO=y +CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL=1 # # USB support @@ -423,7 +566,7 @@ CONFIG_FONT_PEARL_8x8=y # CONFIG_USB_ARCH_HAS_OHCI is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # @@ -442,25 +585,29 @@ CONFIG_FONT_PEARL_8x8=y # CONFIG_INFINIBAND is not set # +# SN Devices +# + +# # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -471,8 +618,11 @@ CONFIG_DNOTIFY=y # # DOS/FAT/NT Filesystems # +CONFIG_FAT_FS=y # CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -481,14 +631,11 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -516,7 +663,46 @@ CONFIG_MSDOS_PARTITION=y # # Native Language Support # -# CONFIG_NLS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set # # Profiling support @@ -526,7 +712,9 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FRAME_POINTER is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_KGDB is not set @@ -550,5 +738,6 @@ CONFIG_MSDOS_PARTITION=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 96e3036ec2b..47c3e837599 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -3,7 +3,7 @@ * * SuperH-specific DMA management API * - * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2003, 2004, 2005 Paul Mundt * * 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 @@ -15,6 +15,7 @@ #include <linux/spinlock.h> #include <linux/proc_fs.h> #include <linux/list.h> +#include <linux/platform_device.h> #include <asm/dma.h> DEFINE_SPINLOCK(dma_spin_lock); @@ -55,16 +56,14 @@ static LIST_HEAD(registered_dmac_list); struct dma_info *get_dma_info(unsigned int chan) { - struct list_head *pos, *tmp; + struct dma_info *info; unsigned int total = 0; /* * Look for each DMAC's range to determine who the owner of * the channel is. */ - list_for_each_safe(pos, tmp, ®istered_dmac_list) { - struct dma_info *info = list_entry(pos, struct dma_info, list); - + list_for_each_entry(info, ®istered_dmac_list, list) { total += info->nr_channels; if (chan > total) continue; @@ -75,6 +74,20 @@ struct dma_info *get_dma_info(unsigned int chan) return NULL; } +static unsigned int get_nr_channels(void) +{ + struct dma_info *info; + unsigned int nr = 0; + + if (unlikely(list_empty(®istered_dmac_list))) + return nr; + + list_for_each_entry(info, ®istered_dmac_list, list) + nr += info->nr_channels; + + return nr; +} + struct dma_channel *get_dma_channel(unsigned int chan) { struct dma_info *info = get_dma_info(chan); @@ -173,7 +186,7 @@ int dma_xfer(unsigned int chan, unsigned long from, static int dma_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data) { - struct list_head *pos, *tmp; + struct dma_info *info; char *p = buf; if (list_empty(®istered_dmac_list)) @@ -182,8 +195,7 @@ static int dma_read_proc(char *buf, char **start, off_t off, /* * Iterate over each registered DMAC */ - list_for_each_safe(pos, tmp, ®istered_dmac_list) { - struct dma_info *info = list_entry(pos, struct dma_info, list); + list_for_each_entry(info, ®istered_dmac_list, list) { int i; /* @@ -205,9 +217,9 @@ static int dma_read_proc(char *buf, char **start, off_t off, #endif -int __init register_dmac(struct dma_info *info) +int register_dmac(struct dma_info *info) { - int i; + unsigned int total_channels, i; INIT_LIST_HEAD(&info->list); @@ -217,6 +229,11 @@ int __init register_dmac(struct dma_info *info) BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); + info->pdev = platform_device_register_simple((char *)info->name, -1, + NULL, 0); + if (IS_ERR(info->pdev)) + return PTR_ERR(info->pdev); + /* * Don't touch pre-configured channels */ @@ -232,10 +249,12 @@ int __init register_dmac(struct dma_info *info) memset(info->channels, 0, size); } + total_channels = get_nr_channels(); for (i = 0; i < info->nr_channels; i++) { struct dma_channel *chan = info->channels + i; chan->chan = i; + chan->vchan = i + total_channels; memcpy(chan->dev_id, "Unused", 7); @@ -245,9 +264,7 @@ int __init register_dmac(struct dma_info *info) init_MUTEX(&chan->sem); init_waitqueue_head(&chan->wait_queue); -#ifdef CONFIG_SYSFS - dma_create_sysfs_files(chan); -#endif + dma_create_sysfs_files(chan, info); } list_add(&info->list, ®istered_dmac_list); @@ -255,12 +272,18 @@ int __init register_dmac(struct dma_info *info) return 0; } -void __exit unregister_dmac(struct dma_info *info) +void unregister_dmac(struct dma_info *info) { + unsigned int i; + + for (i = 0; i < info->nr_channels; i++) + dma_remove_sysfs_files(info->channels + i, info); + if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) kfree(info->channels); list_del(&info->list); + platform_device_unregister(info->pdev); } static int __init dma_api_init(void) diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index 231e3f6fb28..5afab6f56ec 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -140,7 +140,7 @@ static struct dma_ops g2_dma_ops = { }; static struct dma_info g2_dma_info = { - .name = "G2 DMA", + .name = "g2_dmac", .nr_channels = 4, .ops = &g2_dma_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, @@ -160,6 +160,7 @@ static int __init g2_dma_init(void) static void __exit g2_dma_exit(void) { free_irq(HW_EVENT_G2_DMA, 0); + unregister_dmac(&g2_dma_info); } subsys_initcall(g2_dma_init); diff --git a/arch/sh/drivers/dma/dma-isa.c b/arch/sh/drivers/dma/dma-isa.c index 1c9bc45b8bc..05a74ffdb68 100644 --- a/arch/sh/drivers/dma/dma-isa.c +++ b/arch/sh/drivers/dma/dma-isa.c @@ -25,14 +25,14 @@ * such, this code is meant for only the simplest of tasks (and shouldn't be * used in any new drivers at all). * - * It should also be noted that various functions here are labelled as - * being deprecated. This is due to the fact that the ops->xfer() method is - * the preferred way of doing things (as well as just grabbing the spinlock - * directly). As such, any users of this interface will be warned rather - * loudly. + * NOTE: ops->xfer() is the preferred way of doing things. However, there + * are some users of the ISA DMA API that exist in common code that we + * don't necessarily want to go out of our way to break, so we still + * allow for some compatability at that level. Any new code is strongly + * advised to run far away from the ISA DMA API and use the SH DMA API + * directly. */ - -unsigned long __deprecated claim_dma_lock(void) +unsigned long claim_dma_lock(void) { unsigned long flags; @@ -42,19 +42,19 @@ unsigned long __deprecated claim_dma_lock(void) } EXPORT_SYMBOL(claim_dma_lock); -void __deprecated release_dma_lock(unsigned long flags) +void release_dma_lock(unsigned long flags) { spin_unlock_irqrestore(&dma_spin_lock, flags); } EXPORT_SYMBOL(release_dma_lock); -void __deprecated disable_dma(unsigned int chan) +void disable_dma(unsigned int chan) { /* Nothing */ } EXPORT_SYMBOL(disable_dma); -void __deprecated enable_dma(unsigned int chan) +void enable_dma(unsigned int chan) { struct dma_info *info = get_dma_info(chan); struct dma_channel *channel = &info->channels[chan]; diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index 2e1d58f2d1b..df604975ccc 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -80,7 +80,7 @@ static struct dma_ops pvr2_dma_ops = { }; static struct dma_info pvr2_dma_info = { - .name = "PowerVR 2 DMA", + .name = "pvr2_dmac", .nr_channels = 1, .ops = &pvr2_dma_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, @@ -98,6 +98,7 @@ static void __exit pvr2_dma_exit(void) { free_dma(PVR2_CASCADE_CHAN); free_irq(HW_EVENT_PVR2_DMA, 0); + unregister_dmac(&pvr2_dma_info); } subsys_initcall(pvr2_dma_init); diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 31dacd4444b..cca26c4c9d1 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -5,6 +5,7 @@ * * Copyright (C) 2000 Takashi YOSHII * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2005 Andriy Skulysh * * 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 @@ -16,51 +17,28 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <asm/dreamcast/dma.h> #include <asm/signal.h> #include <asm/irq.h> #include <asm/dma.h> #include <asm/io.h> #include "dma-sh.h" -/* - * The SuperH DMAC supports a number of transmit sizes, we list them here, - * with their respective values as they appear in the CHCR registers. - * - * Defaults to a 64-bit transfer size. - */ -enum { - XMIT_SZ_64BIT, - XMIT_SZ_8BIT, - XMIT_SZ_16BIT, - XMIT_SZ_32BIT, - XMIT_SZ_256BIT, -}; - -/* - * The DMA count is defined as the number of bytes to transfer. - */ -static unsigned int ts_shift[] = { - [XMIT_SZ_64BIT] = 3, - [XMIT_SZ_8BIT] = 0, - [XMIT_SZ_16BIT] = 1, - [XMIT_SZ_32BIT] = 2, - [XMIT_SZ_256BIT] = 5, -}; - static inline unsigned int get_dmte_irq(unsigned int chan) { - unsigned int irq; + unsigned int irq = 0; /* * Normally we could just do DMTE0_IRQ + chan outright, though in the * case of the 7751R, the DMTE IRQs for channels > 4 start right above * the SCIF */ - if (chan < 4) { irq = DMTE0_IRQ + chan; } else { +#ifdef DMTE4_IRQ irq = DMTE4_IRQ + chan - 4; +#endif } return irq; @@ -78,9 +56,7 @@ static inline unsigned int calc_xmit_shift(struct dma_channel *chan) { u32 chcr = ctrl_inl(CHCR[chan->chan]); - chcr >>= 4; - - return ts_shift[chcr & 0x0007]; + return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; } /* @@ -109,8 +85,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) static int sh_dmac_request_dma(struct dma_channel *chan) { + char name[32]; + + snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", + chan->chan); + return request_irq(get_dmte_irq(chan->chan), dma_tei, - SA_INTERRUPT, "DMAC Transfer End", chan); + SA_INTERRUPT, name, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) @@ -118,10 +99,18 @@ static void sh_dmac_free_dma(struct dma_channel *chan) free_irq(get_dmte_irq(chan->chan), chan); } -static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) +static void +sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) { if (!chcr) - chcr = RS_DUAL; + chcr = RS_DUAL | CHCR_IE; + + if (chcr & CHCR_IE) { + chcr &= ~CHCR_IE; + chan->flags |= DMA_TEI_CAPABLE; + } else { + chan->flags &= ~DMA_TEI_CAPABLE; + } ctrl_outl(chcr, CHCR[chan->chan]); @@ -130,22 +119,32 @@ static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long ch static void sh_dmac_enable_dma(struct dma_channel *chan) { - int irq = get_dmte_irq(chan->chan); + int irq; u32 chcr; chcr = ctrl_inl(CHCR[chan->chan]); - chcr |= CHCR_DE | CHCR_IE; + chcr |= CHCR_DE; + + if (chan->flags & DMA_TEI_CAPABLE) + chcr |= CHCR_IE; + ctrl_outl(chcr, CHCR[chan->chan]); - enable_irq(irq); + if (chan->flags & DMA_TEI_CAPABLE) { + irq = get_dmte_irq(chan->chan); + enable_irq(irq); + } } static void sh_dmac_disable_dma(struct dma_channel *chan) { - int irq = get_dmte_irq(chan->chan); + int irq; u32 chcr; - disable_irq(irq); + if (chan->flags & DMA_TEI_CAPABLE) { + irq = get_dmte_irq(chan->chan); + disable_irq(irq); + } chcr = ctrl_inl(CHCR[chan->chan]); chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); @@ -158,7 +157,7 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) * If we haven't pre-configured the channel with special flags, use * the defaults. */ - if (!(chan->flags & DMA_CONFIGURED)) + if (unlikely(!(chan->flags & DMA_CONFIGURED))) sh_dmac_configure_channel(chan, 0); sh_dmac_disable_dma(chan); @@ -178,9 +177,11 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) * cascading to the PVR2 DMAC. In this case, we still need to write * SAR and DAR, regardless of value, in order for cascading to work. */ - if (chan->sar || (mach_is_dreamcast() && chan->chan == 2)) + if (chan->sar || (mach_is_dreamcast() && + chan->chan == PVR2_CASCADE_CHAN)) ctrl_outl(chan->sar, SAR[chan->chan]); - if (chan->dar || (mach_is_dreamcast() && chan->chan == 2)) + if (chan->dar || (mach_is_dreamcast() && + chan->chan == PVR2_CASCADE_CHAN)) ctrl_outl(chan->dar, DAR[chan->chan]); ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); @@ -198,17 +199,38 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan) return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); } -#if defined(CONFIG_CPU_SH4) -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +#ifdef CONFIG_CPU_SUBTYPE_SH7780 +#define dmaor_read_reg() ctrl_inw(DMAOR) +#define dmaor_write_reg(data) ctrl_outw(data, DMAOR) +#else +#define dmaor_read_reg() ctrl_inl(DMAOR) +#define dmaor_write_reg(data) ctrl_outl(data, DMAOR) +#endif + +static inline int dmaor_reset(void) { - unsigned long dmaor = ctrl_inl(DMAOR); + unsigned long dmaor = dmaor_read_reg(); + + /* Try to clear the error flags first, incase they are set */ + dmaor &= ~(DMAOR_NMIF | DMAOR_AE); + dmaor_write_reg(dmaor); - printk("DMAE: DMAOR=%lx\n", dmaor); + dmaor |= DMAOR_INIT; + dmaor_write_reg(dmaor); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR); + /* See if we got an error again */ + if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { + printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); + return -EINVAL; + } + return 0; +} + +#if defined(CONFIG_CPU_SH4) +static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +{ + dmaor_reset(); disable_irq(irq); return IRQ_HANDLED; @@ -224,8 +246,8 @@ static struct dma_ops sh_dmac_ops = { }; static struct dma_info sh_dmac_info = { - .name = "SuperH DMAC", - .nr_channels = 4, + .name = "sh_dmac", + .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS, .ops = &sh_dmac_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, }; @@ -248,7 +270,13 @@ static int __init sh_dmac_init(void) make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); } - ctrl_outl(0x8000 | DMAOR_DME, DMAOR); + /* + * Initialize DMAOR, and clean up any error flags that may have + * been set. + */ + i = dmaor_reset(); + if (i < 0) + return i; return register_dmac(info); } @@ -258,10 +286,12 @@ static void __exit sh_dmac_exit(void) #ifdef CONFIG_CPU_SH4 free_irq(DMAE_IRQ, 0); #endif + unregister_dmac(&sh_dmac_info); } subsys_initcall(sh_dmac_init); module_exit(sh_dmac_exit); +MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); +MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); MODULE_LICENSE("GPL"); - diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h index dd9d547539a..0f591fbc922 100644 --- a/arch/sh/drivers/dma/dma-sh.h +++ b/arch/sh/drivers/dma/dma-sh.h @@ -11,6 +11,8 @@ #ifndef __DMA_SH_H #define __DMA_SH_H +#include <asm/cpu/dma.h> + /* Definitions for the SuperH DMAC */ #define REQ_L 0x00000000 #define REQ_E 0x00080000 @@ -26,27 +28,47 @@ #define SM_DEC 0x00002000 #define RS_IN 0x00000200 #define RS_OUT 0x00000300 -#define TM_BURST 0x0000080 -#define TS_8 0x00000010 -#define TS_16 0x00000020 -#define TS_32 0x00000030 -#define TS_64 0x00000000 #define TS_BLK 0x00000040 #define CHCR_DE 0x00000001 #define CHCR_TE 0x00000002 #define CHCR_IE 0x00000004 -/* Define the default configuration for dual address memory-memory transfer. - * The 0x400 value represents auto-request, external->external. - */ -#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) - -#define DMAOR_COD 0x00000008 +/* DMAOR definitions */ #define DMAOR_AE 0x00000004 #define DMAOR_NMIF 0x00000002 #define DMAOR_DME 0x00000001 +/* + * Define the default configuration for dual address memory-memory transfer. + * The 0x400 value represents auto-request, external->external. + */ +#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) + #define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) +/* + * Subtypes that have fewer channels than this simply need to change + * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number + * of channels should expand on this. + * + * For most subtypes we can easily figure these values out with some + * basic calculation, unfortunately on other subtypes these are more + * scattered, so we just leave it unrolled for simplicity. + */ +#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ + SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \ + SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60}) +#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ + SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \ + SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64}) +#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ + SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \ + SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68}) +#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ + SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \ + SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c}) + +#define DMAOR (SH_DMAC_BASE + 0x40) + #endif /* __DMA_SH_H */ diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 6e3b58bd879..70a5d82eb2f 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -3,7 +3,7 @@ * * sysfs interface for SH DMA API * - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004, 2005 Paul Mundt * * 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 @@ -12,7 +12,9 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/platform_device.h> #include <linux/module.h> +#include <linux/err.h> #include <linux/string.h> #include <asm/dma.h> @@ -77,7 +79,7 @@ static ssize_t dma_store_config(struct sys_device *dev, unsigned long config; config = simple_strtoul(buf, NULL, 0); - dma_configure_channel(channel->chan, config); + dma_configure_channel(channel->vchan, config); return count; } @@ -111,12 +113,13 @@ static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL); dma_ro_attr(count, "0x%08x\n"); dma_ro_attr(flags, "0x%08lx\n"); -int __init dma_create_sysfs_files(struct dma_channel *chan) +int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) { struct sys_device *dev = &chan->dev; + char name[16]; int ret; - dev->id = chan->chan; + dev->id = chan->vchan; dev->cls = &dma_sysclass; ret = sysdev_register(dev); @@ -129,6 +132,24 @@ int __init dma_create_sysfs_files(struct dma_channel *chan) sysdev_create_file(dev, &attr_flags); sysdev_create_file(dev, &attr_config); - return 0; + snprintf(name, sizeof(name), "dma%d", chan->chan); + return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); +} + +void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info) +{ + struct sys_device *dev = &chan->dev; + char name[16]; + + sysdev_remove_file(dev, &attr_dev_id); + sysdev_remove_file(dev, &attr_count); + sysdev_remove_file(dev, &attr_mode); + sysdev_remove_file(dev, &attr_flags); + sysdev_remove_file(dev, &attr_config); + + snprintf(name, sizeof(name), "dma%d", chan->chan); + sysfs_remove_link(&info->pdev->dev.kobj, name); + + sysdev_unregister(dev); } diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 8b819698df1..7a86eeb2265 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -17,6 +17,4 @@ obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - -USE_STANDARD_AS_RULE := true - +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index cd43714df61..5bfc33bec5d 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -2,15 +2,12 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y := irq_ipr.o irq_imask.o init.o bus.o +obj-y += irq/ init.o bus.o clock.o obj-$(CONFIG_CPU_SH2) += sh2/ obj-$(CONFIG_CPU_SH3) += sh3/ obj-$(CONFIG_CPU_SH4) += sh4/ -obj-$(CONFIG_SH_RTC) += rtc.o +obj-$(CONFIG_SH_RTC) += rtc.o obj-$(CONFIG_UBC_WAKEUP) += ubc.o -obj-$(CONFIG_SH_ADC) += adc.o - -USE_STANDARD_AS_RULE := true - +obj-$(CONFIG_SH_ADC) += adc.o diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c index 3278d234bb1..fc6c4bd40c6 100644 --- a/arch/sh/kernel/cpu/bus.c +++ b/arch/sh/kernel/cpu/bus.c @@ -109,6 +109,8 @@ int sh_device_register(struct sh_dev *dev) /* This is needed for USB OHCI to work */ if (dev->dma_mask) dev->dev.dma_mask = dev->dma_mask; + if (dev->coherent_dma_mask) + dev->dev.coherent_dma_mask = dev->coherent_dma_mask; snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u", dev->name, dev->dev_id); diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c new file mode 100644 index 00000000000..989e7fdd524 --- /dev/null +++ b/arch/sh/kernel/cpu/clock.c @@ -0,0 +1,287 @@ +/* + * arch/sh/kernel/cpu/clock.c - SuperH clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * This clock framework is derived from the OMAP version by: + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/list.h> +#include <linux/kref.h> +#include <linux/seq_file.h> +#include <linux/err.h> +#include <asm/clock.h> +#include <asm/timer.h> + +static LIST_HEAD(clock_list); +static DEFINE_SPINLOCK(clock_lock); +static DECLARE_MUTEX(clock_list_sem); + +/* + * Each subtype is expected to define the init routines for these clocks, + * as each subtype (or processor family) will have these clocks at the + * very least. These are all provided through the CPG, which even some of + * the more quirky parts (such as ST40, SH4-202, etc.) still have. + * + * The processor-specific code is expected to register any additional + * clock sources that are of interest. + */ +static struct clk master_clk = { + .name = "master_clk", + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +#ifdef CONFIG_SH_PCLK_FREQ_BOOL + .rate = CONFIG_SH_PCLK_FREQ, +#endif +}; + +static struct clk module_clk = { + .name = "module_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +}; + +static struct clk bus_clk = { + .name = "bus_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +}; + +static struct clk cpu_clk = { + .name = "cpu_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED, +}; + +/* + * The ordering of these clocks matters, do not change it. + */ +static struct clk *onchip_clocks[] = { + &master_clk, + &module_clk, + &bus_clk, + &cpu_clk, +}; + +static void propagate_rate(struct clk *clk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->parent != clk)) + continue; + if (likely(clkp->ops && clkp->ops->recalc)) + clkp->ops->recalc(clkp); + } +} + +int __clk_enable(struct clk *clk) +{ + /* + * See if this is the first time we're enabling the clock, some + * clocks that are always enabled still require "special" + * initialization. This is especially true if the clock mode + * changes and the clock needs to hunt for the proper set of + * divisors to use before it can effectively recalc. + */ + if (unlikely(atomic_read(&clk->kref.refcount) == 1)) + if (clk->ops && clk->ops->init) + clk->ops->init(clk); + + if (clk->flags & CLK_ALWAYS_ENABLED) + return 0; + + if (likely(clk->ops && clk->ops->enable)) + clk->ops->enable(clk); + + kref_get(&clk->kref); + return 0; +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&clock_lock, flags); + ret = __clk_enable(clk); + spin_unlock_irqrestore(&clock_lock, flags); + + return ret; +} + +static void clk_kref_release(struct kref *kref) +{ + /* Nothing to do */ +} + +void __clk_disable(struct clk *clk) +{ + if (clk->flags & CLK_ALWAYS_ENABLED) + return; + + kref_put(&clk->kref, clk_kref_release); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clock_lock, flags); +} + +int clk_register(struct clk *clk) +{ + down(&clock_list_sem); + + list_add(&clk->node, &clock_list); + kref_init(&clk->kref); + + up(&clock_list_sem); + + return 0; +} + +void clk_unregister(struct clk *clk) +{ + down(&clock_list_sem); + list_del(&clk->node); + up(&clock_list_sem); +} + +inline unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EOPNOTSUPP; + + if (likely(clk->ops && clk->ops->set_rate)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_rate(clk, rate); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + + return ret; +} + +void clk_recalc_rate(struct clk *clk) +{ + if (likely(clk->ops && clk->ops->recalc)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + clk->ops->recalc(clk); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); +} + +struct clk *clk_get(const char *id) +{ + struct clk *p, *clk = ERR_PTR(-ENOENT); + + down(&clock_list_sem); + list_for_each_entry(p, &clock_list, node) { + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + break; + } + } + up(&clock_list_sem); + + return clk; +} + +void clk_put(struct clk *clk) +{ + if (clk && !IS_ERR(clk)) + module_put(clk->owner); +} + +void __init __attribute__ ((weak)) +arch_init_clk_ops(struct clk_ops **ops, int type) +{ +} + +int __init clk_init(void) +{ + int i, ret = 0; + + if (unlikely(!master_clk.rate)) + /* + * NOTE: This will break if the default divisor has been + * changed. + * + * No one should be changing the default on us however, + * expect that a sane value for CONFIG_SH_PCLK_FREQ will + * be defined in the event of a different divisor. + */ + master_clk.rate = get_timer_frequency() * 4; + + for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) { + struct clk *clk = onchip_clocks[i]; + + arch_init_clk_ops(&clk->ops, i); + ret |= clk_register(clk); + clk_enable(clk); + } + + /* Kick the child clocks.. */ + propagate_rate(&master_clk); + propagate_rate(&bus_clk); + + return ret; +} + +int show_clocks(struct seq_file *m) +{ + struct clk *clk; + + list_for_each_entry_reverse(clk, &clock_list, node) { + unsigned long rate = clk_get_rate(clk); + + /* + * Don't bother listing dummy clocks with no ancestry + * that only support enable and disable ops. + */ + if (unlikely(!rate && !clk->parent)) + continue; + + seq_printf(m, "%-12s\t: %ld.%02ldMHz\n", clk->name, + rate / 1000000, (rate % 1000000) / 10000); + } + + return 0; +} + +EXPORT_SYMBOL_GPL(clk_register); +EXPORT_SYMBOL_GPL(clk_unregister); +EXPORT_SYMBOL_GPL(clk_get); +EXPORT_SYMBOL_GPL(clk_put); +EXPORT_SYMBOL_GPL(clk_enable); +EXPORT_SYMBOL_GPL(clk_disable); +EXPORT_SYMBOL_GPL(__clk_enable); +EXPORT_SYMBOL_GPL(__clk_disable); +EXPORT_SYMBOL_GPL(clk_get_rate); +EXPORT_SYMBOL_GPL(clk_set_rate); +EXPORT_SYMBOL_GPL(clk_recalc_rate); diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile new file mode 100644 index 00000000000..e3cccea15e1 --- /dev/null +++ b/arch/sh/kernel/cpu/irq/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Linux/SuperH CPU-specifc IRQ handlers. +# +obj-y += ipr.o imask.o + +obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o +obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq/imask.c index a963d00a971..baed9a550d3 100644 --- a/arch/sh/kernel/cpu/irq_imask.c +++ b/arch/sh/kernel/cpu/irq/imask.c @@ -1,16 +1,12 @@ -/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $ - * - * linux/arch/sh/kernel/irq_imask.c +/* + * arch/sh/kernel/cpu/irq/imask.c * * Copyright (C) 1999, 2000 Niibe Yutaka * * Simple interrupt handling using IMASK of SR register. * */ - /* NOTE: Will not work on level 15 */ - - #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/kernel_stat.h> @@ -19,13 +15,11 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/irq.h> - #include <linux/spinlock.h> #include <linux/cache.h> #include <linux/irq.h> +#include <asm/system.h> +#include <asm/irq.h> /* Bitmap of IRQ masked */ static unsigned long imask_mask = 0x7fff; @@ -40,7 +34,7 @@ static void end_imask_irq(unsigned int irq); #define IMASK_PRIORITY 15 static unsigned int startup_imask_irq(unsigned int irq) -{ +{ /* Nothing to do */ return 0; /* never anything pending */ } diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c new file mode 100644 index 00000000000..06e8afab32e --- /dev/null +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -0,0 +1,284 @@ +/* + * Interrupt handling for INTC2-based IRQ. + * + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * These are the "new Hitachi style" interrupts, as present on the + * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/machvec.h> + +struct intc2_data { + unsigned char msk_offset; + unsigned char msk_shift; + + int (*clear_irq) (int); +}; + +static struct intc2_data intc2_data[NR_INTC2_IRQS]; + +static void enable_intc2_irq(unsigned int irq); +static void disable_intc2_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_intc2_irq disable_intc2_irq + +static void mask_and_ack_intc2(unsigned int); +static void end_intc2_irq(unsigned int irq); + +static unsigned int startup_intc2_irq(unsigned int irq) +{ + enable_intc2_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type intc2_irq_type = { + .typename = "INTC2-IRQ", + .startup = startup_intc2_irq, + .shutdown = shutdown_intc2_irq, + .enable = enable_intc2_irq, + .disable = disable_intc2_irq, + .ack = mask_and_ack_intc2, + .end = end_intc2_irq +}; + +static void disable_intc2_irq(unsigned int irq) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; + + /* Sanity check */ + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + + ctrl_outl(1 << msk_shift, + INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); +} + +static void enable_intc2_irq(unsigned int irq) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; + + /* Sanity check */ + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + + ctrl_outl(1 << msk_shift, + INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); +} + +static void mask_and_ack_intc2(unsigned int irq) +{ + disable_intc2_irq(irq); +} + +static void end_intc2_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_intc2_irq(irq); + + if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); +} + +/* + * Setup an INTC2 style interrupt. + * NOTE: Unlike IPR interrupts, parameters are not shifted by this code, + * allowing the use of the numbers straight out of the datasheet. + * For example: + * PIO1 which is INTPRI00[19,16] and INTMSK00[13] + * would be: ^ ^ ^ ^ + * | | | | + * make_intc2_irq(84, 0, 16, 0, 13); + */ +void make_intc2_irq(unsigned int irq, + unsigned int ipr_offset, unsigned int ipr_shift, + unsigned int msk_offset, unsigned int msk_shift, + unsigned int priority) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + unsigned int flags; + unsigned long ipr; + + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + disable_irq_nosync(irq); + + /* Fill the data we need */ + intc2_data[irq_offset].msk_offset = msk_offset; + intc2_data[irq_offset].msk_shift = msk_shift; + intc2_data[irq_offset].clear_irq = NULL; + + /* Set the priority level */ + local_irq_save(flags); + + ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + ipr &= ~(0xf << ipr_shift); + ipr |= priority << ipr_shift; + ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + + local_irq_restore(flags); + + irq_desc[irq].handler = &intc2_irq_type; + + disable_intc2_irq(irq); +} + +static struct intc2_init { + unsigned short irq; + unsigned char ipr_offset, ipr_shift; + unsigned char msk_offset, msk_shift; + unsigned char priority; +} intc2_init_data[] __initdata = { +#if defined(CONFIG_CPU_SUBTYPE_ST40) + {64, 0, 0, 0, 0, 13}, /* PCI serr */ + {65, 0, 4, 0, 1, 13}, /* PCI err */ + {66, 0, 4, 0, 2, 13}, /* PCI ad */ + {67, 0, 4, 0, 3, 13}, /* PCI pwd down */ + {72, 0, 8, 0, 5, 13}, /* DMAC INT0 */ + {73, 0, 8, 0, 6, 13}, /* DMAC INT1 */ + {74, 0, 8, 0, 7, 13}, /* DMAC INT2 */ + {75, 0, 8, 0, 8, 13}, /* DMAC INT3 */ + {76, 0, 8, 0, 9, 13}, /* DMAC INT4 */ + {78, 0, 8, 0, 11, 13}, /* DMAC ERR */ + {80, 0, 12, 0, 12, 13}, /* PIO0 */ + {84, 0, 16, 0, 13, 13}, /* PIO1 */ + {88, 0, 20, 0, 14, 13}, /* PIO2 */ + {112, 4, 0, 4, 0, 13}, /* Mailbox */ + #ifdef CONFIG_CPU_SUBTYPE_ST40GX1 + {116, 4, 4, 4, 4, 13}, /* SSC0 */ + {120, 4, 8, 4, 8, 13}, /* IR Blaster */ + {124, 4, 12, 4, 12, 13}, /* USB host */ + {128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */ + {132, 4, 20, 4, 20, 13}, /* UART0 */ + {134, 4, 20, 4, 22, 13}, /* UART2 */ + {136, 4, 24, 4, 24, 13}, /* IO_PIO0 */ + {140, 4, 28, 4, 28, 13}, /* EMPI */ + {144, 8, 0, 8, 0, 13}, /* MAFE */ + {148, 8, 4, 8, 4, 13}, /* PWM */ + {152, 8, 8, 8, 8, 13}, /* SSC1 */ + {156, 8, 12, 8, 12, 13}, /* IO_PIO1 */ + {160, 8, 16, 8, 16, 13}, /* USB target */ + {164, 8, 20, 8, 20, 13}, /* UART1 */ + {168, 8, 24, 8, 24, 13}, /* Teletext */ + {172, 8, 28, 8, 28, 13}, /* VideoSync VTG */ + {173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */ + {174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */ +#endif +#elif defined(CONFIG_CPU_SUBTYPE_SH7760) +/* + * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0 + */ + /* INTPRIO0 | INTMSK0 */ + {48, 0, 28, 0, 31, 3}, /* IRQ 4 */ + {49, 0, 24, 0, 30, 3}, /* IRQ 3 */ + {50, 0, 20, 0, 29, 3}, /* IRQ 2 */ + {51, 0, 16, 0, 28, 3}, /* IRQ 1 */ + /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */ + /* INTPRIO4 | INTMSK0 */ + {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */ + {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */ + {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */ + {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */ + {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */ + {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */ + {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */ + {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */ + /* INTPRIO8 | INTMSK0 */ + {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */ + {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */ + {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */ + {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */ + {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */ + {65, 8, 24, 0, 16, 3}, /* LCDC */ + /* 66, 67 unused */ + {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */ + {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */ + {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */ + /* 71 unused */ + {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */ + {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */ + {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */ + {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */ + {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */ + {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */ + {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */ + {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */ + /* | INTMSK4 */ + {80, 8, 4, 4, 23, 3}, /* SIM_ERI */ + {81, 8, 4, 4, 22, 3}, /* SIM_RXI */ + {82, 8, 4, 4, 21, 3}, /* SIM_TXI */ + {83, 8, 4, 4, 20, 3}, /* SIM_TEI */ + {84, 8, 0, 4, 19, 3}, /* HSPII */ + /* INTPRIOC | INTMSK4 */ + /* 85-87 unused/reserved */ + {88, 12, 20, 4, 18, 3}, /* MMCI0 */ + {89, 12, 20, 4, 17, 3}, /* MMCI1 */ + {90, 12, 20, 4, 16, 3}, /* MMCI2 */ + {91, 12, 20, 4, 15, 3}, /* MMCI3 */ + {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/ + /* 93-107 reserved/undocumented */ + {108,12, 4, 4, 1, 3}, /* ADC */ + {109,12, 0, 4, 0, 3}, /* CMTI */ + /* 110-111 reserved/unused */ +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) + { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2}, +#ifdef CONFIG_SH_RTC + { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, +#endif + { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + + { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + + { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, + { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, + { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, + { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, + { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, +#endif +}; + +void __init init_IRQ_intc2(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { + struct intc2_init *p = intc2_init_data + i; + make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, + p-> msk_offset, p->msk_shift, p->priority); + } +} + +/* Adds a termination callback to the interrupt */ +void intc2_add_clear_irq(int irq, int (*fn)(int)) +{ + if (unlikely(irq < INTC2_FIRST_IRQ)) + return; + + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; +} + diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 71f92096132..fdbd718ae5c 100644 --- a/arch/sh/kernel/cpu/irq_ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -1,6 +1,5 @@ -/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $ - * - * linux/arch/sh/kernel/irq_ipr.c +/* + * arch/sh/kernel/cpu/irq/ipr.c * * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi * Copyright (C) 2000 Kazumoto Kojima @@ -109,7 +108,8 @@ static void end_ipr_irq(unsigned int irq) enable_ipr_irq(irq); } -void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) +void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, + int priority, int maskpos) { disable_irq_nosync(irq); ipr_data[irq].addr = addr; @@ -120,126 +120,47 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) disable_ipr_irq(irq); } -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -static unsigned char pint_map[256]; -static unsigned long portcr_mask = 0; - -static void enable_pint_irq(unsigned int irq); -static void disable_pint_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_pint_irq disable_pint_irq - -static void mask_and_ack_pint(unsigned int); -static void end_pint_irq(unsigned int irq); - -static unsigned int startup_pint_irq(unsigned int irq) -{ - enable_pint_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type pint_irq_type = { - .typename = "PINT-IRQ", - .startup = startup_pint_irq, - .shutdown = shutdown_pint_irq, - .enable = enable_pint_irq, - .disable = disable_pint_irq, - .ack = mask_and_ack_pint, - .end = end_pint_irq -}; - -static void disable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - local_irq_save(flags); - val = ctrl_inw(INTC_INTER); - val &= ~(1 << (irq - PINT_IRQ_BASE)); - ctrl_outw(val, INTC_INTER); /* disable PINTn */ - portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); - local_irq_restore(flags); -} - -static void enable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - local_irq_save(flags); - val = ctrl_inw(INTC_INTER); - val |= 1 << (irq - PINT_IRQ_BASE); - ctrl_outw(val, INTC_INTER); /* enable PINTn */ - portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; - local_irq_restore(flags); -} - -static void mask_and_ack_pint(unsigned int irq) -{ - disable_pint_irq(irq); -} - -static void end_pint_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_pint_irq(irq); -} - -void make_pint_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &pint_irq_type; - disable_pint_irq(irq); -} -#endif - void __init init_IRQ(void) { -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) - int i; -#endif - - make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); - make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); +#ifndef CONFIG_CPU_SUBTYPE_SH7780 + make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0); + make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0); #if defined(CONFIG_SH_RTC) - make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); + make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0); #endif #ifdef SCI_ERI_IRQ - make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); #endif #ifdef SCIF1_ERI_IRQ - make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); + make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0); + make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); + make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); + make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0); #endif #ifdef SCIF_ERI_IRQ - make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); #endif #ifdef IRDA_ERI_IRQ - make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ @@ -254,86 +175,32 @@ void __init init_IRQ(void) * You should set corresponding bits of PFC to "00" * to enable these interrupts. */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY); - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); - make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY); - make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); - make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); - enable_ipr_irq(PINT0_IRQ); - enable_ipr_irq(PINT8_IRQ); + make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0); + make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0); + make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0); + make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0); + make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0); + make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0); +#endif +#endif - for(i = 0; i < 16; i++) - make_pint_irq(PINT_IRQ_BASE + i); - for(i = 0; i < 256; i++) - { - if(i & 1) pint_map[i] = 0; - else if(i & 2) pint_map[i] = 1; - else if(i & 4) pint_map[i] = 2; - else if(i & 8) pint_map[i] = 3; - else if(i & 0x10) pint_map[i] = 4; - else if(i & 0x20) pint_map[i] = 5; - else if(i & 0x40) pint_map[i] = 6; - else if(i & 0x80) pint_map[i] = 7; - } -#endif /* !CONFIG_CPU_SUBTYPE_SH7300 */ -#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/ +#ifdef CONFIG_CPU_HAS_PINT_IRQ + init_IRQ_pint(); +#endif -#ifdef CONFIG_CPU_SUBTYPE_ST40 +#ifdef CONFIG_CPU_HAS_INTC2_IRQ init_IRQ_intc2(); #endif - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) { + if (sh_mv.mv_init_irq != NULL) sh_mv.mv_init_irq(); - } } -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) + +#if !defined(CONFIG_CPU_HAS_PINT_IRQ) int ipr_irq_demux(int irq) { -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - unsigned long creg, dreg, d, sav; - - if(irq == PINT0_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PACR; - dreg = PORT_PADR; -#else - creg = PORT_PCCR; - dreg = PORT_PCDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | portcr_mask, creg); - d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + pint_map[d]; - } - else if(irq == PINT8_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PBCR; - dreg = PORT_PBDR; -#else - creg = PORT_PFCR; - dreg = PORT_PFDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | (portcr_mask >> 16), creg); - d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + 8 + pint_map[d]; - } -#endif return irq; } #endif EXPORT_SYMBOL(make_ipr_irq); - diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c new file mode 100644 index 00000000000..95d6024fe1a --- /dev/null +++ b/arch/sh/kernel/cpu/irq/pint.c @@ -0,0 +1,169 @@ +/* + * arch/sh/kernel/cpu/irq/pint.c - Interrupt handling for PINT-based IRQs. + * + * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi + * Copyright (C) 2000 Kazumoto Kojima + * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp> + * + * 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/config.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/module.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/machvec.h> + +static unsigned char pint_map[256]; +static unsigned long portcr_mask; + +static void enable_pint_irq(unsigned int irq); +static void disable_pint_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_pint_irq disable_pint_irq + +static void mask_and_ack_pint(unsigned int); +static void end_pint_irq(unsigned int irq); + +static unsigned int startup_pint_irq(unsigned int irq) +{ + enable_pint_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type pint_irq_type = { + .typename = "PINT-IRQ", + .startup = startup_pint_irq, + .shutdown = shutdown_pint_irq, + .enable = enable_pint_irq, + .disable = disable_pint_irq, + .ack = mask_and_ack_pint, + .end = end_pint_irq +}; + +static void disable_pint_irq(unsigned int irq) +{ + unsigned long val, flags; + + local_irq_save(flags); + val = ctrl_inw(INTC_INTER); + val &= ~(1 << (irq - PINT_IRQ_BASE)); + ctrl_outw(val, INTC_INTER); /* disable PINTn */ + portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); + local_irq_restore(flags); +} + +static void enable_pint_irq(unsigned int irq) +{ + unsigned long val, flags; + + local_irq_save(flags); + val = ctrl_inw(INTC_INTER); + val |= 1 << (irq - PINT_IRQ_BASE); + ctrl_outw(val, INTC_INTER); /* enable PINTn */ + portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; + local_irq_restore(flags); +} + +static void mask_and_ack_pint(unsigned int irq) +{ + disable_pint_irq(irq); +} + +static void end_pint_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pint_irq(irq); +} + +void make_pint_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &pint_irq_type; + disable_pint_irq(irq); +} + +void __init init_IRQ_pint(void) +{ + int i; + + make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); + make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); + + enable_irq(PINT0_IRQ); + enable_irq(PINT8_IRQ); + + for(i = 0; i < 16; i++) + make_pint_irq(PINT_IRQ_BASE + i); + + for(i = 0; i < 256; i++) { + if (i & 1) + pint_map[i] = 0; + else if (i & 2) + pint_map[i] = 1; + else if (i & 4) + pint_map[i] = 2; + else if (i & 8) + pint_map[i] = 3; + else if (i & 0x10) + pint_map[i] = 4; + else if (i & 0x20) + pint_map[i] = 5; + else if (i & 0x40) + pint_map[i] = 6; + else if (i & 0x80) + pint_map[i] = 7; + } +} + +int ipr_irq_demux(int irq) +{ + unsigned long creg, dreg, d, sav; + + if (irq == PINT0_IRQ) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + creg = PORT_PACR; + dreg = PORT_PADR; +#else + creg = PORT_PCCR; + dreg = PORT_PCDR; +#endif + sav = ctrl_inw(creg); + ctrl_outw(sav | portcr_mask, creg); + d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & + ctrl_inw(INTC_INTER) & 0xff; + ctrl_outw(sav, creg); + + if (d == 0) + return irq; + + return PINT_IRQ_BASE + pint_map[d]; + } else if (irq == PINT8_IRQ) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + creg = PORT_PBCR; + dreg = PORT_PBDR; +#else + creg = PORT_PFCR; + dreg = PORT_PFDR; +#endif + sav = ctrl_inw(creg); + ctrl_outw(sav | (portcr_mask >> 16), creg); + d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & + (ctrl_inw(INTC_INTER) >> 8) & 0xff; + ctrl_outw(sav, creg); + + if (d == 0) + return irq; + + return PINT_IRQ_BASE + 8 + pint_map[d]; + } + + return irq; +} + diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index a64532e4dc6..b54dbb9a0c8 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -4,3 +4,10 @@ obj-y := ex.o probe.o +clock-$(CONFIG_CPU_SH3) := clock-sh3.o +clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o +clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o +clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o + +obj-y += $(clock-y) + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c new file mode 100644 index 00000000000..c3c945958ba --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c @@ -0,0 +1,89 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh3.c + * + * Generic SH-3 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate *= pfc_divisors[idx]; +} + +static struct clk_ops sh3_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh3_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); + + clk->rate = clk->parent->rate / stc_multipliers[idx]; +} + +static struct clk_ops sh3_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); + + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh3_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh3_clk_ops[] = { + &sh3_master_clk_ops, + &sh3_module_clk_ops, + &sh3_bus_clk_ops, + &sh3_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh3_clk_ops)) + *ops = sh3_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7300.c b/arch/sh/kernel/cpu/sh3/clock-sh7300.c new file mode 100644 index 00000000000..e804174b962 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7300.c @@ -0,0 +1,78 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7300.c + * + * SH7300 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007]; +} + +static struct clk_ops sh7300_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8; + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4; + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7300_clk_ops[] = { + &sh7300_master_clk_ops, + &sh7300_module_clk_ops, + &sh7300_bus_clk_ops, + &sh7300_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7300_clk_ops)) + *ops = sh7300_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c new file mode 100644 index 00000000000..dfdbf3277fd --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c @@ -0,0 +1,84 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7705.c + * + * SH7705 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +/* + * SH7705 uses the same divisors as the generic SH-3 case, it's just the + * FRQCR layout that is a bit different.. + */ +static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003]; +} + +static struct clk_ops sh7705_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = ctrl_inw(FRQCR) & 0x0003; + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7705_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8; + clk->rate = clk->parent->rate / stc_multipliers[idx]; +} + +static struct clk_ops sh7705_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4; + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7705_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7705_clk_ops[] = { + &sh7705_master_clk_ops, + &sh7705_module_clk_ops, + &sh7705_bus_clk_ops, + &sh7705_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7705_clk_ops)) + *ops = sh7705_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c new file mode 100644 index 00000000000..10461a745e5 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c @@ -0,0 +1,96 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7709.c + * + * SH7709 support for the clock framework + * + * Copyright (C) 2005 Andriy Skulysh + * + * Based on arch/sh/kernel/cpu/sh3/clock-sh7705.c + * Copyright (C) 2005 Paul Mundt + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int stc_multipliers[] = { 1, 2, 4, 8, 3, 6, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; + +static void set_bus_parent(struct clk *clk) +{ + struct clk *bus_clk = clk_get("bus_clk"); + clk->parent = bus_clk; + clk_put(bus_clk); +} + +static void master_clk_init(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate *= pfc_divisors[idx]; +} + +static struct clk_ops sh7709_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7709_module_clk_ops = { +#ifdef CLOCK_MODE_0_1_2_7 + .init = set_bus_parent, +#endif + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = (frqcr & 0x0080) ? + ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1; + + clk->rate = clk->parent->rate * stc_multipliers[idx]; +} + +static struct clk_ops sh7709_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); + + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7709_cpu_clk_ops = { + .init = set_bus_parent, + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7709_clk_ops[] = { + &sh7709_master_clk_ops, + &sh7709_module_clk_ops, + &sh7709_bus_clk_ops, + &sh7709_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7709_clk_ops)) + *ops = sh7709_clk_ops[idx]; +} diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index ead1071eac7..3d5cafc71ae 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -5,6 +5,15 @@ obj-y := ex.o probe.o obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o +# Primary on-chip clocks (common) +clock-$(CONFIG_CPU_SH4) := clock-sh4.o +clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o +clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o +clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o + +# Additional clocks by subtype +clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o + +obj-y += $(clock-y) diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c new file mode 100644 index 00000000000..bfdf5fe8d94 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -0,0 +1,179 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh4-202.c + * + * Additional SH4-202 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * 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/err.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +#define CPG2_FRQCR3 0xfe0a0018 + +static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 }; +static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 }; + +static void emi_clk_recalc(struct clk *clk) +{ + int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static inline int frqcr3_lookup(struct clk *clk, unsigned long rate) +{ + int divisor = clk->parent->rate / rate; + int i; + + for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) + if (frqcr3_divisors[i] == divisor) + return frqcr3_values[i]; + + /* Safe fallback */ + return 5; +} + +static struct clk_ops sh4202_emi_clk_ops = { + .recalc = emi_clk_recalc, +}; + +static struct clk sh4202_emi_clk = { + .name = "emi_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_emi_clk_ops, +}; + +static void femi_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static struct clk_ops sh4202_femi_clk_ops = { + .recalc = femi_clk_recalc, +}; + +static struct clk sh4202_femi_clk = { + .name = "femi_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_femi_clk_ops, +}; + +static void shoc_clk_init(struct clk *clk) +{ + int i; + + /* + * For some reason, the shoc_clk seems to be set to some really + * insane value at boot (values outside of the allowable frequency + * range for instance). We deal with this by scaling it back down + * to something sensible just in case. + * + * Start scaling from the high end down until we find something + * that passes rate verification.. + */ + for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) { + int divisor = frqcr3_divisors[i]; + + if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0) + break; + } + + WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */ +} + +static void shoc_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) +{ + struct clk *bclk = clk_get("bus_clk"); + unsigned long bclk_rate = clk_get_rate(bclk); + + clk_put(bclk); + + if (rate > bclk_rate) + return 1; + if (rate > 66000000) + return 1; + + return 0; +} + +static int shoc_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long frqcr3; + unsigned int tmp; + + /* Make sure we have something sensible to switch to */ + if (shoc_clk_verify_rate(clk, rate) != 0) + return -EINVAL; + + tmp = frqcr3_lookup(clk, rate); + + frqcr3 = ctrl_inl(CPG2_FRQCR3); + frqcr3 &= ~(0x0007 << 6); + frqcr3 |= tmp << 6; + ctrl_outl(frqcr3, CPG2_FRQCR3); + + clk->rate = clk->parent->rate / frqcr3_divisors[tmp]; + + return 0; +} + +static struct clk_ops sh4202_shoc_clk_ops = { + .init = shoc_clk_init, + .recalc = shoc_clk_recalc, + .set_rate = shoc_clk_set_rate, +}; + +static struct clk sh4202_shoc_clk = { + .name = "shoc_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_shoc_clk_ops, +}; + +static struct clk *sh4202_onchip_clocks[] = { + &sh4202_emi_clk, + &sh4202_femi_clk, + &sh4202_shoc_clk, +}; + +static int __init sh4202_clk_init(void) +{ + struct clk *clk = clk_get("master_clk"); + int i; + + for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { + struct clk *clkp = sh4202_onchip_clocks[i]; + + clkp->parent = clk; + clk_register(clkp); + clk_enable(clkp); + } + + /* + * Now that we have the rest of the clocks registered, we need to + * force the parent clock to propagate so that these clocks will + * automatically figure out their rate. We cheat by handing the + * parent clock its current rate and forcing child propagation. + */ + clk_set_rate(clk, clk_get_rate(clk)); + + clk_put(clk); + + return 0; +} + +arch_initcall(sh4202_clk_init); + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c new file mode 100644 index 00000000000..dca9f87a12d --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c @@ -0,0 +1,80 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh4.c + * + * Generic SH-4 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; +#define bfc_divisors ifc_divisors /* Same */ +static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007]; +} + +static struct clk_ops sh4_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh4_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007; + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh4_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007; + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh4_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh4_clk_ops[] = { + &sh4_master_clk_ops, + &sh4_module_clk_ops, + &sh4_bus_clk_ops, + &sh4_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh4_clk_ops)) + *ops = sh4_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4/clock-sh73180.c new file mode 100644 index 00000000000..2fa5cb2ae68 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh73180.c @@ -0,0 +1,81 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh73180.c + * + * SH73180 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +/* + * SH73180 uses a common set of divisors, so this is quite simple.. + */ +static int divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= divisors[ctrl_inl(FRQCR) & 0x0007]; +} + +static struct clk_ops sh73180_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) >> 12) & 0x0007; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) >> 20) & 0x0007; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh73180_clk_ops[] = { + &sh73180_master_clk_ops, + &sh73180_module_clk_ops, + &sh73180_bus_clk_ops, + &sh73180_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh73180_clk_ops)) + *ops = sh73180_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4/clock-sh7770.c new file mode 100644 index 00000000000..c8694bac647 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh7770.c @@ -0,0 +1,73 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh7770.c + * + * SH7770 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int ifc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 1 }; +static int bfc_divisors[] = { 1, 1, 1, 1, 1, 8,12, 1 }; +static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f]; +} + +static struct clk_ops sh7770_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7770_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x000f); + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh7770_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7770_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7770_clk_ops[] = { + &sh7770_master_clk_ops, + &sh7770_module_clk_ops, + &sh7770_bus_clk_ops, + &sh7770_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7770_clk_ops)) + *ops = sh7770_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c new file mode 100644 index 00000000000..93ad367342c --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c @@ -0,0 +1,126 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh7780.c + * + * SH7780 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * 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 <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int ifc_divisors[] = { 2, 4 }; +static int bfc_divisors[] = { 1, 1, 1, 8, 12, 16, 24, 1 }; +static int pfc_divisors[] = { 1, 24, 24, 1 }; +static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003]; +} + +static struct clk_ops sh7780_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x0003); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7780_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007); + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh7780_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7780_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7780_clk_ops[] = { + &sh7780_master_clk_ops, + &sh7780_module_clk_ops, + &sh7780_bus_clk_ops, + &sh7780_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7780_clk_ops)) + *ops = sh7780_clk_ops[idx]; +} + +static void shyway_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007); + clk->rate = clk->parent->rate / cfc_divisors[idx]; +} + +static struct clk_ops sh7780_shyway_clk_ops = { + .recalc = shyway_clk_recalc, +}; + +static struct clk sh7780_shyway_clk = { + .name = "shyway_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh7780_shyway_clk_ops, +}; + +/* + * Additional SH7780-specific on-chip clocks that aren't already part of the + * clock framework + */ +static struct clk *sh7780_onchip_clocks[] = { + &sh7780_shyway_clk, +}; + +static int __init sh7780_clk_init(void) +{ + struct clk *clk = clk_get("master_clk"); + int i; + + for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { + struct clk *clkp = sh7780_onchip_clocks[i]; + + clkp->parent = clk; + clk_register(clkp); + clk_enable(clkp); + } + + /* + * Now that we have the rest of the clocks registered, we need to + * force the parent clock to propagate so that these clocks will + * automatically figure out their rate. We cheat by handing the + * parent clock its current rate and forcing child propagation. + */ + clk_set_rate(clk, clk_get_rate(clk)); + + clk_put(clk); + + return 0; +} + +arch_initcall(sh7780_clk_init); + diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c deleted file mode 100644 index f6b16ba0193..00000000000 --- a/arch/sh/kernel/cpu/sh4/irq_intc2.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * linux/arch/sh/kernel/irq_intc2.c - * - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Interrupt handling for INTC2-based IRQ. - * - * These are the "new Hitachi style" interrupts, as present on the - * Hitachi 7751 and the STM ST40 STB1. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/irq.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/machvec.h> - - -struct intc2_data { - unsigned char msk_offset; - unsigned char msk_shift; -#ifdef CONFIG_CPU_SUBTYPE_ST40 - int (*clear_irq) (int); -#endif -}; - - -static struct intc2_data intc2_data[NR_INTC2_IRQS]; - -static void enable_intc2_irq(unsigned int irq); -static void disable_intc2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_intc2_irq disable_intc2_irq - -static void mask_and_ack_intc2(unsigned int); -static void end_intc2_irq(unsigned int irq); - -static unsigned int startup_intc2_irq(unsigned int irq) -{ - enable_intc2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type intc2_irq_type = { - .typename = "INTC2-IRQ", - .startup = startup_intc2_irq, - .shutdown = shutdown_intc2_irq, - .enable = enable_intc2_irq, - .disable = disable_intc2_irq, - .ack = mask_and_ack_intc2, - .end = end_intc2_irq -}; - -static void disable_intc2_irq(unsigned int irq) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - // Sanity check - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1<<msk_shift, - INTC2_BASE+INTC2_INTMSK_OFFSET+msk_offset); -} - -static void enable_intc2_irq(unsigned int irq) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - /* Sanity check */ - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1<<msk_shift, - INTC2_BASE+INTC2_INTMSKCLR_OFFSET+msk_offset); -} - -static void mask_and_ack_intc2(unsigned int irq) -{ - disable_intc2_irq(irq); -} - -static void end_intc2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_intc2_irq(irq); - -#ifdef CONFIG_CPU_SUBTYPE_ST40 - if (intc2_data[irq - INTC2_FIRST_IRQ].clear_irq) - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq (irq); -#endif -} - -/* - * Setup an INTC2 style interrupt. - * NOTE: Unlike IPR interrupts, parameters are not shifted by this code, - * allowing the use of the numbers straight out of the datasheet. - * For example: - * PIO1 which is INTPRI00[19,16] and INTMSK00[13] - * would be: ^ ^ ^ ^ - * | | | | - * make_intc2_irq(84, 0, 16, 0, 13); - */ -void make_intc2_irq(unsigned int irq, - unsigned int ipr_offset, unsigned int ipr_shift, - unsigned int msk_offset, unsigned int msk_shift, - unsigned int priority) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - unsigned int flags; - unsigned long ipr; - - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - disable_irq_nosync(irq); - - /* Fill the data we need */ - intc2_data[irq_offset].msk_offset = msk_offset; - intc2_data[irq_offset].msk_shift = msk_shift; -#ifdef CONFIG_CPU_SUBTYPE_ST40 - intc2_data[irq_offset].clear_irq = NULL; -#endif - - /* Set the priority level */ - local_irq_save(flags); - - ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset); - ipr&=~(0xf<<ipr_shift); - ipr|=(priority)<<ipr_shift; - ctrl_outl(ipr, INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset); - - local_irq_restore(flags); - - irq_desc[irq].handler=&intc2_irq_type; - - disable_intc2_irq(irq); -} - -#ifdef CONFIG_CPU_SUBTYPE_ST40 - -struct intc2_init { - unsigned short irq; - unsigned char ipr_offset, ipr_shift; - unsigned char msk_offset, msk_shift; -}; - -static struct intc2_init intc2_init_data[] __initdata = { - {64, 0, 0, 0, 0}, /* PCI serr */ - {65, 0, 4, 0, 1}, /* PCI err */ - {66, 0, 4, 0, 2}, /* PCI ad */ - {67, 0, 4, 0, 3}, /* PCI pwd down */ - {72, 0, 8, 0, 5}, /* DMAC INT0 */ - {73, 0, 8, 0, 6}, /* DMAC INT1 */ - {74, 0, 8, 0, 7}, /* DMAC INT2 */ - {75, 0, 8, 0, 8}, /* DMAC INT3 */ - {76, 0, 8, 0, 9}, /* DMAC INT4 */ - {78, 0, 8, 0, 11}, /* DMAC ERR */ - {80, 0, 12, 0, 12}, /* PIO0 */ - {84, 0, 16, 0, 13}, /* PIO1 */ - {88, 0, 20, 0, 14}, /* PIO2 */ - {112, 4, 0, 4, 0}, /* Mailbox */ -#ifdef CONFIG_CPU_SUBTYPE_ST40GX1 - {116, 4, 4, 4, 4}, /* SSC0 */ - {120, 4, 8, 4, 8}, /* IR Blaster */ - {124, 4, 12, 4, 12}, /* USB host */ - {128, 4, 16, 4, 16}, /* Video processor BLITTER */ - {132, 4, 20, 4, 20}, /* UART0 */ - {134, 4, 20, 4, 22}, /* UART2 */ - {136, 4, 24, 4, 24}, /* IO_PIO0 */ - {140, 4, 28, 4, 28}, /* EMPI */ - {144, 8, 0, 8, 0}, /* MAFE */ - {148, 8, 4, 8, 4}, /* PWM */ - {152, 8, 8, 8, 8}, /* SSC1 */ - {156, 8, 12, 8, 12}, /* IO_PIO1 */ - {160, 8, 16, 8, 16}, /* USB target */ - {164, 8, 20, 8, 20}, /* UART1 */ - {168, 8, 24, 8, 24}, /* Teletext */ - {172, 8, 28, 8, 28}, /* VideoSync VTG */ - {173, 8, 28, 8, 29}, /* VideoSync DVP0 */ - {174, 8, 28, 8, 30}, /* VideoSync DVP1 */ -#endif -}; - -void __init init_IRQ_intc2(void) -{ - struct intc2_init *p; - - printk(KERN_ALERT "init_IRQ_intc2\n"); - - for (p = intc2_init_data; - p<intc2_init_data+ARRAY_SIZE(intc2_init_data); - p++) { - make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, - p-> msk_offset, p->msk_shift, 13); - } -} - -/* Adds a termination callback to the interrupt */ -void intc2_add_clear_irq(int irq, int (*fn)(int)) -{ - if (irq < INTC2_FIRST_IRQ) - return; - - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; -} - -#endif /* CONFIG_CPU_SUBTYPE_ST40 */ diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c index d9932f25993..71c9fde2fd9 100644 --- a/arch/sh/kernel/io.c +++ b/arch/sh/kernel/io.c @@ -2,58 +2,73 @@ * linux/arch/sh/kernel/io.c * * Copyright (C) 2000 Stuart Menefy + * Copyright (C) 2005 Paul Mundt * * Provide real functions which expand to whatever the header file defined. * Also definitions of machine independent IO functions. + * + * 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 <asm/io.h> #include <linux/module.h> +#include <asm/machvec.h> +#include <asm/io.h> /* * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void memcpy_fromio(void * to, unsigned long from, unsigned long count) +void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count) { char *p = to; while (count) { count--; - *p = readb(from); + *p = readb((void __iomem *)from); p++; from++; } } - +EXPORT_SYMBOL(memcpy_fromio); + /* * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void memcpy_toio(unsigned long to, const void * from, unsigned long count) +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count) { const char *p = from; while (count) { count--; - writeb(*p, to); + writeb(*p, (void __iomem *)to); p++; to++; } } - +EXPORT_SYMBOL(memcpy_toio); + /* * "memset" on IO memory space. * This needs to be optimized. */ -void memset_io(unsigned long dst, int c, unsigned long count) +void memset_io(volatile void __iomem *dst, int c, unsigned long count) { while (count) { count--; - writeb(c, dst); + writeb(c, (void __iomem *)dst); dst++; } } - -EXPORT_SYMBOL(memcpy_fromio); -EXPORT_SYMBOL(memcpy_toio); EXPORT_SYMBOL(memset_io); +void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return sh_mv.mv_ioport_map(port, nr); +} +EXPORT_SYMBOL(ioport_map); + +void ioport_unmap(void __iomem *addr) +{ + sh_mv.mv_ioport_unmap(addr); +} +EXPORT_SYMBOL(ioport_unmap); diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index a911b0149d1..28ec7487de8 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -3,6 +3,7 @@ * linux/arch/sh/kernel/io_generic.c * * Copyright (C) 2000 Niibe Yutaka + * Copyright (C) 2005 Paul Mundt * * Generic I/O routine. These can be used where a machine specific version * is not required. @@ -10,21 +11,20 @@ * 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/module.h> #include <asm/io.h> #include <asm/machvec.h> -#include <linux/module.h> -#if defined(CONFIG_CPU_SH3) +#ifdef CONFIG_CPU_SH3 +/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a + * workaround. */ /* I'm not sure SH7709 has this kind of bug */ -#define SH3_PCMCIA_BUG_WORKAROUND 1 -#define DUMMY_READ_AREA6 0xba000000 +#define dummy_read() ctrl_inb(0xba000000) +#else +#define dummy_read() #endif -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) - unsigned long generic_io_base; static inline void delay(void) @@ -32,40 +32,40 @@ static inline void delay(void) ctrl_inw(0xa0000000); } -unsigned char generic_inb(unsigned long port) +u8 generic_inb(unsigned long port) { - return *(volatile unsigned char*)PORT2ADDR(port); + return ctrl_inb((unsigned long __force)ioport_map(port, 1)); } -unsigned short generic_inw(unsigned long port) +u16 generic_inw(unsigned long port) { - return *(volatile unsigned short*)PORT2ADDR(port); + return ctrl_inw((unsigned long __force)ioport_map(port, 2)); } -unsigned int generic_inl(unsigned long port) +u32 generic_inl(unsigned long port) { - return *(volatile unsigned long*)PORT2ADDR(port); + return ctrl_inl((unsigned long __force)ioport_map(port, 4)); } -unsigned char generic_inb_p(unsigned long port) +u8 generic_inb_p(unsigned long port) { - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + unsigned long v = generic_inb(port); delay(); return v; } -unsigned short generic_inw_p(unsigned long port) +u16 generic_inw_p(unsigned long port) { - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + unsigned long v = generic_inw(port); delay(); return v; } -unsigned int generic_inl_p(unsigned long port) +u32 generic_inl_p(unsigned long port) { - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + unsigned long v = generic_inl(port); delay(); return v; @@ -77,75 +77,70 @@ unsigned int generic_inl_p(unsigned long port) * convert the port address to real address once. */ -void generic_insb(unsigned long port, void *buffer, unsigned long count) +void generic_insb(unsigned long port, void *dst, unsigned long count) { - volatile unsigned char *port_addr; - unsigned char *buf=buffer; - - port_addr = (volatile unsigned char *)PORT2ADDR(port); + volatile u8 *port_addr; + u8 *buf = dst; - while(count--) - *buf++ = *port_addr; + port_addr = (volatile u8 *)ioport_map(port, 1); + while (count--) + *buf++ = *port_addr; } -void generic_insw(unsigned long port, void *buffer, unsigned long count) +void generic_insw(unsigned long port, void *dst, unsigned long count) { - volatile unsigned short *port_addr; - unsigned short *buf=buffer; + volatile u16 *port_addr; + u16 *buf = dst; - port_addr = (volatile unsigned short *)PORT2ADDR(port); + port_addr = (volatile u16 *)ioport_map(port, 2); + while (count--) + *buf++ = *port_addr; - while(count--) - *buf++ = *port_addr; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_insl(unsigned long port, void *buffer, unsigned long count) +void generic_insl(unsigned long port, void *dst, unsigned long count) { - volatile unsigned long *port_addr; - unsigned long *buf=buffer; + volatile u32 *port_addr; + u32 *buf = dst; - port_addr = (volatile unsigned long *)PORT2ADDR(port); + port_addr = (volatile u32 *)ioport_map(port, 4); + while (count--) + *buf++ = *port_addr; - while(count--) - *buf++ = *port_addr; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_outb(unsigned char b, unsigned long port) +void generic_outb(u8 b, unsigned long port) { - *(volatile unsigned char*)PORT2ADDR(port) = b; + ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); } -void generic_outw(unsigned short b, unsigned long port) +void generic_outw(u16 b, unsigned long port) { - *(volatile unsigned short*)PORT2ADDR(port) = b; + ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); } -void generic_outl(unsigned int b, unsigned long port) +void generic_outl(u32 b, unsigned long port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); } -void generic_outb_p(unsigned char b, unsigned long port) +void generic_outb_p(u8 b, unsigned long port) { - *(volatile unsigned char*)PORT2ADDR(port) = b; + generic_outb(b, port); delay(); } -void generic_outw_p(unsigned short b, unsigned long port) +void generic_outw_p(u16 b, unsigned long port) { - *(volatile unsigned short*)PORT2ADDR(port) = b; + generic_outw(b, port); delay(); } -void generic_outl_p(unsigned int b, unsigned long port) +void generic_outl_p(u32 b, unsigned long port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + generic_outl(b, port); delay(); } @@ -154,90 +149,77 @@ void generic_outl_p(unsigned int b, unsigned long port) * address. However as the port address doesn't change we only need to * convert the port address to real address once. */ - -void generic_outsb(unsigned long port, const void *buffer, unsigned long count) +void generic_outsb(unsigned long port, const void *src, unsigned long count) { - volatile unsigned char *port_addr; - const unsigned char *buf=buffer; + volatile u8 *port_addr; + const u8 *buf = src; - port_addr = (volatile unsigned char *)PORT2ADDR(port); + port_addr = (volatile u8 __force *)ioport_map(port, 1); - while(count--) - *port_addr = *buf++; + while (count--) + *port_addr = *buf++; } -void generic_outsw(unsigned long port, const void *buffer, unsigned long count) +void generic_outsw(unsigned long port, const void *src, unsigned long count) { - volatile unsigned short *port_addr; - const unsigned short *buf=buffer; + volatile u16 *port_addr; + const u16 *buf = src; - port_addr = (volatile unsigned short *)PORT2ADDR(port); + port_addr = (volatile u16 __force *)ioport_map(port, 2); - while(count--) - *port_addr = *buf++; + while (count--) + *port_addr = *buf++; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_outsl(unsigned long port, const void *buffer, unsigned long count) +void generic_outsl(unsigned long port, const void *src, unsigned long count) { - volatile unsigned long *port_addr; - const unsigned long *buf=buffer; + volatile u32 *port_addr; + const u32 *buf = src; - port_addr = (volatile unsigned long *)PORT2ADDR(port); + port_addr = (volatile u32 __force *)ioport_map(port, 4); + while (count--) + *port_addr = *buf++; - while(count--) - *port_addr = *buf++; - -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -unsigned char generic_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; + dummy_read(); } -unsigned short generic_readw(unsigned long addr) +u8 generic_readb(void __iomem *addr) { - return *(volatile unsigned short*)addr; + return ctrl_inb((unsigned long __force)addr); } -unsigned int generic_readl(unsigned long addr) +u16 generic_readw(void __iomem *addr) { - return *(volatile unsigned long*)addr; + return ctrl_inw((unsigned long __force)addr); } -void generic_writeb(unsigned char b, unsigned long addr) +u32 generic_readl(void __iomem *addr) { - *(volatile unsigned char*)addr = b; + return ctrl_inl((unsigned long __force)addr); } -void generic_writew(unsigned short b, unsigned long addr) +void generic_writeb(u8 b, void __iomem *addr) { - *(volatile unsigned short*)addr = b; + ctrl_outb(b, (unsigned long __force)addr); } -void generic_writel(unsigned int b, unsigned long addr) +void generic_writew(u16 b, void __iomem *addr) { - *(volatile unsigned long*)addr = b; + ctrl_outw(b, (unsigned long __force)addr); } -void * generic_ioremap(unsigned long offset, unsigned long size) +void generic_writel(u32 b, void __iomem *addr) { - return (void *) P2SEGADDR(offset); + ctrl_outl(b, (unsigned long __force)addr); } -EXPORT_SYMBOL(generic_ioremap); -void generic_iounmap(void *addr) +void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) { + return (void __iomem *)(addr + generic_io_base); } -EXPORT_SYMBOL(generic_iounmap); -unsigned long generic_isa_port2addr(unsigned long offset) +void generic_ioport_unmap(void __iomem *addr) { - return offset + generic_io_base; } diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 54c171225b7..6883c00728c 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -8,38 +8,13 @@ * SuperH version: Copyright (C) 1999 Niibe Yutaka */ -/* - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/ioport.h> +#include <linux/irq.h> #include <linux/interrupt.h> -#include <linux/timex.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/init.h> +#include <linux/kernel_stat.h> #include <linux/seq_file.h> -#include <linux/kallsyms.h> -#include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/pgalloc.h> -#include <asm/delay.h> #include <asm/irq.h> -#include <linux/irq.h> - +#include <asm/processor.h> +#include <asm/cpu/mmu_context.h> /* * 'what should we do if we get a hw irq event on an illegal vector'. @@ -66,7 +41,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); } - if (i < ACTUAL_NR_IRQS) { + if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) @@ -86,19 +61,32 @@ unlock: } #endif + asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) -{ - int irq; +{ + int irq = r4; irq_enter(); - asm volatile("stc r2_bank, %0\n\t" - "shlr2 %0\n\t" - "shlr2 %0\n\t" - "shlr %0\n\t" - "add #-16, %0\n\t" - :"=z" (irq)); + +#ifdef CONFIG_CPU_HAS_INTEVT + __asm__ __volatile__ ( +#ifdef CONFIG_CPU_HAS_SR_RB + "stc r2_bank, %0\n\t" +#else + "mov.l @%1, %0\n\t" +#endif + "shlr2 %0\n\t" + "shlr2 %0\n\t" + "shlr %0\n\t" + "add #-16, %0\n\t" + : "=z" (irq), "=r" (r4) + : "1" (INTEVT) + : "memory" + ); +#endif + irq = irq_demux(irq); __do_IRQ(irq, ®s); irq_exit(); diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c new file mode 100644 index 00000000000..43546525f28 --- /dev/null +++ b/arch/sh/kernel/machine_kexec.c @@ -0,0 +1,112 @@ +/* + * machine_kexec.c - handle transition of Linux booting another kernel + * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> + * + * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz + * LANDISK/sh4 supported by kogiidena + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include <linux/mm.h> +#include <linux/kexec.h> +#include <linux/delay.h> +#include <linux/reboot.h> +#include <asm/pgtable.h> +#include <asm/pgalloc.h> +#include <asm/mmu_context.h> +#include <asm/io.h> +#include <asm/cacheflush.h> + +typedef NORET_TYPE void (*relocate_new_kernel_t)( + unsigned long indirection_page, + unsigned long reboot_code_buffer, + unsigned long start_address, + unsigned long vbr_reg) ATTRIB_NORET; + +const extern unsigned char relocate_new_kernel[]; +const extern unsigned int relocate_new_kernel_size; +extern void *gdb_vbr_vector; + +/* + * Provide a dummy crash_notes definition while crash dump arrives to ppc. + * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. + */ +void *crash_notes = NULL; + +void machine_shutdown(void) +{ +} + +void machine_crash_shutdown(struct pt_regs *regs) +{ +} + +/* + * Do what every setup is needed on image and the + * reboot code buffer to allow us to avoid allocations + * later. + */ +int machine_kexec_prepare(struct kimage *image) +{ + return 0; +} + +void machine_kexec_cleanup(struct kimage *image) +{ +} + +static void kexec_info(struct kimage *image) +{ + int i; + printk("kexec information\n"); + for (i = 0; i < image->nr_segments; i++) { + printk(" segment[%d]: 0x%08x - 0x%08x (0x%08x)\n", + i, + (unsigned int)image->segment[i].mem, + (unsigned int)image->segment[i].mem + image->segment[i].memsz, + (unsigned int)image->segment[i].memsz); + } + printk(" start : 0x%08x\n\n", (unsigned int)image->start); +} + + +/* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. + */ +NORET_TYPE void machine_kexec(struct kimage *image) +{ + + unsigned long page_list; + unsigned long reboot_code_buffer; + unsigned long vbr_reg; + relocate_new_kernel_t rnk; + +#if defined(CONFIG_SH_STANDARD_BIOS) + vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100; +#else + vbr_reg = 0x80000000; // dummy +#endif + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + page_list = image->head; + + /* we need both effective and real address here */ + reboot_code_buffer = + (unsigned long)page_address(image->control_code_page); + + /* copy our kernel relocation code to the control code page */ + memcpy((void *)reboot_code_buffer, relocate_new_kernel, + relocate_new_kernel_size); + + kexec_info(image); + flush_cache_all(); + + /* now call it */ + rnk = (relocate_new_kernel_t) reboot_code_buffer; + (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); +} + diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index aac15e42d03..a4dc2b532e1 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -71,6 +71,16 @@ void cpu_idle(void) void machine_restart(char * __unused) { + +#ifdef CONFIG_KEXEC + struct kimage *image; + image = xchg(&kexec_image, 0); + if (image) { + machine_shutdown(); + machine_kexec(image); + } +#endif + /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ asm volatile("ldc %0, sr\n\t" "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S new file mode 100644 index 00000000000..b0695cffec6 --- /dev/null +++ b/arch/sh/kernel/relocate_kernel.S @@ -0,0 +1,102 @@ +/* + * relocate_kernel.S - put the kernel image in place to boot + * 2005.9.17 kogiidena@eggplant.ddo.jp + * + * LANDISK/sh4 is supported. Maybe, SH archtecture works well. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include <linux/config.h> +#include <linux/linkage.h> + +#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */ + + + .globl relocate_new_kernel +relocate_new_kernel: + /* r4 = indirection_page */ + /* r5 = reboot_code_buffer */ + /* r6 = start_address */ + /* r7 = vbr_reg */ + + mov.l 10f,r8 /* 4096 */ + mov.l 11f,r9 /* 0xa0000000 */ + + /* stack setting */ + add r8,r5 + mov r5,r15 + + bra 1f + mov r4,r0 /* cmd = indirection_page */ +0: + mov.l @r4+,r0 /* cmd = *ind++ */ + +1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ + mov r0,r2 + or r9,r2 + mov #-16,r1 + and r1,r2 + + /* if(cmd & IND_DESTINATION) dst = addr */ + tst #1,r0 + bt 2f + bra 0b + mov r2,r5 + +2: /* else if(cmd & IND_INDIRECTION) ind = addr */ + tst #2,r0 + bt 3f + bra 0b + mov r2,r4 + +3: /* else if(cmd & IND_DONE) goto 6 */ + tst #4,r0 + bt 4f + bra 6f + nop + +4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */ + tst #8,r0 + bt 0b + + mov r8,r3 + shlr2 r3 + shlr2 r3 +5: + dt r3 + mov.l @r2+,r1 /* 16n+0 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+4 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+8 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+12 */ + mov.l r1,@r5 + add #4,r5 + bf 5b + + bra 0b + nop +6: +#ifdef CONFIG_SH_STANDARD_BIOS + ldc r7, vbr +#endif + jmp @r6 + nop + + .align 2 +10: + .long PAGE_SIZE +11: + .long 0xa0000000 + +relocate_new_kernel_end: + + .globl relocate_new_kernel_size +relocate_new_kernel_size: + .long relocate_new_kernel_end - relocate_new_kernel diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 671b876416b..314a275c04e 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -3,7 +3,7 @@ * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> * * Some code taken from i386 version. @@ -11,50 +11,21 @@ */ #include <linux/config.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/sched.h> #include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/delay.h> +#include <linux/module.h> #include <linux/init.h> -#include <linux/smp.h> #include <linux/profile.h> - -#include <asm/processor.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/delay.h> -#include <asm/machvec.h> +#include <asm/clock.h> #include <asm/rtc.h> -#include <asm/freq.h> -#include <asm/cpu/timer.h> -#ifdef CONFIG_SH_KGDB +#include <asm/timer.h> #include <asm/kgdb.h> -#endif - -#include <linux/timex.h> -#include <linux/irq.h> - -#define TMU_TOCR_INIT 0x00 -#define TMU0_TCR_INIT 0x0020 -#define TMU_TSTR_INIT 1 - -#define TMU0_TCR_CALIB 0x0000 - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 -#define CLOCKGEN_MEMCLKCR 0xbb040038 -#define MEMCLKCR_RATIO_MASK 0x7 -#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */ extern unsigned long wall_jiffies; -#define TICK_SIZE (tick_nsec / 1000) -DEFINE_SPINLOCK(tmu0_lock); +struct sys_timer *sys_timer; + +/* Move this somewhere more sensible.. */ +DEFINE_SPINLOCK(rtc_lock); +EXPORT_SYMBOL(rtc_lock); /* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want * these routines anywhere... */ @@ -66,98 +37,14 @@ void (*rtc_get_time)(struct timespec *); int (*rtc_set_time)(const time_t); #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; -#endif -#if defined(CONFIG_CPU_SH3) -static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; -static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; -#define bfc_divisors stc_multipliers -#define bfc_values stc_values -static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; -static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 }; -static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; -static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; -#elif defined(CONFIG_CPU_SH4) -#if defined(CONFIG_CPU_SUBTYPE_SH73180) -static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; -static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; -#define bfc_divisors ifc_divisors /* Same */ -#define bfc_values ifc_values -#define pfc_divisors ifc_divisors /* Same */ -#define pfc_values ifc_values -#else -static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; -static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 }; -#define bfc_divisors ifc_divisors /* Same */ -#define bfc_values ifc_values -static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; -static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 }; -#endif -#else -#error "Unknown ifc/bfc/pfc/stc values for this processor" -#endif - /* * Scheduler clock - returns current time in nanosec units. */ -unsigned long long sched_clock(void) +unsigned long long __attribute__ ((weak)) sched_clock(void) { return (unsigned long long)jiffies * (1000000000 / HZ); } -static unsigned long do_gettimeoffset(void) -{ - int count; - unsigned long flags; - - static int count_p = 0x7fffffff; /* for the first call after boot */ - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; - - spin_lock_irqsave(&tmu0_lock, flags); - /* timer count may underflow right here */ - count = ctrl_inl(TMU0_TCNT); /* read the latched count */ - - jiffies_t = jiffies; - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there is one kind of problem that must be avoided here: - * 1. the timer counter underflows - */ - - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - - if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); - } - } - } else - jiffies_p = jiffies_t; - - count_p = count; - spin_unlock_irqrestore(&tmu0_lock, flags); - - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; - - return count; -} - void do_gettimeofday(struct timeval *tv) { unsigned long seq; @@ -166,7 +53,7 @@ void do_gettimeofday(struct timeval *tv) do { seq = read_seqbegin(&xtime_lock); - usec = do_gettimeoffset(); + usec = get_timer_offset(); lost = jiffies - wall_jiffies; if (lost) @@ -202,7 +89,7 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - nsec -= 1000 * (do_gettimeoffset() + + nsec -= 1000 * (get_timer_offset() + (jiffies - wall_jiffies) * (1000000 / HZ)); wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); @@ -224,10 +111,10 @@ EXPORT_SYMBOL(do_settimeofday); static long last_rtc_update; /* - * timer_interrupt() needs to keep up the real-time clock, + * handle_timer_tick() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void do_timer_interrupt(int irq, struct pt_regs *regs) +void handle_timer_tick(struct pt_regs *regs) { do_timer(regs); #ifndef CONFIG_SMP @@ -252,337 +139,35 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs) if (rtc_set_time(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + /* do it again in 60s */ + last_rtc_update = xtime.tv_sec - 600; } } -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long timer_status; - - /* Clear UNF bit */ - timer_status = ctrl_inw(TMU0_TCR); - timer_status &= ~0x100; - ctrl_outw(timer_status, TMU0_TCR); - - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, regs); - write_sequnlock(&xtime_lock); - - return IRQ_HANDLED; -} - -/* - * Hah! We'll see if this works (switching from usecs to nsecs). - */ -static unsigned int __init get_timer_frequency(void) -{ - u32 freq; - struct timespec ts1, ts2; - unsigned long diff_nsec; - unsigned long factor; - - /* Setup the timer: We don't want to generate interrupts, just - * have it count down at its natural rate. - */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); - ctrl_outl(0xffffffff, TMU0_TCOR); - ctrl_outl(0xffffffff, TMU0_TCNT); - - rtc_get_time(&ts2); - - do { - rtc_get_time(&ts1); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - /* actually start the timer */ - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); - - do { - rtc_get_time(&ts2); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - freq = 0xffffffff - ctrl_inl(TMU0_TCNT); - if (ts2.tv_nsec < ts1.tv_nsec) { - ts2.tv_nsec += 1000000000; - ts2.tv_sec--; - } - - diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); - - /* this should work well if the RTC has a precision of n Hz, where - * n is an integer. I don't think we have to worry about the other - * cases. */ - factor = (1000000000 + diff_nsec/2) / diff_nsec; - - if (factor * diff_nsec > 1100000000 || - factor * diff_nsec < 900000000) - panic("weird RTC (diff_nsec %ld)", diff_nsec); - - return freq * factor; -} - -void (*board_time_init)(void); -void (*board_timer_setup)(struct irqaction *irq); - -static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ; - -static int __init sh_pclk_setup(char *str) -{ - unsigned int freq; - - if (get_option(&str, &freq)) - sh_pclk_freq = freq; - - return 1; -} -__setup("sh_pclk=", sh_pclk_setup); - -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; - -void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc) -{ - unsigned int frqcr = ctrl_inw(FRQCR); - -#if defined(CONFIG_CPU_SH3) -#if defined(CONFIG_CPU_SUBTYPE_SH7300) - *ifc = md_table[((frqcr & 0x0070) >> 4)]; - *bfc = md_table[((frqcr & 0x0700) >> 8)]; - *pfc = md_table[frqcr & 0x0007]; -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) - *bfc = stc_multipliers[(frqcr & 0x0300) >> 8]; - *ifc = ifc_divisors[(frqcr & 0x0030) >> 4]; - *pfc = pfc_divisors[frqcr & 0x0003]; -#else - unsigned int tmp; - - tmp = (frqcr & 0x8000) >> 13; - tmp |= (frqcr & 0x0030) >> 4; - *bfc = stc_multipliers[tmp]; - tmp = (frqcr & 0x4000) >> 12; - tmp |= (frqcr & 0x000c) >> 2; - *ifc = ifc_divisors[tmp]; - tmp = (frqcr & 0x2000) >> 11; - tmp |= frqcr & 0x0003; - *pfc = pfc_divisors[tmp]; -#endif -#elif defined(CONFIG_CPU_SH4) -#if defined(CONFIG_CPU_SUBTYPE_SH73180) - *ifc = ifc_divisors[(frqcr>> 20) & 0x0007]; - *bfc = bfc_divisors[(frqcr>> 12) & 0x0007]; - *pfc = pfc_divisors[frqcr & 0x0007]; -#else - *ifc = ifc_divisors[(frqcr >> 6) & 0x0007]; - *bfc = bfc_divisors[(frqcr >> 3) & 0x0007]; - *pfc = pfc_divisors[frqcr & 0x0007]; -#endif -#endif -} - -/* - * This bit of ugliness builds up accessor routines to get at both - * the divisors and the physical values. - */ -#define _FREQ_TABLE(x) \ - unsigned int get_##x##_divisor(unsigned int value) \ - { return x##_divisors[value]; } \ - \ - unsigned int get_##x##_value(unsigned int divisor) \ - { return x##_values[(divisor - 1)]; } - -_FREQ_TABLE(ifc); -_FREQ_TABLE(bfc); -_FREQ_TABLE(pfc); - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - -/* - * The ST40 divisors are totally different so we set the cpu data - * clocks using a different algorithm - * - * I've just plugged this from the 2.4 code - * - Alex Bennee <kernel-hacker@bennee.com> - */ -#define CCN_PVR_CHIP_SHIFT 24 -#define CCN_PVR_CHIP_MASK 0xff -#define CCN_PVR_CHIP_ST40STB1 0x4 - - -struct frqcr_data { - unsigned short frqcr; - - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; -}; - -static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, +static struct sysdev_class timer_sysclass = { + set_kset_name("timer"), }; -struct memclk_data { - unsigned char multiplier; - unsigned char divisor; -}; - -static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 -}; - -static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr) +static int __init timer_init_sysfs(void) { - unsigned int cpu_clock, master_clock, bus_clock, memory_clock; - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; + int ret = sysdev_class_register(&timer_sysclass); + if (ret != 0) + return ret; - for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) { - d = &st40_frqcr_table[a]; - - if (d->frqcr == (frqcr & 0x1ff)) - break; - } + sys_timer->dev.cls = &timer_sysclass; + return sysdev_register(&sys_timer->dev); +} - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; +device_initcall(timer_init_sysfs); - printk("ERROR: Unrecognised FRQCR value (0x%x), " - "using default multipliers\n", frqcr); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d " - "Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - master_clock = module_clock * d->factor[2].divisor - / d->factor[2].multiplier; - bus_clock = master_clock * d->factor[1].multiplier - / d->factor[1].divisor; - memory_clock = master_clock * e->multiplier - / e->divisor; - cpu_clock = master_clock * d->factor[0].multiplier - / d->factor[0].divisor; - - current_cpu_data.cpu_clock = cpu_clock; - current_cpu_data.master_clock = master_clock; - current_cpu_data.bus_clock = bus_clock; - current_cpu_data.memory_clock = memory_clock; - current_cpu_data.module_clock = module_clock; -} -#endif +void (*board_time_init)(void); void __init time_init(void) { - unsigned int timer_freq = 0; - unsigned int ifc, pfc, bfc; - unsigned long interval; -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - unsigned long pvr; - unsigned short frqcr; -#endif - if (board_time_init) board_time_init(); - /* - * If we don't have an RTC (such as with the SH7300), don't attempt to - * probe the timer frequency. Rely on an either hardcoded peripheral - * clock value, or on the sh_pclk command line option. Note that we - * still need to have CONFIG_SH_PCLK_FREQ set in order for things like - * CLOCK_TICK_RATE to be sane. - */ - current_cpu_data.module_clock = sh_pclk_freq; - -#ifdef CONFIG_SH_PCLK_CALC - /* XXX: Switch this over to a more generic test. */ - { - unsigned int freq; - - /* - * If we've specified a peripheral clock frequency, and we have - * an RTC, compare it against the autodetected value. Complain - * if there's a mismatch. - */ - timer_freq = get_timer_frequency(); - freq = timer_freq * 4; - - if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) { - printk(KERN_NOTICE "Calculated peripheral clock value " - "%d differs from sh_pclk value %d, fixing..\n", - freq, sh_pclk_freq); - current_cpu_data.module_clock = freq; - } - } -#endif - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - /* XXX: Update ST40 code to use board_time_init() */ - pvr = ctrl_inl(CCN_PVR); - frqcr = ctrl_inw(FRQCR); - printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr); - - if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) - st40_specific_time_init(current_cpu_data.module_clock, frqcr); - else -#endif - get_current_frequency_divisors(&ifc, &bfc, &pfc); + clk_init(); if (rtc_get_time) { rtc_get_time(&xtime); @@ -594,51 +179,12 @@ void __init time_init(void) set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - if (board_timer_setup) { - board_timer_setup(&irq0); - } else { - setup_irq(TIMER_IRQ, &irq0); - } - /* - * for ST40 chips the current_cpu_data should already be set - * so not having valid pfc/bfc/ifc shouldn't be a problem + * Find the timer to use as the system timer, it will be + * initialized for us. */ - if (!current_cpu_data.master_clock) - current_cpu_data.master_clock = current_cpu_data.module_clock * pfc; - if (!current_cpu_data.bus_clock) - current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc; - if (!current_cpu_data.cpu_clock) - current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc; - - printk("CPU clock: %d.%02dMHz\n", - (current_cpu_data.cpu_clock / 1000000), - (current_cpu_data.cpu_clock % 1000000)/10000); - printk("Bus clock: %d.%02dMHz\n", - (current_cpu_data.bus_clock / 1000000), - (current_cpu_data.bus_clock % 1000000)/10000); -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - printk("Memory clock: %d.%02dMHz\n", - (current_cpu_data.memory_clock / 1000000), - (current_cpu_data.memory_clock % 1000000)/10000); -#endif - printk("Module clock: %d.%02dMHz\n", - (current_cpu_data.module_clock / 1000000), - (current_cpu_data.module_clock % 1000000)/10000); - - interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ; - - printk("Interval = %ld\n", interval); - - /* Start TMU0 */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); - ctrl_outl(interval, TMU0_TCOR); - ctrl_outl(interval, TMU0_TCNT); - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + sys_timer = get_sys_timer(); + printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); #if defined(CONFIG_SH_KGDB) /* diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile new file mode 100644 index 00000000000..151a6a304ce --- /dev/null +++ b/arch/sh/kernel/timers/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the various Linux/SuperH timers +# + +obj-y := timer.o + +obj-$(CONFIG_SH_TMU) += timer-tmu.o + diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c new file mode 100644 index 00000000000..96a64cb1310 --- /dev/null +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -0,0 +1,229 @@ +/* + * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support + * + * Copyright (C) 2005 Paul Mundt + * + * TMU handling code hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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/interrupt.h> +#include <linux/spinlock.h> +#include <linux/seqlock.h> +#include <asm/timer.h> +#include <asm/rtc.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/clock.h> + +#define TMU_TOCR_INIT 0x00 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 + +#define TMU0_TCR_CALIB 0x0000 + +static DEFINE_SPINLOCK(tmu0_lock); + +static unsigned long tmu_timer_get_offset(void) +{ + int count; + unsigned long flags; + + static int count_p = 0x7fffffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + spin_lock_irqsave(&tmu0_lock, flags); + /* timer count may underflow right here */ + count = ctrl_inl(TMU0_TCNT); /* read the latched count */ + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + spin_unlock_irqrestore(&tmu0_lock, flags); + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + unsigned long timer_status; + + /* Clear UNF bit */ + timer_status = ctrl_inw(TMU0_TCR); + timer_status &= ~0x100; + ctrl_outw(timer_status, TMU0_TCR); + + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(regs); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction tmu_irq = { + .name = "timer", + .handler = tmu_timer_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, +}; + +/* + * Hah! We'll see if this works (switching from usecs to nsecs). + */ +static unsigned long tmu_timer_get_frequency(void) +{ + u32 freq; + struct timespec ts1, ts2; + unsigned long diff_nsec; + unsigned long factor; + + /* Setup the timer: We don't want to generate interrupts, just + * have it count down at its natural rate. + */ + ctrl_outb(0, TMU_TSTR); +#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); +#endif + ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); + ctrl_outl(0xffffffff, TMU0_TCOR); + ctrl_outl(0xffffffff, TMU0_TCNT); + + rtc_get_time(&ts2); + + do { + rtc_get_time(&ts1); + } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); + + /* actually start the timer */ + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + + do { + rtc_get_time(&ts2); + } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); + + freq = 0xffffffff - ctrl_inl(TMU0_TCNT); + if (ts2.tv_nsec < ts1.tv_nsec) { + ts2.tv_nsec += 1000000000; + ts2.tv_sec--; + } + + diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); + + /* this should work well if the RTC has a precision of n Hz, where + * n is an integer. I don't think we have to worry about the other + * cases. */ + factor = (1000000000 + diff_nsec/2) / diff_nsec; + + if (factor * diff_nsec > 1100000000 || + factor * diff_nsec < 900000000) + panic("weird RTC (diff_nsec %ld)", diff_nsec); + + return freq * factor; +} + +static void tmu_clk_init(struct clk *clk) +{ + u8 divisor = TMU0_TCR_INIT & 0x7; + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); + clk->rate = clk->parent->rate / (4 << (divisor << 1)); +} + +static void tmu_clk_recalc(struct clk *clk) +{ + u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; + clk->rate = clk->parent->rate / (4 << (divisor << 1)); +} + +static struct clk_ops tmu_clk_ops = { + .init = tmu_clk_init, + .recalc = tmu_clk_recalc, +}; + +static struct clk tmu0_clk = { + .name = "tmu0_clk", + .ops = &tmu_clk_ops, +}; + +static int tmu_timer_init(void) +{ + unsigned long interval; + + setup_irq(TIMER_IRQ, &tmu_irq); + + tmu0_clk.parent = clk_get("module_clk"); + + /* Start TMU0 */ + ctrl_outb(0, TMU_TSTR); +#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); +#endif + + clk_register(&tmu0_clk); + clk_enable(&tmu0_clk); + + interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); + + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + + return 0; +} + +struct sys_timer_ops tmu_timer_ops = { + .init = tmu_timer_init, + .get_frequency = tmu_timer_get_frequency, + .get_offset = tmu_timer_get_offset, +}; + +struct sys_timer tmu_timer = { + .name = "tmu", + .ops = &tmu_timer_ops, +}; + diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c new file mode 100644 index 00000000000..dc1f631053a --- /dev/null +++ b/arch/sh/kernel/timers/timer.c @@ -0,0 +1,50 @@ +/* + * arch/sh/kernel/timers/timer.c - Common timer code + * + * Copyright (C) 2005 Paul Mundt + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/timer.h> +#include <linux/string.h> +#include <asm/timer.h> + +static struct sys_timer *sys_timers[] __initdata = { +#ifdef CONFIG_SH_TMU + &tmu_timer, +#endif + NULL, +}; + +static char timer_override[10] __initdata; +static int __init timer_setup(char *str) +{ + if (str) + strlcpy(timer_override, str, sizeof(timer_override)); + return 1; +} +__setup("timer=", timer_setup); + +struct sys_timer *get_sys_timer(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sys_timers); i++) { + struct sys_timer *t = sys_timers[i]; + + if (unlikely(!t)) + break; + if (unlikely(timer_override[0])) + if ((strcmp(timer_override, t->name) != 0)) + continue; + if (likely(t->ops->init() == 0)) + return t; + } + + return NULL; +} + diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig new file mode 100644 index 00000000000..fb586b1cf8b --- /dev/null +++ b/arch/sh/mm/Kconfig @@ -0,0 +1,233 @@ +menu "Processor selection" + +# +# Processor families +# +config CPU_SH2 + bool + select SH_WRITETHROUGH + +config CPU_SH3 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4A + bool + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +config CPU_SUBTYPE_ST40 + bool + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +# +# Processor subtypes +# + +comment "SH-2 Processor Support" + +config CPU_SUBTYPE_SH7604 + bool "Support SH7604 processor" + select CPU_SH2 + +comment "SH-3 Processor Support" + +config CPU_SUBTYPE_SH7300 + bool "Support SH7300 processor" + select CPU_SH3 + +config CPU_SUBTYPE_SH7705 + bool "Support SH7705 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + +config CPU_SUBTYPE_SH7707 + bool "Support SH7707 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + help + Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. + +config CPU_SUBTYPE_SH7708 + bool "Support SH7708 processor" + select CPU_SH3 + help + Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or + if you have a 100 Mhz SH-3 HD6417708R CPU. + +config CPU_SUBTYPE_SH7709 + bool "Support SH7709 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + help + Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. + +comment "SH-4 Processor Support" + +config CPU_SUBTYPE_SH7750 + bool "Support SH7750 processor" + select CPU_SH4 + help + Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. + +config CPU_SUBTYPE_SH7091 + bool "Support SH7091 processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + help + Select SH7091 if you have an SH-4 based Sega device (such as + the Dreamcast, Naomi, and Naomi 2). + +config CPU_SUBTYPE_SH7750R + bool "Support SH7750R processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + +config CPU_SUBTYPE_SH7750S + bool "Support SH7750S processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + +config CPU_SUBTYPE_SH7751 + bool "Support SH7751 processor" + select CPU_SH4 + help + Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, + or if you have a HD6417751R CPU. + +config CPU_SUBTYPE_SH7751R + bool "Support SH7751R processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7751 + +config CPU_SUBTYPE_SH7760 + bool "Support SH7760 processor" + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +config CPU_SUBTYPE_SH4_202 + bool "Support SH4-202 processor" + select CPU_SH4 + +comment "ST40 Processor Support" + +config CPU_SUBTYPE_ST40STB1 + bool "Support ST40STB1/ST40RA processors" + select CPU_SUBTYPE_ST40 + help + Select ST40STB1 if you have a ST40RA CPU. + This was previously called the ST40STB1, hence the option name. + +config CPU_SUBTYPE_ST40GX1 + bool "Support ST40GX1 processor" + select CPU_SUBTYPE_ST40 + help + Select ST40GX1 if you have a ST40GX1 CPU. + +comment "SH-4A Processor Support" + +config CPU_SUBTYPE_SH73180 + bool "Support SH73180 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7770 + bool "Support SH7770 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7780 + bool "Support SH7780 processor" + select CPU_SH4A + +endmenu + +menu "Memory management options" + +config MMU + bool "Support for memory management hardware" + depends on !CPU_SH2 + default y + help + Some SH processors (such as SH-2/SH-2A) lack an MMU. In order to + boot on these systems, this option must not be set. + + On other systems (such as the SH-3 and 4) where an MMU exists, + turning this off will boot the kernel on these machines with the + MMU implicitly switched off. + +config 32BIT + bool "Support 32-bit physical addressing through PMB" + depends on CPU_SH4A + default y + help + If you say Y here, physical addressing will be extended to + 32-bits through the SH-4A PMB. If this is not set, legacy + 29-bit physical addressing will be used. + +choice + prompt "HugeTLB page size" + depends on HUGETLB_PAGE && CPU_SH4 && MMU + default HUGETLB_PAGE_SIZE_64K + +config HUGETLB_PAGE_SIZE_64K + bool "64K" + +config HUGETLB_PAGE_SIZE_1MB + bool "1MB" + +endchoice + +source "mm/Kconfig" + +endmenu + +menu "Cache configuration" + +config SH7705_CACHE_32KB + bool "Enable 32KB cache size for SH7705" + depends on CPU_SUBTYPE_SH7705 + default y + +config SH_DIRECT_MAPPED + bool "Use direct-mapped caching" + default n + help + Selecting this option will configure the caches to be direct-mapped, + even if the cache supports a 2 or 4-way mode. This is useful primarily + for debugging on platforms with 2 and 4-way caches (SH7750R/SH7751R, + SH4-202, SH4-501, etc.) + + Turn this option off for platforms that do not have a direct-mapped + cache, and you have no need to run the caches in such a configuration. + +config SH_WRITETHROUGH + bool "Use write-through caching" + default y if CPU_SH2 + help + Selecting this option will configure the caches in write-through + mode, as opposed to the default write-back configuration. + + Since there's sill some aliasing issues on SH-4, this option will + unfortunately still require the majority of flushing functions to + be implemented to deal with aliasing. + + If unsure, say N. + +config SH_OCRAM + bool "Operand Cache RAM (OCRAM) support" + help + Selecting this option will automatically tear down the number of + sets in the dcache by half, which in turn exposes a memory range. + + The addresses for the OC RAM base will vary according to the + processor version. Consult vendor documentation for specifics. + + If unsure, say N. + +endmenu diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index e794e27a72f..96fa4a999e2 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -6,13 +6,19 @@ * 640k-1MB IO memory area on PC's * * (C) Copyright 1995 1996 Linus Torvalds + * (C) Copyright 2005, 2006 Paul Mundt + * + * 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/vmalloc.h> +#include <linux/module.h> #include <linux/mm.h> #include <asm/io.h> #include <asm/page.h> #include <asm/pgalloc.h> +#include <asm/addrspace.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> @@ -80,9 +86,15 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, if (address >= end) BUG(); do { + pud_t *pud; pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); + error = -ENOMEM; + + pud = pud_alloc(&init_mm, dir, address); + if (!pud) + break; + pmd = pmd_alloc(&init_mm, pud, address); if (!pmd) break; if (remap_area_pmd(pmd, address, end - address, @@ -97,10 +109,6 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, } /* - * Generic mapping function (not visible outside): - */ - -/* * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses * directly. @@ -109,11 +117,11 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, + unsigned long flags) { - void * addr; struct vm_struct * area; - unsigned long offset, last_addr; + unsigned long offset, last_addr, addr, orig_addr; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -124,7 +132,7 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla * Don't remap the low PCI/ISA area, it's always mapped.. */ if (phys_addr >= 0xA0000 && last_addr < 0x100000) - return phys_to_virt(phys_addr); + return (void __iomem *)phys_to_virt(phys_addr); /* * Don't allow anybody to remap normal RAM that we're using.. @@ -146,16 +154,71 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla if (!area) return NULL; area->phys_addr = phys_addr; - addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { - vunmap(addr); - return NULL; + orig_addr = addr = (unsigned long)area->addr; + +#ifdef CONFIG_32BIT + /* + * First try to remap through the PMB once a valid VMA has been + * established. Smaller allocations (or the rest of the size + * remaining after a PMB mapping due to the size not being + * perfectly aligned on a PMB size boundary) are then mapped + * through the UTLB using conventional page tables. + * + * PMB entries are all pre-faulted. + */ + if (unlikely(size >= 0x1000000)) { + unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); + + if (likely(mapped)) { + addr += mapped; + phys_addr += mapped; + size -= mapped; + } } - return (void *) (offset + (char *)addr); +#endif + + if (likely(size)) + if (remap_area_pages(addr, phys_addr, size, flags)) { + vunmap((void *)orig_addr); + return NULL; + } + + return (void __iomem *)(offset + (char *)orig_addr); } +EXPORT_SYMBOL(__ioremap); -void p3_iounmap(void *addr) +void __iounmap(void __iomem *addr) { - if (addr > high_memory) - vfree((void *)(PAGE_MASK & (unsigned long)addr)); + unsigned long vaddr = (unsigned long __force)addr; + struct vm_struct *p; + + if (PXSEG(vaddr) < P3SEG) + return; + +#ifdef CONFIG_32BIT + /* + * Purge any PMB entries that may have been established for this + * mapping, then proceed with conventional VMA teardown. + * + * XXX: Note that due to the way that remove_vm_area() does + * matching of the resultant VMA, we aren't able to fast-forward + * the address past the PMB space until the end of the VMA where + * the page tables reside. As such, unmap_vm_area() will be + * forced to linearly scan over the area until it finds the page + * tables where PTEs that need to be unmapped actually reside, + * which is far from optimal. Perhaps we need to use a separate + * VMA for the PMB mappings? + * -- PFM. + */ + pmb_unmap(vaddr); +#endif + + p = remove_vm_area((void *)(vaddr & PAGE_MASK)); + if (!p) { + printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr); + return; + } + + kfree(p); } +EXPORT_SYMBOL(__iounmap); diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 0693fbd1f95..182fe909257 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -10,10 +10,7 @@ SE SH_SOLUTION_ENGINE 7300SE SH_7300_SOLUTION_ENGINE 73180SE SH_73180_SOLUTION_ENGINE 7751SYSTEMH SH_7751_SYSTEMH -HP600 SH_HP600 -HP620 SH_HP620 -HP680 SH_HP680 -HP690 SH_HP690 +HP6XX SH_HP6XX HD64461 HD64461 HD64465 HD64465 SH2000 SH_SH2000 diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 2efc4be2270..2f9deca31cc 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -305,7 +305,11 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on NUMA + depends on (NUMA || EXPERIMENTAL) + +config ARCH_MEMORY_PROBE + def_bool y + depends on MEMORY_HOTPLUG config ARCH_FLATMEM_ENABLE def_bool y @@ -315,6 +319,7 @@ source "mm/Kconfig" config HAVE_ARCH_EARLY_PFN_TO_NID def_bool y + depends on NUMA config NR_CPUS int "Maximum number of CPUs (2-256)" @@ -350,7 +355,7 @@ config HPET_TIMER <http://www.intel.com/hardwaredesign/hpetspec.htm>. config X86_PM_TIMER - bool "PM timer" + bool "PM timer" if EMBEDDED depends on ACPI default y help diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 054dcd8a5e9..5231fe83ea4 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-git7 -# Wed Jan 11 11:57:36 2006 +# Linux kernel version: 2.6.15-git12 +# Mon Jan 16 13:09:08 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -319,6 +319,11 @@ CONFIG_IPV6=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -537,8 +542,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -805,6 +809,7 @@ CONFIG_SOFT_WATCHDOG=y # CONFIG_W83877F_WDT is not set # CONFIG_W83977F_WDT is not set # CONFIG_MACHZ_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set # # PCI-based Watchdog Cards @@ -850,6 +855,12 @@ CONFIG_HPET_MMAP=y # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set @@ -992,6 +1003,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set @@ -1276,6 +1288,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_FRAME_POINTER is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_INIT_DEBUG=y # CONFIG_DEBUG_RODATA is not set diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index 051608d5592..929e6b0771f 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile @@ -3,7 +3,8 @@ # obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \ - ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o + ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o \ + mmap32.o sysv-$(CONFIG_SYSVIPC) := ipc32.o obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 029bddab045..572b3b28772 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -293,8 +293,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int } while(0) -#define elf_map elf32_map - #include <linux/module.h> MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries."); @@ -390,21 +388,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, } EXPORT_SYMBOL(ia32_setup_arg_pages); -static unsigned long -elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) -{ - unsigned long map_addr; - struct task_struct *me = current; - - down_write(&me->mm->mmap_sem); - map_addr = do_mmap(filep, ELF_PAGESTART(addr), - eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, - type, - eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)); - up_write(&me->mm->mmap_sem); - return(map_addr); -} - #ifdef CONFIG_SYSCTL /* Register vsyscall32 into the ABI table */ #include <linux/sysctl.h> diff --git a/arch/x86_64/ia32/mmap32.c b/arch/x86_64/ia32/mmap32.c new file mode 100644 index 00000000000..079f4132575 --- /dev/null +++ b/arch/x86_64/ia32/mmap32.c @@ -0,0 +1,78 @@ +/* + * linux/arch/x86_64/ia32/mm/mmap.c + * + * flexible mmap layout support + * + * Based on the i386 version which was + * + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Started by Ingo Molnar <mingo@elte.hu> + */ + +#include <linux/personality.h> +#include <linux/mm.h> +#include <linux/random.h> + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(struct mm_struct *mm) +{ + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; + unsigned long random_factor = 0; + + if (current->flags & PF_RANDOMIZE) + random_factor = get_random_int() % (1024*1024); + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return PAGE_ALIGN(TASK_SIZE - gap - random_factor); +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void ia32_pick_mmap_layout(struct mm_struct *mm) +{ + /* + * Fall back to the standard layout if the personality + * bit is set, or if the expected stack growth is unlimited: + */ + if (sysctl_legacy_va_layout || + (current->personality & ADDR_COMPAT_LAYOUT) || + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(mm); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 8fdd089fd17..5d3c5b07b8d 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -499,13 +499,10 @@ static int lapic_resume(struct sys_device *dev) if (!apic_pm_state.active) return 0; - /* XXX: Pavel needs this for S3 resume, but can't explain why */ - set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE); - local_irq_save(flags); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c index cfb4f9cebea..38834bbbae1 100644 --- a/arch/x86_64/kernel/asm-offsets.c +++ b/arch/x86_64/kernel/asm-offsets.c @@ -43,6 +43,7 @@ int main(void) ENTRY(irqcount); ENTRY(cpunumber); ENTRY(irqstackptr); + ENTRY(data_offset); BLANK(); #undef ENTRY #ifdef CONFIG_IA32_EMULATION @@ -66,8 +67,6 @@ int main(void) DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); DEFINE(pbe_next, offsetof(struct pbe, next)); BLANK(); -#if DEBUG_STKSZ > EXCEPTION_STKSZ - DEFINE(DEBUG_IST, DEBUG_STACK); -#endif + DEFINE(TSS_ist, offsetof(struct tss_struct, ist)); return 0; } diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 632fc0f59fc..dbdba56e8fa 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -41,6 +41,7 @@ #include <asm/unistd.h> #include <asm/thread_info.h> #include <asm/hw_irq.h> +#include <asm/page.h> .code64 @@ -674,9 +675,6 @@ ENTRY(spurious_interrupt) /* error code is on the stack already */ /* handle NMI like exceptions that can happen everywhere */ -#ifndef DEBUG_IST -# define DEBUG_IST 0 -#endif .macro paranoidentry sym, ist=0 SAVE_ALL cld @@ -695,11 +693,11 @@ ENTRY(spurious_interrupt) movq ORIG_RAX(%rsp),%rsi movq $-1,ORIG_RAX(%rsp) .if \ist - subq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) .endif call \sym .if \ist - addq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) .endif cli .endm @@ -918,7 +916,7 @@ KPROBE_ENTRY(debug) INTR_FRAME pushq $0 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_debug, DEBUG_IST + paranoidentry do_debug, DEBUG_STACK jmp paranoid_exit CFI_ENDPROC .previous .text @@ -976,7 +974,7 @@ KPROBE_ENTRY(int3) INTR_FRAME pushq $0 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_int3, DEBUG_IST + paranoidentry do_int3, DEBUG_STACK jmp paranoid_exit CFI_ENDPROC .previous .text diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 38fc3d5112e..692c737fedd 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -241,104 +241,70 @@ ljumpvector: ENTRY(stext) ENTRY(_stext) -.org 0x1000 -ENTRY(init_level4_pgt) + $page = 0 +#define NEXT_PAGE(name) \ + $page = $page + 1; \ + .org $page * 0x1000; \ + phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \ +ENTRY(name) + +NEXT_PAGE(init_level4_pgt) /* This gets initialized in x86_64_start_kernel */ .fill 512,8,0 -.org 0x2000 -ENTRY(level3_ident_pgt) - .quad 0x0000000000004007 + __PHYSICAL_START +NEXT_PAGE(level3_ident_pgt) + .quad phys_level2_ident_pgt | 0x007 .fill 511,8,0 -.org 0x3000 -ENTRY(level3_kernel_pgt) +NEXT_PAGE(level3_kernel_pgt) .fill 510,8,0 /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */ - .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt */ + .quad phys_level2_kernel_pgt | 0x007 .fill 1,8,0 -.org 0x4000 -ENTRY(level2_ident_pgt) +NEXT_PAGE(level2_ident_pgt) /* 40MB for bootup. */ - .quad 0x0000000000000083 - .quad 0x0000000000200083 - .quad 0x0000000000400083 - .quad 0x0000000000600083 - .quad 0x0000000000800083 - .quad 0x0000000000A00083 - .quad 0x0000000000C00083 - .quad 0x0000000000E00083 - .quad 0x0000000001000083 - .quad 0x0000000001200083 - .quad 0x0000000001400083 - .quad 0x0000000001600083 - .quad 0x0000000001800083 - .quad 0x0000000001A00083 - .quad 0x0000000001C00083 - .quad 0x0000000001E00083 - .quad 0x0000000002000083 - .quad 0x0000000002200083 - .quad 0x0000000002400083 - .quad 0x0000000002600083 + i = 0 + .rept 20 + .quad i << 21 | 0x083 + i = i + 1 + .endr /* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */ .globl temp_boot_pmds temp_boot_pmds: .fill 492,8,0 -.org 0x5000 -ENTRY(level2_kernel_pgt) +NEXT_PAGE(level2_kernel_pgt) /* 40MB kernel mapping. The kernel code cannot be bigger than that. When you change this change KERNEL_TEXT_SIZE in page.h too. */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ - .quad 0x0000000000000183 - .quad 0x0000000000200183 - .quad 0x0000000000400183 - .quad 0x0000000000600183 - .quad 0x0000000000800183 - .quad 0x0000000000A00183 - .quad 0x0000000000C00183 - .quad 0x0000000000E00183 - .quad 0x0000000001000183 - .quad 0x0000000001200183 - .quad 0x0000000001400183 - .quad 0x0000000001600183 - .quad 0x0000000001800183 - .quad 0x0000000001A00183 - .quad 0x0000000001C00183 - .quad 0x0000000001E00183 - .quad 0x0000000002000183 - .quad 0x0000000002200183 - .quad 0x0000000002400183 - .quad 0x0000000002600183 + i = 0 + .rept 20 + .quad i << 21 | 0x183 + i = i + 1 + .endr /* Module mapping starts here */ .fill 492,8,0 -.org 0x6000 -ENTRY(empty_zero_page) - -.org 0x7000 -ENTRY(empty_bad_page) +NEXT_PAGE(empty_zero_page) -.org 0x8000 -ENTRY(empty_bad_pte_table) +NEXT_PAGE(level3_physmem_pgt) + .quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */ + .fill 511,8,0 -.org 0x9000 -ENTRY(empty_bad_pmd_table) +#undef NEXT_PAGE -.org 0xa000 -ENTRY(level3_physmem_pgt) - .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */ + .data - .org 0xb000 #ifdef CONFIG_ACPI_SLEEP + .align PAGE_SIZE ENTRY(wakeup_level4_pgt) - .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ + .quad phys_level3_ident_pgt | 0x007 .fill 255,8,0 - .quad 0x000000000000a007 + __PHYSICAL_START + .quad phys_level3_physmem_pgt | 0x007 .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ + .quad phys_level3_kernel_pgt | 0x007 #endif #ifndef CONFIG_HOTPLUG_CPU @@ -352,12 +318,12 @@ ENTRY(wakeup_level4_pgt) */ .align PAGE_SIZE ENTRY(boot_level4_pgt) - .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ + .quad phys_level3_ident_pgt | 0x007 .fill 255,8,0 - .quad 0x000000000000a007 + __PHYSICAL_START + .quad phys_level3_physmem_pgt | 0x007 .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ + .quad phys_level3_kernel_pgt | 0x007 .data diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 6eff51e9400..8ac4db09610 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -38,7 +38,7 @@ struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table }; char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned"))); unsigned long __supported_pte_mask __read_mostly = ~0UL; -static int do_not_nx __initdata = 0; +static int do_not_nx __cpuinitdata = 0; /* noexec=on|off Control non executable mappings for 64bit processes. diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile index 1d232a87f11..d25ac86fe27 100644 --- a/arch/x86_64/mm/Makefile +++ b/arch/x86_64/mm/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux x86_64-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o extable.o pageattr.o +obj-y := init.o fault.o ioremap.o extable.o pageattr.o mmap.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_K8_NUMA) += k8topology.o diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index eca60125efc..7af1742aa95 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -24,6 +24,8 @@ #include <linux/proc_fs.h> #include <linux/pci.h> #include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/memory_hotplug.h> #include <asm/processor.h> #include <asm/system.h> @@ -180,13 +182,19 @@ static struct temp_map { {} }; -static __init void *alloc_low_page(int *index, unsigned long *phys) +static __meminit void *alloc_low_page(int *index, unsigned long *phys) { struct temp_map *ti; int i; unsigned long pfn = table_end++, paddr; void *adr; + if (after_bootmem) { + adr = (void *)get_zeroed_page(GFP_ATOMIC); + *phys = __pa(adr); + return adr; + } + if (pfn >= end_pfn) panic("alloc_low_page: ran out of memory"); for (i = 0; temp_mappings[i].allocated; i++) { @@ -199,55 +207,86 @@ static __init void *alloc_low_page(int *index, unsigned long *phys) ti->allocated = 1; __flush_tlb(); adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK); + memset(adr, 0, PAGE_SIZE); *index = i; *phys = pfn * PAGE_SIZE; return adr; } -static __init void unmap_low_page(int i) +static __meminit void unmap_low_page(int i) { - struct temp_map *ti = &temp_mappings[i]; + struct temp_map *ti; + + if (after_bootmem) + return; + + ti = &temp_mappings[i]; set_pmd(ti->pmd, __pmd(0)); ti->allocated = 0; } -static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) +static void __meminit +phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) +{ + int i; + + for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { + unsigned long entry; + + if (address > end) { + for (; i < PTRS_PER_PMD; i++, pmd++) + set_pmd(pmd, __pmd(0)); + break; + } + entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address; + entry &= __supported_pte_mask; + set_pmd(pmd, __pmd(entry)); + } +} + +static void __meminit +phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) +{ + pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address)); + + if (pmd_none(*pmd)) { + spin_lock(&init_mm.page_table_lock); + phys_pmd_init(pmd, address, end); + spin_unlock(&init_mm.page_table_lock); + __flush_tlb_all(); + } +} + +static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) { - long i, j; + long i = pud_index(address); - i = pud_index(address); pud = pud + i; + + if (after_bootmem && pud_val(*pud)) { + phys_pmd_update(pud, address, end); + return; + } + for (; i < PTRS_PER_PUD; pud++, i++) { int map; unsigned long paddr, pmd_phys; pmd_t *pmd; - paddr = address + i*PUD_SIZE; - if (paddr >= end) { - for (; i < PTRS_PER_PUD; i++, pud++) - set_pud(pud, __pud(0)); + paddr = (address & PGDIR_MASK) + i*PUD_SIZE; + if (paddr >= end) break; - } - if (!e820_mapped(paddr, paddr+PUD_SIZE, 0)) { + if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) { set_pud(pud, __pud(0)); continue; } pmd = alloc_low_page(&map, &pmd_phys); + spin_lock(&init_mm.page_table_lock); set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); - for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { - unsigned long pe; - - if (paddr >= end) { - for (; j < PTRS_PER_PMD; j++, pmd++) - set_pmd(pmd, __pmd(0)); - break; - } - pe = _PAGE_NX|_PAGE_PSE | _KERNPG_TABLE | _PAGE_GLOBAL | paddr; - pe &= __supported_pte_mask; - set_pmd(pmd, __pmd(pe)); - } + phys_pmd_init(pmd, paddr, end); + spin_unlock(&init_mm.page_table_lock); unmap_low_page(map); } __flush_tlb(); @@ -262,30 +301,25 @@ static void __init find_early_table_space(unsigned long end) tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + round_up(pmds * sizeof(pmd_t), PAGE_SIZE); - /* Put page tables beyond the DMA zones if possible. - RED-PEN might be better to spread them out more over - memory to avoid hotspots */ - if (end > MAX_DMA32_PFN<<PAGE_SHIFT) - start = MAX_DMA32_PFN << PAGE_SHIFT; - else if (end > MAX_DMA_PFN << PAGE_SHIFT) - start = MAX_DMA_PFN << PAGE_SHIFT; - else - start = 0x8000; - - table_start = find_e820_area(start, end, tables); - if (table_start == -1) - table_start = find_e820_area(0x8000, end, tables); + /* RED-PEN putting page tables only on node 0 could + cause a hotspot and fill up ZONE_DMA. The page tables + need roughly 0.5KB per GB. */ + start = 0x8000; + table_start = find_e820_area(start, end, tables); if (table_start == -1UL) panic("Cannot find space for the kernel page tables"); table_start >>= PAGE_SHIFT; table_end = table_start; + + early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n", + end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT); } /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ -void __init init_memory_mapping(unsigned long start, unsigned long end) +void __meminit init_memory_mapping(unsigned long start, unsigned long end) { unsigned long next; @@ -297,7 +331,8 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) * mapped. Unfortunately this is done currently before the nodes are * discovered. */ - find_early_table_space(end); + if (!after_bootmem) + find_early_table_space(end); start = (unsigned long)__va(start); end = (unsigned long)__va(end); @@ -305,20 +340,26 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) for (; start < end; start = next) { int map; unsigned long pud_phys; - pud_t *pud = alloc_low_page(&map, &pud_phys); + pgd_t *pgd = pgd_offset_k(start); + pud_t *pud; + + if (after_bootmem) + pud = pud_offset_k(pgd, __PAGE_OFFSET); + else + pud = alloc_low_page(&map, &pud_phys); + next = start + PGDIR_SIZE; if (next > end) next = end; phys_pud_init(pud, __pa(start), __pa(next)); - set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); + if (!after_bootmem) + set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); unmap_low_page(map); } - asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); + if (!after_bootmem) + asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); __flush_tlb_all(); - early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, - table_start<<PAGE_SHIFT, - table_end<<PAGE_SHIFT); } void __cpuinit zap_low_mappings(int cpu) @@ -393,6 +434,9 @@ size_zones(unsigned long *z, unsigned long *h, void __init paging_init(void) { unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; + + memory_present(0, 0, end_pfn); + sparse_init(); size_zones(zones, holes, 0, end_pfn); free_area_init_node(0, NODE_DATA(0), zones, __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); @@ -433,6 +477,50 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) __flush_tlb_all(); } +/* + * Memory hotplug specific functions + * These are only for non-NUMA machines right now. + */ +#ifdef CONFIG_MEMORY_HOTPLUG + +void online_page(struct page *page) +{ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + totalram_pages++; + num_physpages++; +} + +int add_memory(u64 start, u64 size) +{ + struct pglist_data *pgdat = NODE_DATA(0); + struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + int ret; + + ret = __add_pages(zone, start_pfn, nr_pages); + if (ret) + goto error; + + init_memory_mapping(start, (start + size -1)); + + return ret; +error: + printk("%s: Problem encountered in __add_pages!\n", __func__); + return ret; +} +EXPORT_SYMBOL_GPL(add_memory); + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(remove_memory); + +#endif + static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, kcore_vsyscall; @@ -539,7 +627,7 @@ void mark_rodata_ro(void) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start < (unsigned long)&_end) + if (start >= end) return; printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { diff --git a/arch/x86_64/mm/mmap.c b/arch/x86_64/mm/mmap.c new file mode 100644 index 00000000000..43e9b99bdf2 --- /dev/null +++ b/arch/x86_64/mm/mmap.c @@ -0,0 +1,30 @@ +/* Copyright 2005 Andi Kleen, SuSE Labs. + * Licensed under GPL, v.2 + */ +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/random.h> +#include <asm/ia32.h> + +/* Notebook: move the mmap code from sys_x86_64.c over here. */ + +void arch_pick_mmap_layout(struct mm_struct *mm) +{ +#ifdef CONFIG_IA32_EMULATION + if (current_thread_info()->flags & _TIF_IA32) + return ia32_pick_mmap_layout(mm); +#endif + mm->mmap_base = TASK_UNMAPPED_BASE; + if (current->flags & PF_RANDOMIZE) { + /* Add 28bit randomness which is about 40bits of address space + because mmap base has to be page aligned. + or ~1/128 of the total user VM + (total user address space is 47bits) */ + unsigned rnd = get_random_int() & 0xfffffff; + mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT; + } + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; +} + |