summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/core.c
AgeCommit message (Expand)Author
2011-05-24mmc: core: duplicated trial with same freq in mmc_rescan_try_freq()Jaehoon Chung
2011-05-24mmc: core: add support for eMMC Dual Data RatePhilip Rakity
2011-05-24mmc: core: eMMC signal voltage does not use CMD11Philip Rakity
2011-05-24mmc: core: clear MMC_PM_KEEP_POWER flag on resumeEliad Peller
2011-05-24mmc: sd: add support for driver type selectionArindam Nath
2011-05-24mmc: sd: add support for signal voltage switch procedureArindam Nath
2011-05-24mmc: initialize struct mmc_request at declaration timeChris Ball
2011-05-24mmc: initialize struct mmc_command at declaration timeChris Ball
2011-05-24mmc: core: Rename erase_timeout to cmd_timeout_ms.Andrei Warkentin
2011-05-24mmc: mmc_card_keep_power cleanupsOhad Ben-Cohen
2011-03-17mmc: core: reset card voltage after power offUlf Hansson
2011-03-17mmc: core: export function mmc_do_release_host()Ulf Hansson
2011-03-16mmc: core: comment on why sdio_reset is done at init timePhilip Rakity
2011-03-15mmc: put the led blinking code after clock ungatingPierre Tardy
2011-03-08mmc: fix CONFIG_MMC_UNSAFE_RESUME regressionOhad Ben-Cohen
2011-01-08mmc: fix division by zero in MMC coreLinus Walleij
2011-01-08mmc: Explain why we make adjacent mmc_bus_{put,get} calls during rescan.Chris Ball
2011-01-08mmc: Fix sd/sdio/mmc initialization frequency retriesAndy Ross
2011-01-08mmc: fix detection of memory part of SD-combo card with broken SDIOMichal Miroslaw
2011-01-08mmc: sdio: don't power up cards on system suspendOhad Ben-Cohen
2011-01-08mmc: skip detection of nonremovable cards on rescanOhad Ben-Cohen
2011-01-08mmc: Aggressive clock gating frameworkLinus Walleij
2011-01-07Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wqLinus Torvalds
2010-12-24mmc: update workqueue usagesTejun Heo
2010-12-21mmc: Fix re-probing with PM_POST_RESTORE notificationTakashi Iwai
2010-11-11mmc: fix rmmod race for hosts using card-detection pollingGuennadi Liakhovetski
2010-10-23mmc: propagate power save/restore ops return valueOhad Ben-Cohen
2010-10-23mmc: refine DDR supportAdrian Hunter
2010-10-23mmc: Fixes for Dual Data Rate (DDR) supportAdrian Hunter
2010-10-23mmc: Move regulator handling closer to coreLinus Walleij
2010-10-23mmc: sdhci: mmc_rescan: reduce verbosityEric BĂ©nard
2010-10-23mmc: Make ID freq configurableHein Tibosch
2010-10-23mmc: Add helper function to check if a card is removableMatt Fleming
2010-10-15mmc: sdio: fix SDIO suspend/resume regressionOhad Ben-Cohen
2010-08-12mmc: add erase, secure erase, trim and secure trim operationsAdrian Hunter
2010-08-11mmc: fix all hangs related to mmc/sd card insert/removal during suspend/resumeMaxim Levitsky
2010-08-11mmc: implement SD-combo (IO+mem) supportMichal Miroslaw
2010-05-27mmc: remove the "state" argument to mmc_suspend_host()Matt Fleming
2010-03-12sdio: recognize io card without powercycleAlbert Herranz
2010-03-06sdio: introduce API for special power management featuresNicolas Pitre
2009-12-15mmc: add module parameter to set whether cards are assumed removableBen Hutchings
2009-09-23mmc: propagate error codes back from bus drivers' suspend/resume methodsNicolas Pitre
2009-09-23mmc: power off once at removalDenis Karpov
2009-09-23mmc: add mmc card sleep and awake supportJarkko Lavinen
2009-09-23mmc: add ability to save power by powering off cardsAdrian Hunter
2009-09-23mmc: allow host claim / release nestingAdrian Hunter
2009-09-23mmc: add 'enable' and 'disable' methods to mmc hostAdrian Hunter
2009-09-23mmc: in mmc_power_up(), use previously selected ocr if availableBalaji Rao
2009-06-13MMC core: limit minimum initialization frequency to 400kHzSascha Hauer
2009-06-13mmc: mmc_rescan detects card change in one runJorg Schummer
#n393'>393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2012 Regents of the University of California
 * Copyright (C) 2017 SiFive
 */

#include <linux/init.h>
#include <linux/linkage.h>

#include <asm/asm.h>
#include <asm/csr.h>
#include <asm/unistd.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>

	.text
	.altmacro

