-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: eric miao <eric.y.miao@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
- Loading branch information
eric miao
authored and
Russell King
committed
Oct 15, 2007
1 parent
073ac8f
commit 2c8086a
Showing
21 changed files
with
2,942 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
/* | ||
* linux/arch/arm/mach-pxa/mfp.c | ||
* | ||
* PXA3xx Multi-Function Pin Support | ||
* | ||
* Copyright (C) 2007 Marvell Internation Ltd. | ||
* | ||
* 2007-08-21: eric miao <eric.y.miao@gmail.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)); | ||
} |
Oops, something went wrong.