Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at b1404069f64457c94de241738fdca142c2e5698f 149 lines 3.6 kB view raw
1/* 2 * QUICC Engine GPIOs 3 * 4 * Copyright (c) MontaVista Software, Inc. 2008. 5 * 6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/init.h> 16#include <linux/spinlock.h> 17#include <linux/io.h> 18#include <linux/of.h> 19#include <linux/of_gpio.h> 20#include <linux/gpio.h> 21#include <asm/qe.h> 22 23struct qe_gpio_chip { 24 struct of_mm_gpio_chip mm_gc; 25 spinlock_t lock; 26 27 /* shadowed data register to clear/set bits safely */ 28 u32 cpdata; 29}; 30 31static inline struct qe_gpio_chip * 32to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc) 33{ 34 return container_of(mm_gc, struct qe_gpio_chip, mm_gc); 35} 36 37static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc) 38{ 39 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); 40 struct qe_pio_regs __iomem *regs = mm_gc->regs; 41 42 qe_gc->cpdata = in_be32(&regs->cpdata); 43} 44 45static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) 46{ 47 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 48 struct qe_pio_regs __iomem *regs = mm_gc->regs; 49 u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); 50 51 return in_be32(&regs->cpdata) & pin_mask; 52} 53 54static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 55{ 56 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 57 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); 58 struct qe_pio_regs __iomem *regs = mm_gc->regs; 59 unsigned long flags; 60 u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); 61 62 spin_lock_irqsave(&qe_gc->lock, flags); 63 64 if (val) 65 qe_gc->cpdata |= pin_mask; 66 else 67 qe_gc->cpdata &= ~pin_mask; 68 69 out_be32(&regs->cpdata, qe_gc->cpdata); 70 71 spin_unlock_irqrestore(&qe_gc->lock, flags); 72} 73 74static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 75{ 76 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 77 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); 78 unsigned long flags; 79 80 spin_lock_irqsave(&qe_gc->lock, flags); 81 82 __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0); 83 84 spin_unlock_irqrestore(&qe_gc->lock, flags); 85 86 return 0; 87} 88 89static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 90{ 91 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 92 struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc); 93 unsigned long flags; 94 95 spin_lock_irqsave(&qe_gc->lock, flags); 96 97 __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0); 98 99 spin_unlock_irqrestore(&qe_gc->lock, flags); 100 101 qe_gpio_set(gc, gpio, val); 102 103 return 0; 104} 105 106static int __init qe_add_gpiochips(void) 107{ 108 struct device_node *np; 109 110 for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") { 111 int ret; 112 struct qe_gpio_chip *qe_gc; 113 struct of_mm_gpio_chip *mm_gc; 114 struct of_gpio_chip *of_gc; 115 struct gpio_chip *gc; 116 117 qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL); 118 if (!qe_gc) { 119 ret = -ENOMEM; 120 goto err; 121 } 122 123 spin_lock_init(&qe_gc->lock); 124 125 mm_gc = &qe_gc->mm_gc; 126 of_gc = &mm_gc->of_gc; 127 gc = &of_gc->gc; 128 129 mm_gc->save_regs = qe_gpio_save_regs; 130 of_gc->gpio_cells = 2; 131 gc->ngpio = QE_PIO_PINS; 132 gc->direction_input = qe_gpio_dir_in; 133 gc->direction_output = qe_gpio_dir_out; 134 gc->get = qe_gpio_get; 135 gc->set = qe_gpio_set; 136 137 ret = of_mm_gpiochip_add(np, mm_gc); 138 if (ret) 139 goto err; 140 continue; 141err: 142 pr_err("%s: registration failed with status %d\n", 143 np->full_name, ret); 144 kfree(qe_gc); 145 /* try others anyway */ 146 } 147 return 0; 148} 149arch_initcall(qe_add_gpiochips);