diff options
81 files changed, 3706 insertions, 4229 deletions
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 3bb1d7589bd..283fa1d804f 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -24,9 +24,6 @@ config ARM_VIC_NR config ICST bool -config PL330 - bool - config SA1111 bool select DMABOUNCE if !ARCH_PXA diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 69feafe7286..215816f1775 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_ARM_GIC) += gic.o obj-$(CONFIG_ARM_VIC) += vic.o obj-$(CONFIG_ICST) += icst.o -obj-$(CONFIG_PL330) += pl330.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c deleted file mode 100644 index ff3ad224482..00000000000 --- a/arch/arm/common/pl330.c +++ /dev/null @@ -1,1960 +0,0 @@ -/* linux/arch/arm/common/pl330.c - * - * Copyright (C) 2010 Samsung Electronics Co Ltd. - * Jaswinder Singh <jassi.brar@samsung.com> - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/string.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> - -#include <asm/hardware/pl330.h> - -/* Register and Bit field Definitions */ -#define DS 0x0 -#define DS_ST_STOP 0x0 -#define DS_ST_EXEC 0x1 -#define DS_ST_CMISS 0x2 -#define DS_ST_UPDTPC 0x3 -#define DS_ST_WFE 0x4 -#define DS_ST_ATBRR 0x5 -#define DS_ST_QBUSY 0x6 -#define DS_ST_WFP 0x7 -#define DS_ST_KILL 0x8 -#define DS_ST_CMPLT 0x9 -#define DS_ST_FLTCMP 0xe -#define DS_ST_FAULT 0xf - -#define DPC 0x4 -#define INTEN 0x20 -#define ES 0x24 -#define INTSTATUS 0x28 -#define INTCLR 0x2c -#define FSM 0x30 -#define FSC 0x34 -#define FTM 0x38 - -#define _FTC 0x40 -#define FTC(n) (_FTC + (n)*0x4) - -#define _CS 0x100 -#define CS(n) (_CS + (n)*0x8) -#define CS_CNS (1 << 21) - -#define _CPC 0x104 -#define CPC(n) (_CPC + (n)*0x8) - -#define _SA 0x400 -#define SA(n) (_SA + (n)*0x20) - -#define _DA 0x404 -#define DA(n) (_DA + (n)*0x20) - -#define _CC 0x408 -#define CC(n) (_CC + (n)*0x20) - -#define CC_SRCINC (1 << 0) -#define CC_DSTINC (1 << 14) -#define CC_SRCPRI (1 << 8) -#define CC_DSTPRI (1 << 22) -#define CC_SRCNS (1 << 9) -#define CC_DSTNS (1 << 23) -#define CC_SRCIA (1 << 10) -#define CC_DSTIA (1 << 24) -#define CC_SRCBRSTLEN_SHFT 4 -#define CC_DSTBRSTLEN_SHFT 18 -#define CC_SRCBRSTSIZE_SHFT 1 -#define CC_DSTBRSTSIZE_SHFT 15 -#define CC_SRCCCTRL_SHFT 11 -#define CC_SRCCCTRL_MASK 0x7 -#define CC_DSTCCTRL_SHFT 25 -#define CC_DRCCCTRL_MASK 0x7 -#define CC_SWAP_SHFT 28 - -#define _LC0 0x40c -#define LC0(n) (_LC0 + (n)*0x20) - -#define _LC1 0x410 -#define LC1(n) (_LC1 + (n)*0x20) - -#define DBGSTATUS 0xd00 -#define DBG_BUSY (1 << 0) - -#define DBGCMD 0xd04 -#define DBGINST0 0xd08 -#define DBGINST1 0xd0c - -#define CR0 0xe00 -#define CR1 0xe04 -#define CR2 0xe08 -#define CR3 0xe0c -#define CR4 0xe10 -#define CRD 0xe14 - -#define PERIPH_ID 0xfe0 -#define PCELL_ID 0xff0 - -#define CR0_PERIPH_REQ_SET (1 << 0) -#define CR0_BOOT_EN_SET (1 << 1) -#define CR0_BOOT_MAN_NS (1 << 2) -#define CR0_NUM_CHANS_SHIFT 4 -#define CR0_NUM_CHANS_MASK 0x7 -#define CR0_NUM_PERIPH_SHIFT 12 -#define CR0_NUM_PERIPH_MASK 0x1f -#define CR0_NUM_EVENTS_SHIFT 17 -#define CR0_NUM_EVENTS_MASK 0x1f - -#define CR1_ICACHE_LEN_SHIFT 0 -#define CR1_ICACHE_LEN_MASK 0x7 -#define CR1_NUM_ICACHELINES_SHIFT 4 -#define CR1_NUM_ICACHELINES_MASK 0xf - -#define CRD_DATA_WIDTH_SHIFT 0 -#define CRD_DATA_WIDTH_MASK 0x7 -#define CRD_WR_CAP_SHIFT 4 -#define CRD_WR_CAP_MASK 0x7 -#define CRD_WR_Q_DEP_SHIFT 8 -#define CRD_WR_Q_DEP_MASK 0xf -#define CRD_RD_CAP_SHIFT 12 -#define CRD_RD_CAP_MASK 0x7 -#define CRD_RD_Q_DEP_SHIFT 16 -#define CRD_RD_Q_DEP_MASK 0xf -#define CRD_DATA_BUFF_SHIFT 20 -#define CRD_DATA_BUFF_MASK 0x3ff - -#define PART 0x330 -#define DESIGNER 0x41 -#define REVISION 0x0 -#define INTEG_CFG 0x0 -#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12)) - -#define PCELL_ID_VAL 0xb105f00d - -#define PL330_STATE_STOPPED (1 << 0) -#define PL330_STATE_EXECUTING (1 << 1) -#define PL330_STATE_WFE (1 << 2) -#define PL330_STATE_FAULTING (1 << 3) -#define PL330_STATE_COMPLETING (1 << 4) -#define PL330_STATE_WFP (1 << 5) -#define PL330_STATE_KILLING (1 << 6) -#define PL330_STATE_FAULT_COMPLETING (1 << 7) -#define PL330_STATE_CACHEMISS (1 << 8) -#define PL330_STATE_UPDTPC (1 << 9) -#define PL330_STATE_ATBARRIER (1 << 10) -#define PL330_STATE_QUEUEBUSY (1 << 11) -#define PL330_STATE_INVALID (1 << 15) - -#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \ - | PL330_STATE_WFE | PL330_STATE_FAULTING) - -#define CMD_DMAADDH 0x54 -#define CMD_DMAEND 0x00 -#define CMD_DMAFLUSHP 0x35 -#define CMD_DMAGO 0xa0 -#define CMD_DMALD 0x04 -#define CMD_DMALDP 0x25 -#define CMD_DMALP 0x20 -#define CMD_DMALPEND 0x28 -#define CMD_DMAKILL 0x01 -#define CMD_DMAMOV 0xbc -#define CMD_DMANOP 0x18 -#define CMD_DMARMB 0x12 -#define CMD_DMASEV 0x34 -#define CMD_DMAST 0x08 -#define CMD_DMASTP 0x29 -#define CMD_DMASTZ 0x0c -#define CMD_DMAWFE 0x36 -#define CMD_DMAWFP 0x30 -#define CMD_DMAWMB 0x13 - -#define SZ_DMAADDH 3 -#define SZ_DMAEND 1 -#define SZ_DMAFLUSHP 2 -#define SZ_DMALD 1 -#define SZ_DMALDP 2 -#define SZ_DMALP 2 -#define SZ_DMALPEND 2 -#define SZ_DMAKILL 1 -#define SZ_DMAMOV 6 -#define SZ_DMANOP 1 -#define SZ_DMARMB 1 -#define SZ_DMASEV 2 -#define SZ_DMAST 1 -#define SZ_DMASTP 2 -#define SZ_DMASTZ 1 -#define SZ_DMAWFE 2 -#define SZ_DMAWFP 2 -#define SZ_DMAWMB 1 -#define SZ_DMAGO 6 - -#define BRST_LEN(ccr) ((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1) -#define BRST_SIZE(ccr) (1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7)) - -#define BYTE_TO_BURST(b, ccr) ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr)) -#define BURST_TO_BYTE(c, ccr) ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr)) - -/* - * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req - * at 1byte/burst for P<->M and M<->M respectively. - * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req - * should be enough for P<->M and M<->M respectively. - */ -#define MCODE_BUFF_PER_REQ 256 - -/* If the _pl330_req is available to the client */ -#define IS_FREE(req) (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND) - -/* Use this _only_ to wait on transient states */ -#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax(); - -#ifdef PL330_DEBUG_MCGEN -static unsigned cmd_line; -#define PL330_DBGCMD_DUMP(off, x...) do { \ - printk("%x:", cmd_line); \ - printk(x); \ - cmd_line += off; \ - } while (0) -#define PL330_DBGMC_START(addr) (cmd_line = addr) -#else -#define PL330_DBGCMD_DUMP(off, x...) do {} while (0) -#define PL330_DBGMC_START(addr) do {} while (0) -#endif - -struct _xfer_spec { - u32 ccr; - struct pl330_req *r; - struct pl330_xfer *x; -}; - -enum dmamov_dst { - SAR = 0, - CCR, - DAR, -}; - -enum pl330_dst { - SRC = 0, - DST, -}; - -enum pl330_cond { - SINGLE, - BURST, - ALWAYS, -}; - -struct _pl330_req { - u32 mc_bus; - void *mc_cpu; - /* Number of bytes taken to setup MC for the req */ - u32 mc_len; - struct pl330_req *r; - /* Hook to attach to DMAC's list of reqs with due callback */ - struct list_head rqd; -}; - -/* ToBeDone for tasklet */ -struct _pl330_tbd { - bool reset_dmac; - bool reset_mngr; - u8 reset_chan; -}; - -/* A DMAC Thread */ -struct pl330_thread { - u8 id; - int ev; - /* If the channel is not yet acquired by any client */ - bool free; - /* Parent DMAC */ - struct pl330_dmac *dmac; - /* Only two at a time */ - struct _pl330_req req[2]; - /* Index of the last enqueued request */ - unsigned lstenq; - /* Index of the last submitted request or -1 if the DMA is stopped */ - int req_running; -}; - -enum pl330_dmac_state { - UNINIT, - INIT, - DYING, -}; - -/* A DMAC */ -struct pl330_dmac { - spinlock_t lock; - /* Holds list of reqs with due callbacks */ - struct list_head req_done; - /* Pointer to platform specific stuff */ - struct pl330_info *pinfo; - /* Maximum possible events/irqs */ - int events[32]; - /* BUS address of MicroCode buffer */ - u32 mcode_bus; - /* CPU address of MicroCode buffer */ - void *mcode_cpu; - /* List of all Channel threads */ - struct pl330_thread *channels; - /* Pointer to the MANAGER thread */ - struct pl330_thread *manager; - /* To handle bad news in interrupt */ - struct tasklet_struct tasks; - struct _pl330_tbd dmac_tbd; - /* State of DMAC operation */ - enum pl330_dmac_state state; -}; - -static inline void _callback(struct pl330_req *r, enum pl330_op_err err) -{ - if (r && r->xfer_cb) - r->xfer_cb(r->token, err); -} - -static inline bool _queue_empty(struct pl330_thread *thrd) -{ - return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1])) - ? true : false; -} - -static inline bool _queue_full(struct pl330_thread *thrd) -{ - return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1])) - ? false : true; -} - -static inline bool is_manager(struct pl330_thread *thrd) -{ - struct pl330_dmac *pl330 = thrd->dmac; - - /* MANAGER is indexed at the end */ - if (thrd->id == pl330->pinfo->pcfg.num_chan) - return true; - else - return false; -} - -/* If manager of the thread is in Non-Secure mode */ -static inline bool _manager_ns(struct pl330_thread *thrd) -{ - struct pl330_dmac *pl330 = thrd->dmac; - - return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false; -} - -static inline u32 get_id(struct pl330_info *pi, u32 off) -{ - void __iomem *regs = pi->base; - u32 id = 0; - - id |= (readb(regs + off + 0x0) << 0); - id |= (readb(regs + off + 0x4) << 8); - id |= (readb(regs + off + 0x8) << 16); - id |= (readb(regs + off + 0xc) << 24); - - return id; -} - -static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], - enum pl330_dst da, u16 val) -{ - if (dry_run) - return SZ_DMAADDH; - - buf[0] = CMD_DMAADDH; - buf[0] |= (da << 1); - *((u16 *)&buf[1]) = val; - - PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n", - da == 1 ? "DA" : "SA", val); - - return SZ_DMAADDH; -} - -static inline u32 _emit_END(unsigned dry_run, u8 buf[]) -{ - if (dry_run) - return SZ_DMAEND; - - buf[0] = CMD_DMAEND; - - PL330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n"); - - return SZ_DMAEND; -} - -static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri) -{ - if (dry_run) - return SZ_DMAFLUSHP; - - buf[0] = CMD_DMAFLUSHP; - - peri &= 0x1f; - peri <<= 3; - buf[1] = peri; - - PL330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3); - - return SZ_DMAFLUSHP; -} - -static inline u32 _emit_LD(unsigned dry_run, u8 buf[], enum pl330_cond cond) -{ - if (dry_run) - return SZ_DMALD; - - buf[0] = CMD_DMALD; - - if (cond == SINGLE) - buf[0] |= (0 << 1) | (1 << 0); - else if (cond == BURST) - buf[0] |= (1 << 1) | (1 << 0); - - PL330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n", - cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A')); - - return SZ_DMALD; -} - -static inline u32 _emit_LDP(unsigned dry_run, u8 buf[], - enum pl330_cond cond, u8 peri) -{ - if (dry_run) - return SZ_DMALDP; - - buf[0] = CMD_DMALDP; - - if (cond == BURST) - buf[0] |= (1 << 1); - - peri &= 0x1f; - peri <<= 3; - buf[1] = peri; - - PL330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n", - cond == SINGLE ? 'S' : 'B', peri >> 3); - - return SZ_DMALDP; -} - -static inline u32 _emit_LP(unsigned dry_run, u8 buf[], - unsigned loop, u8 cnt) -{ - if (dry_run) - return SZ_DMALP; - - buf[0] = CMD_DMALP; - - if (loop) - buf[0] |= (1 << 1); - - cnt--; /* DMAC increments by 1 internally */ - buf[1] = cnt; - - PL330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt); - - return SZ_DMALP; -} - -struct _arg_LPEND { - enum pl330_cond cond; - bool forever; - unsigned loop; - u8 bjump; -}; - -static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[], - const struct _arg_LPEND *arg) -{ - enum pl330_cond cond = arg->cond; - bool forever = arg->forever; - unsigned loop = arg->loop; - u8 bjump = arg->bjump; - - if (dry_run) - return SZ_DMALPEND; - - buf[0] = CMD_DMALPEND; - - if (loop) - buf[0] |= (1 << 2); - - if (!forever) - buf[0] |= (1 << 4); - - if (cond == SINGLE) - buf[0] |= (0 << 1) | (1 << 0); - else if (cond == BURST) - buf[0] |= (1 << 1) | (1 << 0); - - buf[1] = bjump; - - PL330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n", - forever ? "FE" : "END", - cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'), - loop ? '1' : '0', - bjump); - - return SZ_DMALPEND; -} - -static inline u32 _emit_KILL(unsigned dry_run, u8 buf[]) -{ - if (dry_run) - return SZ_DMAKILL; - - buf[0] = CMD_DMAKILL; - - return SZ_DMAKILL; |