linux/arch/arm/mach-dove/mpp.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-dove/mpp.c
   3 *
   4 * MPP functions for Marvell Dove SoCs
   5 *
   6 * This file is licensed under the terms of the GNU General Public
   7 * License version 2.  This program is licensed "as is" without any
   8 * warranty of any kind, whether express or implied.
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/gpio.h>
  13#include <linux/io.h>
  14#include <plat/mpp.h>
  15#include <mach/dove.h>
  16#include <plat/orion-gpio.h>
  17#include "mpp.h"
  18
  19struct dove_mpp_grp {
  20        int start;
  21        int end;
  22};
  23
  24/* Map a group to a range of GPIO pins in that group */
  25static const struct dove_mpp_grp dove_mpp_grp[] = {
  26        [MPP_24_39] = {
  27                .start  = 24,
  28                .end    = 39,
  29        },
  30        [MPP_40_45] = {
  31                .start  = 40,
  32                .end    = 45,
  33        },
  34        [MPP_46_51] = {
  35                .start  = 46,
  36                .end    = 51,
  37        },
  38        [MPP_58_61] = {
  39                .start  = 58,
  40                .end    = 61,
  41        },
  42        [MPP_62_63] = {
  43                .start  = 62,
  44                .end    = 63,
  45        },
  46};
  47
  48/* Enable gpio for a range of pins. mode should be a combination of
  49   GPIO_OUTPUT_OK | GPIO_INPUT_OK */
  50static void __init dove_mpp_gpio_mode(int start, int end, int gpio_mode)
  51{
  52        int i;
  53
  54        for (i = start; i <= end; i++)
  55                orion_gpio_set_valid(i, gpio_mode);
  56}
  57
  58/* Dump all the extra MPP registers. The platform code will dump the
  59   registers for pins 0-23. */
  60static void __init dove_mpp_dump_regs(void)
  61{
  62        pr_debug("PMU_CTRL4_CTRL: %08x\n",
  63                 readl(DOVE_MPP_CTRL4_VIRT_BASE));
  64
  65        pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n",
  66                 readl(DOVE_PMU_MPP_GENERAL_CTRL));
  67
  68        pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
  69}
  70
  71static void __init dove_mpp_cfg_nfc(int sel)
  72{
  73        u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
  74
  75        mpp_gen_cfg &= ~0x1;
  76        mpp_gen_cfg |= sel;
  77        writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);
  78
  79        dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
  80}
  81
  82static void __init dove_mpp_cfg_au1(int sel)
  83{
  84        u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
  85        u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
  86        u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE);
  87        u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2);
  88
  89        mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL);
  90        ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1);
  91        mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN);
  92        global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO);
  93
  94        if (!sel || sel == 0x2)
  95                dove_mpp_gpio_mode(52, 57, 0);
  96        else
  97                dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
  98
  99        if (sel & 0x1) {
 100                global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
 101                dove_mpp_gpio_mode(56, 57, 0);
 102        }
 103        if (sel & 0x2) {
 104                mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
 105                dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
 106        }
 107        if (sel & 0x4) {
 108                ssp_ctrl1 |= DOVE_SSP_ON_AU1;
 109                dove_mpp_gpio_mode(52, 55, 0);
 110        }
 111        if (sel & 0x8)
 112                mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;
 113
 114        writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
 115        writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1);
 116        writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE);
 117        writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2);
 118}
 119
 120/* Configure the group registers, enabling GPIO if sel indicates the
 121   pin is to be used for GPIO */
 122static void __init dove_mpp_conf_grp(unsigned int *mpp_grp_list)
 123{
 124        u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
 125        int gpio_mode;
 126
 127        for ( ; *mpp_grp_list; mpp_grp_list++) {
 128                unsigned int num = MPP_NUM(*mpp_grp_list);
 129                unsigned int sel = MPP_SEL(*mpp_grp_list);
 130
 131                if (num > MPP_GRP_MAX) {
 132                        pr_err("dove: invalid MPP GRP number (%u)\n", num);
 133                        continue;
 134                }
 135
 136                mpp_ctrl4 &= ~(0x1 << num);
 137                mpp_ctrl4 |= sel << num;
 138
 139                gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0;
 140                dove_mpp_gpio_mode(dove_mpp_grp[num].start,
 141                                   dove_mpp_grp[num].end, gpio_mode);
 142        }
 143        writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
 144}
 145
 146/* Configure the various MPP pins on Dove */
 147void __init dove_mpp_conf(unsigned int *mpp_list,
 148                          unsigned int *mpp_grp_list,
 149                          unsigned int grp_au1_52_57,
 150                          unsigned int grp_nfc_64_71)
 151{
 152        dove_mpp_dump_regs();
 153
 154        /* Use platform code for pins 0-23 */
 155        orion_mpp_conf(mpp_list, 0, MPP_MAX, DOVE_MPP_VIRT_BASE);
 156
 157        dove_mpp_conf_grp(mpp_grp_list);
 158        dove_mpp_cfg_au1(grp_au1_52_57);
 159        dove_mpp_cfg_nfc(grp_nfc_64_71);
 160
 161        dove_mpp_dump_regs();
 162}
 163