/*
 * Prepares to enter a system call or exception by saving all registers to the
 * stack.
 */
	.macro SAVE_ALL
	LOCAL _restore_kernel_tpsp
	LOCAL _save_context

	/*
	 * If coming from userspace, preserve the user thread pointer and load
	 * the kernel thread pointer.  If we came from the kernel, the scratch
	 * register will contain 0, and we should continue on the current TP.
	 */
	csrrw tp, CSR_SCRATCH, tp
	bnez tp, _save_context

_restore_kernel_tpsp:
	csrr tp, CSR_SCRATCH
	REG_S sp, TASK_TI_KERNEL_SP(tp)
_save_context:
	REG_S sp, TASK_TI_USER_SP(tp)
	REG_L sp, TASK_TI_KERNEL_SP(tp)
	addi sp, sp, -(PT_SIZE_ON_STACK)
	REG_S x1,  PT_RA(sp)
	REG_S x3,  PT_GP(sp)
	REG_S x5,  PT_T0(sp)
	REG_S x6,  PT_T1(sp)
	REG_S x7,  PT_T2(sp)
	REG_S x8,  PT_S0(sp)
	REG_S x9,  PT_S1(sp)
	REG_S x10, PT_A0(sp)
	REG_S x11, PT_A1(sp)
	REG_S x12, PT_A2(sp)
	REG_S x13, PT_A3(sp)
	REG_S x14, PT_A4(sp)
	REG_S x15, PT_A5(sp)
	REG_S x16, PT_A6(sp)
	REG_S x17, PT_A7(sp)
	REG_S x18, PT_S2(sp)
	REG_S x19, PT_S3(sp)
	REG_S x20, PT_S4(sp)
	REG_S x21, PT_S5(sp)
	REG_S x22, PT_S6(sp)
	REG_S x23, PT_S7(sp)
	REG_S x24, PT_S8(sp)
	REG_S x25, PT_S9(sp)
	REG_S x26, PT_S10(sp)
	REG_S x27, PT_S11(sp)
	REG_S x28, PT_T3(sp)
	REG_S x29, PT_T4(sp)
	REG_S x30, PT_T5(sp)
	REG_S x31, PT_T6(sp)

	/*
	 * Disable user-mode memory access as it should only be set in the
	 * actual user copy routines.
	 *
	 * Disable the FPU to detect illegal usage of floating point in kernel
	 * space.
	 */
	li t0, SR_SUM | SR_FS

	REG_L s0, TASK_TI_USER_SP(tp)
	csrrc s1, CSR_STATUS, t0
	csrr s2, CSR_EPC
	csrr s3, CSR_TVAL
	csrr s4, CSR_CAUSE
	csrr s5, CSR_SCRATCH
	REG_S s0, PT_SP(sp)
	REG_S s1, PT_STATUS(sp)
	REG_S s2, PT_EPC(sp)
	REG_S s3, PT_BADADDR(sp)
	REG_S s4, PT_CAUSE(sp)
	REG_S s5, PT_TP(sp)
	.endm

/*
 * Prepares to return from a system call or exception by restoring all
 * registers from the stack.
 */
	.macro RESTORE_ALL
	REG_L a0, PT_STATUS(sp)
	/*
	 * The current load reservation is effectively part of the processor's
	 * state, in the sense that load reservations cannot be shared between
	 * different hart contexts.  We can't actually save and restore a load
	 * reservation, so instead here we clear any existing reservation --
	 * it's always legal for implementations to clear load reservations at
	 * any point (as long as the forward progress guarantee is kept, but
	 * we'll ignore that here).
	 *
	 * Dangling load reservations can be the result of taking a trap in the
	 * middle of an LR/SC sequence, but can also be the result of a taken
	 * forward branch around an SC -- which is how we implement CAS.  As a
	 * result we need to clear reservations between the last CAS and the
	 * jump back to the new context.  While it is unlikely the store
	 * completes, implementations are allowed to expand reservations to be
	 * arbitrarily large.
	 */
	REG_L  a2, PT_EPC(sp)
	REG_SC x0, a2, PT_EPC(sp)

	csrw CSR_STATUS, a0
	csrw CSR_EPC, a2

	REG_L x1,  PT_RA(sp)
	REG_L x3,  PT_GP(sp)
	REG_L x4,  PT_TP(sp)
	REG_L x5,  PT_T0(sp)
	REG_L x6,  PT_T1(sp)
	REG_L x7,  PT_T2(sp)
	REG_L x8,  PT_S0(sp)
	REG_L x9,  PT_S1(sp)
	REG_L x10, PT_A0(sp)
	REG_L x11, PT_A1(sp)
	REG_L x12, PT_A2(sp)
	REG_L x13, PT_A3(sp)
	REG_L x14, PT_A4(sp)
	REG_L x15, PT_A5(sp)
	REG_L x16, PT_A6(sp)
	REG_L x17, PT_A7(sp)
	REG_L x18, PT_S2(sp)
	REG_L x19, PT_S3(sp)
	REG_L x20, PT_S4(sp)
	REG_L x21, PT_S5(sp)
	REG_L x22, PT_S6(sp)
	REG_L x23, PT_S7(sp)
	REG_L x24, PT_S8(sp)
	REG_L x25, PT_S9(sp)
	REG_L x26, PT_S10(sp)
	REG_L x27, PT_S11(sp)
	REG_L x28, PT_T3(sp)
	REG_L x29, PT_T4(sp)
	REG_L x30, PT_T5(sp)
	REG_L x31, PT_T6(sp)

	REG_L x2,  PT_SP(sp)
	.endm

