⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfp.c

📁 linux 内核源代码
💻 C
字号:
/* * linux/arch/arm/mach-pxa/mfp.c * * PXA3xx Multi-Function Pin Support * * Copyright (C) 2007 Marvell Internation Ltd. * * 2007-08-21: eric miao <eric.miao@marvell.com> *             initial version * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/io.h>#include <asm/hardware.h>#include <asm/arch/mfp.h>/* mfp_spin_lock is used to ensure that MFP register configuration * (most likely a read-modify-write operation) is atomic, and that * mfp_table[] is consistent */static DEFINE_SPINLOCK(mfp_spin_lock);static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];#define mfpr_readl(off)			\	__raw_readl(mfpr_mmio_base + (off))#define mfpr_writel(off, val)		\	__raw_writel(val, mfpr_mmio_base + (off))/* * perform a read-back of any MFPR register to make sure the * previous writings are finished */#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + 0)static inline void __mfp_config(int pin, unsigned long val){	unsigned long off = mfp_table[pin].mfpr_off;	mfp_table[pin].mfpr_val = val;	mfpr_writel(off, val);}void pxa3xx_mfp_config(mfp_cfg_t *mfp_cfgs, int num){	int i, pin;	unsigned long val, flags;	mfp_cfg_t *mfp_cfg = mfp_cfgs;	spin_lock_irqsave(&mfp_spin_lock, flags);	for (i = 0; i < num; i++, mfp_cfg++) {		pin = MFP_CFG_PIN(*mfp_cfg);		val = MFP_CFG_VAL(*mfp_cfg);		BUG_ON(pin >= MFP_PIN_MAX);		__mfp_config(pin, val);	}	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}unsigned long pxa3xx_mfp_read(int mfp){	unsigned long val, flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	val = mfpr_readl(mfp_table[mfp].mfpr_off);	spin_unlock_irqrestore(&mfp_spin_lock, flags);	return val;}void pxa3xx_mfp_write(int mfp, unsigned long val){	unsigned long flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	mfpr_writel(mfp_table[mfp].mfpr_off, val);	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void pxa3xx_mfp_set_afds(int mfp, int af, int ds){	uint32_t mfpr_off, mfpr_val;	unsigned long flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	mfpr_off = mfp_table[mfp].mfpr_off;	mfpr_val = mfpr_readl(mfpr_off);	mfpr_val &= ~(MFPR_AF_MASK | MFPR_DRV_MASK);	mfpr_val |= (((af & 0x7) << MFPR_ALT_OFFSET) |		     ((ds & 0x7) << MFPR_DRV_OFFSET));	mfpr_writel(mfpr_off, mfpr_val);	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void pxa3xx_mfp_set_rdh(int mfp, int rdh){	uint32_t mfpr_off, mfpr_val;	unsigned long flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	mfpr_off = mfp_table[mfp].mfpr_off;	mfpr_val = mfpr_readl(mfpr_off);	mfpr_val &= ~MFPR_RDH_MASK;	if (likely(rdh))		mfpr_val |= (1u << MFPR_SS_OFFSET);	mfpr_writel(mfpr_off, mfpr_val);	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void pxa3xx_mfp_set_lpm(int mfp, int lpm){	uint32_t mfpr_off, mfpr_val;	unsigned long flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	mfpr_off = mfp_table[mfp].mfpr_off;	mfpr_val = mfpr_readl(mfpr_off);	mfpr_val &= ~MFPR_LPM_MASK;	if (lpm & 0x1) mfpr_val |= 1u << MFPR_SON_OFFSET;	if (lpm & 0x2) mfpr_val |= 1u << MFPR_SD_OFFSET;	if (lpm & 0x4) mfpr_val |= 1u << MFPR_PU_OFFSET;	if (lpm & 0x8) mfpr_val |= 1u << MFPR_PD_OFFSET;	if (lpm &0x10) mfpr_val |= 1u << MFPR_PS_OFFSET;	mfpr_writel(mfpr_off, mfpr_val);	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void pxa3xx_mfp_set_pull(int mfp, int pull){	uint32_t mfpr_off, mfpr_val;	unsigned long flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	mfpr_off = mfp_table[mfp].mfpr_off;	mfpr_val = mfpr_readl(mfpr_off);	mfpr_val &= ~MFPR_PULL_MASK;	mfpr_val |= ((pull & 0x7u) << MFPR_PD_OFFSET);	mfpr_writel(mfpr_off, mfpr_val);	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void pxa3xx_mfp_set_edge(int mfp, int edge){	uint32_t mfpr_off, mfpr_val;	unsigned long flags;	BUG_ON(mfp >= MFP_PIN_MAX);	spin_lock_irqsave(&mfp_spin_lock, flags);	mfpr_off = mfp_table[mfp].mfpr_off;	mfpr_val = mfpr_readl(mfpr_off);	mfpr_val &= ~MFPR_EDGE_MASK;	mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;	mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;	mfpr_writel(mfpr_off, mfpr_val);	mfpr_sync();	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map){	struct pxa3xx_mfp_addr_map *p;	unsigned long offset, flags;	int i;	spin_lock_irqsave(&mfp_spin_lock, flags);	for (p = map; p->start != MFP_PIN_INVALID; p++) {		offset = p->offset;		i = p->start;		do {			mfp_table[i].mfpr_off = offset;			mfp_table[i].mfpr_val = 0;			offset += 4; i++;		} while ((i <= p->end) && (p->end != -1));	}	spin_unlock_irqrestore(&mfp_spin_lock, flags);}void __init pxa3xx_init_mfp(void){	memset(mfp_table, 0, sizeof(mfp_table));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -