source: trunk/target/linux/lantiq/patches-2.6.39/0008-MIPS-Lantiq-Add-more-gpio-drivers.patch @ 27104

Last change on this file since 27104 was 27104, checked in by florian, 5 years ago

[kernel] update to 2.6.39.1

patch from Peter Wagner

File size: 8.7 KB
  • arch/mips/lantiq/xway/Makefile

    From f9391211e47cdcc31f341d710efef4b3b46c333d Mon Sep 17 00:00:00 2001
    From: John Crispin <blogic@openwrt.org>
    Date: Wed, 30 Mar 2011 09:27:56 +0200
    Subject: [PATCH 08/13] MIPS: Lantiq: Add more gpio drivers
    
    The XWAY family allows to extend the number of gpios by using shift registers or latches. This patch adds the 2 drivers needed for this. The extended gpios are output only.
    
    [ralf@linux-mips.org: Fixed ltq_stp_probe section() attributes.]
    
    Signed-off-by: John Crispin <blogic@openwrt.org>
    Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
    Cc: linux-mips@linux-mips.org
    Patchwork: https://patchwork.linux-mips.org/patch/2258/
    Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
    ---
     arch/mips/lantiq/xway/Makefile   |    2 +-
     arch/mips/lantiq/xway/gpio_ebu.c |  126 ++++++++++++++++++++++++++++++
     arch/mips/lantiq/xway/gpio_stp.c |  157 ++++++++++++++++++++++++++++++++++++++
     3 files changed, 284 insertions(+), 1 deletions(-)
     create mode 100644 arch/mips/lantiq/xway/gpio_ebu.c
     create mode 100644 arch/mips/lantiq/xway/gpio_stp.c
    
    a b  
    1 obj-y := pmu.o ebu.o reset.o gpio.o devices.o 
     1obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o 
    22 
    33obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o 
    44obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o 
  • new file arch/mips/lantiq/xway/gpio_ebu.c

    - +  
     1/* 
     2 *  This program is free software; you can redistribute it and/or modify it 
     3 *  under the terms of the GNU General Public License version 2 as published 
     4 *  by the Free Software Foundation. 
     5 * 
     6 *  Copyright (C) 2010 John Crispin <blogic@openwrt.org> 
     7 */ 
     8 
     9#include <linux/init.h> 
     10#include <linux/module.h> 
     11#include <linux/types.h> 
     12#include <linux/platform_device.h> 
     13#include <linux/mutex.h> 
     14#include <linux/gpio.h> 
     15#include <linux/io.h> 
     16 
     17#include <lantiq_soc.h> 
     18 
     19/* 
     20 * By attaching hardware latches to the EBU it is possible to create output 
     21 * only gpios. This driver configures a special memory address, which when 
     22 * written to outputs 16 bit to the latches. 
     23 */ 
     24 
     25#define LTQ_EBU_BUSCON  0x1e7ff         /* 16 bit access, slowest timing */ 
     26#define LTQ_EBU_WP      0x80000000      /* write protect bit */ 
     27 
     28/* we keep a shadow value of the last value written to the ebu */ 
     29static int ltq_ebu_gpio_shadow = 0x0; 
     30static void __iomem *ltq_ebu_gpio_membase; 
     31 
     32static void ltq_ebu_apply(void) 
     33{ 
     34        unsigned long flags; 
     35 
     36        spin_lock_irqsave(&ebu_lock, flags); 
     37        ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1); 
     38        *((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow; 
     39        ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1); 
     40        spin_unlock_irqrestore(&ebu_lock, flags); 
     41} 
     42 
     43static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value) 
     44{ 
     45        if (value) 
     46                ltq_ebu_gpio_shadow |= (1 << offset); 
     47        else 
     48                ltq_ebu_gpio_shadow &= ~(1 << offset); 
     49        ltq_ebu_apply(); 
     50} 
     51 
     52static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset, 
     53        int value) 
     54{ 
     55        ltq_ebu_set(chip, offset, value); 
     56 
     57        return 0; 
     58} 
     59 
     60static struct gpio_chip ltq_ebu_chip = { 
     61        .label = "ltq_ebu", 
     62        .direction_output = ltq_ebu_direction_output, 
     63        .set = ltq_ebu_set, 
     64        .base = 72, 
     65        .ngpio = 16, 
     66        .can_sleep = 1, 
     67        .owner = THIS_MODULE, 
     68}; 
     69 
     70static int ltq_ebu_probe(struct platform_device *pdev) 
     71{ 
     72        int ret = 0; 
     73        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     74 
     75        if (!res) { 
     76                dev_err(&pdev->dev, "failed to get memory resource\n"); 
     77                return -ENOENT; 
     78        } 
     79 
     80        res = devm_request_mem_region(&pdev->dev, res->start, 
     81                resource_size(res), dev_name(&pdev->dev)); 
     82        if (!res) { 
     83                dev_err(&pdev->dev, "failed to request memory resource\n"); 
     84                return -EBUSY; 
     85        } 
     86 
     87        ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start, 
     88                resource_size(res)); 
     89        if (!ltq_ebu_gpio_membase) { 
     90                dev_err(&pdev->dev, "Failed to ioremap mem region\n"); 
     91                return -ENOMEM; 
     92        } 
     93 
     94        /* grab the default shadow value passed form the platform code */ 
     95        ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data; 
     96 
     97        /* tell the ebu controller which memory address we will be using */ 
     98        ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1); 
     99 
     100        /* write protect the region */ 
     101        ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1); 
     102 
     103        ret = gpiochip_add(&ltq_ebu_chip); 
     104        if (!ret) 
     105                ltq_ebu_apply(); 
     106        return ret; 
     107} 
     108 
     109static struct platform_driver ltq_ebu_driver = { 
     110        .probe = ltq_ebu_probe, 
     111        .driver = { 
     112                .name = "ltq_ebu", 
     113                .owner = THIS_MODULE, 
     114        }, 
     115}; 
     116 
     117static int __init ltq_ebu_init(void) 
     118{ 
     119        int ret = platform_driver_register(&ltq_ebu_driver); 
     120 
     121        if (ret) 
     122                pr_info("ltq_ebu : Error registering platfom driver!"); 
     123        return ret; 
     124} 
     125 
     126postcore_initcall(ltq_ebu_init); 
  • new file arch/mips/lantiq/xway/gpio_stp.c

    - +  
     1/* 
     2 *  This program is free software; you can redistribute it and/or modify it 
     3 *  under the terms of the GNU General Public License version 2 as published 
     4 *  by the Free Software Foundation. 
     5 * 
     6 *  Copyright (C) 2007 John Crispin <blogic@openwrt.org> 
     7 * 
     8 */ 
     9 
     10#include <linux/slab.h> 
     11#include <linux/init.h> 
     12#include <linux/module.h> 
     13#include <linux/types.h> 
     14#include <linux/platform_device.h> 
     15#include <linux/mutex.h> 
     16#include <linux/io.h> 
     17#include <linux/gpio.h> 
     18 
     19#include <lantiq_soc.h> 
     20 
     21#define LTQ_STP_CON0            0x00 
     22#define LTQ_STP_CON1            0x04 
     23#define LTQ_STP_CPU0            0x08 
     24#define LTQ_STP_CPU1            0x0C 
     25#define LTQ_STP_AR              0x10 
     26 
     27#define LTQ_STP_CON_SWU         (1 << 31) 
     28#define LTQ_STP_2HZ             0 
     29#define LTQ_STP_4HZ             (1 << 23) 
     30#define LTQ_STP_8HZ             (2 << 23) 
     31#define LTQ_STP_10HZ            (3 << 23) 
     32#define LTQ_STP_SPEED_MASK      (0xf << 23) 
     33#define LTQ_STP_UPD_FPI         (1 << 31) 
     34#define LTQ_STP_UPD_MASK        (3 << 30) 
     35#define LTQ_STP_ADSL_SRC        (3 << 24) 
     36 
     37#define LTQ_STP_GROUP0          (1 << 0) 
     38 
     39#define LTQ_STP_RISING          0 
     40#define LTQ_STP_FALLING         (1 << 26) 
     41#define LTQ_STP_EDGE_MASK       (1 << 26) 
     42 
     43#define ltq_stp_r32(reg)        __raw_readl(ltq_stp_membase + reg) 
     44#define ltq_stp_w32(val, reg)   __raw_writel(val, ltq_stp_membase + reg) 
     45#define ltq_stp_w32_mask(clear, set, reg) \ 
     46                ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \ 
     47                ltq_stp_membase + (reg)) 
     48 
     49static int ltq_stp_shadow = 0xffff; 
     50static void __iomem *ltq_stp_membase; 
     51 
     52static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value) 
     53{ 
     54        if (value) 
     55                ltq_stp_shadow |= (1 << offset); 
     56        else 
     57                ltq_stp_shadow &= ~(1 << offset); 
     58        ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0); 
     59} 
     60 
     61static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset, 
     62        int value) 
     63{ 
     64        ltq_stp_set(chip, offset, value); 
     65 
     66        return 0; 
     67} 
     68 
     69static struct gpio_chip ltq_stp_chip = { 
     70        .label = "ltq_stp", 
     71        .direction_output = ltq_stp_direction_output, 
     72        .set = ltq_stp_set, 
     73        .base = 48, 
     74        .ngpio = 24, 
     75        .can_sleep = 1, 
     76        .owner = THIS_MODULE, 
     77}; 
     78 
     79static int ltq_stp_hw_init(void) 
     80{ 
     81        /* the 3 pins used to control the external stp */ 
     82        ltq_gpio_request(4, 1, 0, 1, "stp-st"); 
     83        ltq_gpio_request(5, 1, 0, 1, "stp-d"); 
     84        ltq_gpio_request(6, 1, 0, 1, "stp-sh"); 
     85 
     86        /* sane defaults */ 
     87        ltq_stp_w32(0, LTQ_STP_AR); 
     88        ltq_stp_w32(0, LTQ_STP_CPU0); 
     89        ltq_stp_w32(0, LTQ_STP_CPU1); 
     90        ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0); 
     91        ltq_stp_w32(0, LTQ_STP_CON1); 
     92 
     93        /* rising or falling edge */ 
     94        ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0); 
     95 
     96        /* per default stp 15-0 are set */ 
     97        ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1); 
     98 
     99        /* stp are update periodically by the FPI bus */ 
     100        ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1); 
     101 
     102        /* set stp update speed */ 
     103        ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1); 
     104 
     105        /* tell the hardware that pin (led) 0 and 1 are controlled 
     106         *  by the dsl arc 
     107         */ 
     108        ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0); 
     109 
     110        ltq_pmu_enable(PMU_LED); 
     111        return 0; 
     112} 
     113 
     114static int __devinit ltq_stp_probe(struct platform_device *pdev) 
     115{ 
     116        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     117        int ret = 0; 
     118 
     119        if (!res) 
     120                return -ENOENT; 
     121        res = devm_request_mem_region(&pdev->dev, res->start, 
     122                resource_size(res), dev_name(&pdev->dev)); 
     123        if (!res) { 
     124                dev_err(&pdev->dev, "failed to request STP memory\n"); 
     125                return -EBUSY; 
     126        } 
     127        ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start, 
     128                resource_size(res)); 
     129        if (!ltq_stp_membase) { 
     130                dev_err(&pdev->dev, "failed to remap STP memory\n"); 
     131                return -ENOMEM; 
     132        } 
     133        ret = gpiochip_add(&ltq_stp_chip); 
     134        if (!ret) 
     135                ret = ltq_stp_hw_init(); 
     136 
     137        return ret; 
     138} 
     139 
     140static struct platform_driver ltq_stp_driver = { 
     141        .probe = ltq_stp_probe, 
     142        .driver = { 
     143                .name = "ltq_stp", 
     144                .owner = THIS_MODULE, 
     145        }, 
     146}; 
     147 
     148int __init ltq_stp_init(void) 
     149{ 
     150        int ret = platform_driver_register(&ltq_stp_driver); 
     151 
     152        if (ret) 
     153                pr_info("ltq_stp: error registering platfom driver"); 
     154        return ret; 
     155} 
     156 
     157postcore_initcall(ltq_stp_init); 
Note: See TracBrowser for help on using the repository browser.