#if !IS_ENABLED(CONFIG_PREEMPTION)
.set resume_kernel, restore_all
#endif

ENTRY(handle_exception)
	SAVE_ALL

	/*
	 * Set the scratch register to 0, so that if a recursive exception
	 * occurs, the exception vector knows it came from the kernel
	 */
	csrw CSR_SCRATCH, x0

	/* Load the global pointer */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	la ra, ret_from_exception
	/*
	 * MSB of cause differentiates between
	 * interrupts and exceptions
	 */
	bge s4, zero, 1f

	/* Handle interrupts */
	move a0, sp /* pt_regs */
	tail do_IRQ
1:
	/*
	 * Exceptions run with interrupts enabled or disabled depending on the
	 * state of SR_PIE in m/sstatus.
	 */
	andi t0, s1, SR_PIE
	beqz t0, 1f
	csrs CSR_STATUS, SR_IE

1:
	/* Handle syscalls */
	li t0, EXC_SYSCALL
	beq s4, t0, handle_syscall

	/* Handle other exceptions */
	slli t0, s4, RISCV_LGPTR
	la t1, excp_vect_table
	la t2, excp_vect_table_end
	move a0, sp /* pt_regs */
	add t0, t1, t0
	/* Check if exception code lies within bounds */
	bgeu t0, t2, 1f
	REG_L t0, 0(t0)
	jr t0
1:
	tail do_trap_unknown

handle_syscall:
	 /* save the initial A0 value (needed in signal handlers) */
	REG_S a0, PT_ORIG_A0(sp)
	/*
	 * Advance SEPC to avoid executing the original
	 * scall instruction on sret
	 */
	addi s2, s2, 0x4
	REG_S s2, PT_EPC(sp)
	/* Trace syscalls, but only if requested by the user. */
	REG_L t0, TASK_TI_FLAGS(tp)
	andi t0, t0, _TIF_SYSCALL_WORK
	bnez t0, handle_syscall_trace_enter
check_syscall_nr:
	/* Check to make sure we don't jump to a bogus syscall number. */
	li t0, __NR_syscalls
	la s0, sys_ni_syscall
	/*
	 * Syscall number held in a7.
	 * If syscall number is above allowed value, redirect to ni_syscall.
	 */
	bge a7, t0, 1f
	/*
	 * Check if syscall is rejected by tracer, i.e., a7 == -1.
	 * If yes, we pretend it was executed.
	 */
	li t1, -1
	beq a7, t1, ret_from_syscall_rejected
	blt a7, t1, 1f
	/* Call syscall */
	la s0, sys_call_table
	slli t0, a7, RISCV_LGPTR
	add s0, s0, t0
	REG_L s0, 0(s0)
1:
	jalr s0

ret_from_syscall:
	/* Set user a0 to kernel a0 */
	REG_S a0, PT_A0(sp)
	/*
	 * We didn't execute the actual syscall.
	 * Seccomp already set return value for the current task pt_regs.
	 * (If it was configured with SECCOMP_RET_ERRNO/TRACE)
	 */
ret_from_syscall_rejected:
	/* Trace syscalls, but only if requested by the user. */
	REG_L t0, TASK_TI_FLAGS(tp)
	andi t0, t0, _TIF_SYSCALL_WORK
	bnez t0, handle_syscall_trace_exit

ret_from_exception:
	REG_L s0, PT_STATUS(sp)
	csrc CSR_STATUS, SR_IE
#ifdef CONFIG_RISCV_M_MODE
	/* the MPP value is too large to be used as an immediate arg for addi */
	li t0, SR_MPP
	and s0, s0, t0
#else
	andi s0, s0, SR_SPP
#endif
	bnez s0, resume_kernel

resume_userspace:
	/* Interrupts must be disabled here so flags are checked atomically */
	REG_L s0, TASK_TI_FLAGS(tp) /* current_thread_info->flags */
	andi s1, s0, _TIF_WORK_MASK
	bnez s1, work_pending

	/* Save unwound kernel stack pointer in thread_info */
	addi s0, sp, PT_SIZE_ON_STACK
	REG_S s0, TASK_TI_KERNEL_SP(tp)

	/*
	 * Save TP into the scratch register , so we can find the kernel data
	 * structures again.
	 */
	csrw CSR_SCRATCH,