1f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* 2f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * linux/arch/arm/plat-pxa/mfp.c 3f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 4f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Multi-Function Pin Support 5f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 6f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Copyright (C) 2007 Marvell Internation Ltd. 7f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 8f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 2007-08-21: eric miao <eric.miao@marvell.com> 9f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * initial version 10f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 11f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * This program is free software; you can redistribute it and/or modify 12f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * it under the terms of the GNU General Public License version 2 as 13f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * published by the Free Software Foundation. 14f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao */ 15f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 16f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#include <linux/module.h> 17f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#include <linux/kernel.h> 18f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#include <linux/init.h> 19f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#include <linux/io.h> 20f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 21f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#include <plat/mfp.h> 22f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 23f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_SIZE (PAGE_SIZE) 24f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 25f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* MFPR register bit definitions */ 26f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULL_SEL (0x1 << 15) 27f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULLUP_EN (0x1 << 14) 28f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULLDOWN_EN (0x1 << 13) 29f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_SLEEP_SEL (0x1 << 9) 30f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_SLEEP_OE_N (0x1 << 7) 31f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_CLEAR (0x1 << 6) 32f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_FALL_EN (0x1 << 5) 33f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_RISE_EN (0x1 << 4) 34f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 35f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_SLEEP_DATA(x) ((x) << 8) 36f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_DRIVE(x) (((x) & 0x7) << 10) 37f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_AF_SEL(x) (((x) & 0x7) << 0) 38f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 39f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_NONE (0) 40f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_RISE (MFPR_EDGE_RISE_EN) 41f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_FALL (MFPR_EDGE_FALL_EN) 42f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_EDGE_BOTH (MFPR_EDGE_RISE | MFPR_EDGE_FALL) 43f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 44f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* 45f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Table that determines the low power modes outputs, with actual settings 46f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * used in parentheses for don't-care values. Except for the float output, 47f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * the configured driven and pulled levels match, so if there is a need for 48f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * non-LPM pulled output, the same configuration could probably be used. 49f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 50f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Output value sleep_oe_n sleep_data pullup_en pulldown_en pull_sel 51f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * (bit 7) (bit 8) (bit 14) (bit 13) (bit 15) 52f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 53f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Input 0 X(0) X(0) X(0) 0 54f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Drive 0 0 0 0 X(1) 0 55f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Drive 1 0 1 X(1) 0 0 56f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Pull hi (1) 1 X(1) 1 0 0 57f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Pull lo (0) 1 X(0) 0 1 0 58f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Z (float) 1 X(0) 0 0 0 59f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao */ 60f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_INPUT (0) 61f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_DRIVE_LOW (MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN) 62f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_DRIVE_HIGH (MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN) 63f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_PULL_LOW (MFPR_LPM_DRIVE_LOW | MFPR_SLEEP_OE_N) 64f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_PULL_HIGH (MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N) 65f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_FLOAT (MFPR_SLEEP_OE_N) 66f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_LPM_MASK (0xe080) 67f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 68f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* 69f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * The pullup and pulldown state of the MFP pin at run mode is by default 70f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * determined by the selected alternate function. In case that some buggy 71f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * devices need to override this default behavior, the definitions below 72f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * indicates the setting of corresponding MFPR bits 73f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * 74f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * Definition pull_sel pullup_en pulldown_en 75f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * MFPR_PULL_NONE 0 0 0 76f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * MFPR_PULL_LOW 1 0 1 77f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * MFPR_PULL_HIGH 1 1 0 78f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * MFPR_PULL_BOTH 1 1 1 79fb60870f630f926d2299b6ebd31fc94714dcd734Daniel Mack * MFPR_PULL_FLOAT 1 0 0 80f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao */ 81f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULL_NONE (0) 82f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULL_LOW (MFPR_PULL_SEL | MFPR_PULLDOWN_EN) 83f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULL_BOTH (MFPR_PULL_LOW | MFPR_PULLUP_EN) 84f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define MFPR_PULL_HIGH (MFPR_PULL_SEL | MFPR_PULLUP_EN) 85fb60870f630f926d2299b6ebd31fc94714dcd734Daniel Mack#define MFPR_PULL_FLOAT (MFPR_PULL_SEL) 86f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 87f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* mfp_spin_lock is used to ensure that MFP register configuration 88f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * (most likely a read-modify-write operation) is atomic, and that 89f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * mfp_table[] is consistent 90f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao */ 91f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic DEFINE_SPINLOCK(mfp_spin_lock); 92f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 93f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic void __iomem *mfpr_mmio_base; 94f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 95f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostruct mfp_pin { 96f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long config; /* -1 for not configured */ 97f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long mfpr_off; /* MFPRxx Register offset */ 98f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long mfpr_run; /* Run-Mode Register Value */ 99f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long mfpr_lpm; /* Low Power Mode Register Value */ 100f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao}; 101f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 102f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic struct mfp_pin mfp_table[MFP_PIN_MAX]; 103f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 104f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */ 105f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic const unsigned long mfpr_lpm[] = { 106f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_LPM_INPUT, 107f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_LPM_DRIVE_LOW, 108f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_LPM_DRIVE_HIGH, 109f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_LPM_PULL_LOW, 110f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_LPM_PULL_HIGH, 111f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_LPM_FLOAT, 1121fe8c2bcad52d16e4d31d3680b9bb536c56df3d8Eric Miao MFPR_LPM_INPUT, 113f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao}; 114f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 115f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ 116f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic const unsigned long mfpr_pull[] = { 117f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_PULL_NONE, 118f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_PULL_LOW, 119f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_PULL_HIGH, 120f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_PULL_BOTH, 121fb60870f630f926d2299b6ebd31fc94714dcd734Daniel Mack MFPR_PULL_FLOAT, 122f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao}; 123f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 124f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */ 125f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic const unsigned long mfpr_edge[] = { 126f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_EDGE_NONE, 127f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_EDGE_RISE, 128f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_EDGE_FALL, 129f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao MFPR_EDGE_BOTH, 130f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao}; 131f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 132f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define mfpr_readl(off) \ 133f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao __raw_readl(mfpr_mmio_base + (off)) 134f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 135f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define mfpr_writel(off, val) \ 136f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao __raw_writel(val, mfpr_mmio_base + (off)) 137f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 138f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao#define mfp_configured(p) ((p)->config != -1) 139f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 140f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao/* 1410c7fbbe1a15e419eb2f1a687444330c4016fdb8fYu Tang * perform a read-back of any valid MFPR register to make sure the 142f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * previous writings are finished 143f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao */ 1440c7fbbe1a15e419eb2f1a687444330c4016fdb8fYu Tangstatic unsigned long mfpr_off_readback; 1450c7fbbe1a15e419eb2f1a687444330c4016fdb8fYu Tang#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + mfpr_off_readback) 146f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 147f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic inline void __mfp_config_run(struct mfp_pin *p) 148f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 149f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao if (mfp_configured(p)) 150f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfpr_writel(p->mfpr_off, p->mfpr_run); 151f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 152f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 153f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaostatic inline void __mfp_config_lpm(struct mfp_pin *p) 154f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 155f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao if (mfp_configured(p)) { 156f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR; 157f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao if (mfpr_clr != p->mfpr_run) 158f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfpr_writel(p->mfpr_off, mfpr_clr); 159f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao if (p->mfpr_lpm != mfpr_clr) 160f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfpr_writel(p->mfpr_off, p->mfpr_lpm); 161f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao } 162f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 163f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 164f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaovoid mfp_config(unsigned long *mfp_cfgs, int num) 165f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 166f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long flags; 167f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao int i; 168f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 169f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_lock_irqsave(&mfp_spin_lock, flags); 170f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 171f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao for (i = 0; i < num; i++, mfp_cfgs++) { 172f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long tmp, c = *mfp_cfgs; 173f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao struct mfp_pin *p; 174f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao int pin, af, drv, lpm, edge, pull; 175f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 176f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao pin = MFP_PIN(c); 177f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao BUG_ON(pin >= MFP_PIN_MAX); 178f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao p = &mfp_table[pin]; 179f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 180f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao af = MFP_AF(c); 181f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao drv = MFP_DS(c); 182f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao lpm = MFP_LPM_STATE(c); 183f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao edge = MFP_LPM_EDGE(c); 184f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao pull = MFP_PULL(c); 185f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 186f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao /* run-mode pull settings will conflict with MFPR bits of 187f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * low power mode state, calculate mfpr_run and mfpr_lpm 188f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao * individually if pull != MFP_PULL_NONE 189f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao */ 190f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv); 191f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 192f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao if (likely(pull == MFP_PULL_NONE)) { 193f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; 194f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao p->mfpr_lpm = p->mfpr_run; 195f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao } else { 196f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge]; 197f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao p->mfpr_run = tmp | mfpr_pull[pull]; 198f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao } 199f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 200f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao p->config = c; __mfp_config_run(p); 201f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao } 202f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 203f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfpr_sync(); 204f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_unlock_irqrestore(&mfp_spin_lock, flags); 205f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 206f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 207f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaounsigned long mfp_read(int mfp) 208f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 209f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long val, flags; 210f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 2117df56c2586049a06b007474ca059779c81ddb1ffRoel Kluin BUG_ON(mfp < 0 || mfp >= MFP_PIN_MAX); 212f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 213f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_lock_irqsave(&mfp_spin_lock, flags); 214f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao val = mfpr_readl(mfp_table[mfp].mfpr_off); 215f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_unlock_irqrestore(&mfp_spin_lock, flags); 216f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 217f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao return val; 218f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 219f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 220f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaovoid mfp_write(int mfp, unsigned long val) 221f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 222f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long flags; 223f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 2247df56c2586049a06b007474ca059779c81ddb1ffRoel Kluin BUG_ON(mfp < 0 || mfp >= MFP_PIN_MAX); 225f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 226f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_lock_irqsave(&mfp_spin_lock, flags); 227f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfpr_writel(mfp_table[mfp].mfpr_off, val); 228f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfpr_sync(); 229f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_unlock_irqrestore(&mfp_spin_lock, flags); 230f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 231f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 23297b09da4ee36ec4bd0f6e16b84b4bb6fa05db110Arnd Bergmannvoid __init mfp_init_base(void __iomem *mfpr_base) 233f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 234f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao int i; 235f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 236f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao /* initialize the table with default - unconfigured */ 237f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao for (i = 0; i < ARRAY_SIZE(mfp_table); i++) 238f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfp_table[i].config = -1; 239f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 24097b09da4ee36ec4bd0f6e16b84b4bb6fa05db110Arnd Bergmann mfpr_mmio_base = mfpr_base; 241f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 242f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 243f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaovoid __init mfp_init_addr(struct mfp_addr_map *map) 244f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 245f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao struct mfp_addr_map *p; 246f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao unsigned long offset, flags; 247f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao int i; 248f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 249f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_lock_irqsave(&mfp_spin_lock, flags); 250f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 2510c7fbbe1a15e419eb2f1a687444330c4016fdb8fYu Tang /* mfp offset for readback */ 2520c7fbbe1a15e419eb2f1a687444330c4016fdb8fYu Tang mfpr_off_readback = map[0].offset; 2530c7fbbe1a15e419eb2f1a687444330c4016fdb8fYu Tang 254f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao for (p = map; p->start != MFP_PIN_INVALID; p++) { 255f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao offset = p->offset; 256f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao i = p->start; 257f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 258f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao do { 259f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfp_table[i].mfpr_off = offset; 260f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfp_table[i].mfpr_run = 0; 261f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao mfp_table[i].mfpr_lpm = 0; 262f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao offset += 4; i++; 263f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao } while ((i <= p->end) && (p->end != -1)); 264f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao } 265f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 266f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao spin_unlock_irqrestore(&mfp_spin_lock, flags); 267f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 268f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 269f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaovoid mfp_config_lpm(void) 270f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 271f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao struct mfp_pin *p = &mfp_table[0]; 272f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao int pin; 273f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 274f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) 275f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao __mfp_config_lpm(p); 276f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 277f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 278f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miaovoid mfp_config_run(void) 279f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao{ 280f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao struct mfp_pin *p = &mfp_table[0]; 281f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao int pin; 282f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao 283f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++) 284f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao __mfp_config_run(p); 285f8dec04d33b94a4cfa9358fd9666c01480bb164dEric Miao} 286