Path: blob/master/arch/mips/lantiq/xway/gpio_stp.c
10818 views
/*1* This program is free software; you can redistribute it and/or modify it2* under the terms of the GNU General Public License version 2 as published3* by the Free Software Foundation.4*5* Copyright (C) 2007 John Crispin <[email protected]>6*7*/89#include <linux/slab.h>10#include <linux/init.h>11#include <linux/module.h>12#include <linux/types.h>13#include <linux/platform_device.h>14#include <linux/mutex.h>15#include <linux/io.h>16#include <linux/gpio.h>1718#include <lantiq_soc.h>1920#define LTQ_STP_CON0 0x0021#define LTQ_STP_CON1 0x0422#define LTQ_STP_CPU0 0x0823#define LTQ_STP_CPU1 0x0C24#define LTQ_STP_AR 0x102526#define LTQ_STP_CON_SWU (1 << 31)27#define LTQ_STP_2HZ 028#define LTQ_STP_4HZ (1 << 23)29#define LTQ_STP_8HZ (2 << 23)30#define LTQ_STP_10HZ (3 << 23)31#define LTQ_STP_SPEED_MASK (0xf << 23)32#define LTQ_STP_UPD_FPI (1 << 31)33#define LTQ_STP_UPD_MASK (3 << 30)34#define LTQ_STP_ADSL_SRC (3 << 24)3536#define LTQ_STP_GROUP0 (1 << 0)3738#define LTQ_STP_RISING 039#define LTQ_STP_FALLING (1 << 26)40#define LTQ_STP_EDGE_MASK (1 << 26)4142#define ltq_stp_r32(reg) __raw_readl(ltq_stp_membase + reg)43#define ltq_stp_w32(val, reg) __raw_writel(val, ltq_stp_membase + reg)44#define ltq_stp_w32_mask(clear, set, reg) \45ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \46ltq_stp_membase + (reg))4748static int ltq_stp_shadow = 0xffff;49static void __iomem *ltq_stp_membase;5051static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)52{53if (value)54ltq_stp_shadow |= (1 << offset);55else56ltq_stp_shadow &= ~(1 << offset);57ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);58}5960static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,61int value)62{63ltq_stp_set(chip, offset, value);6465return 0;66}6768static struct gpio_chip ltq_stp_chip = {69.label = "ltq_stp",70.direction_output = ltq_stp_direction_output,71.set = ltq_stp_set,72.base = 48,73.ngpio = 24,74.can_sleep = 1,75.owner = THIS_MODULE,76};7778static int ltq_stp_hw_init(void)79{80/* the 3 pins used to control the external stp */81ltq_gpio_request(4, 1, 0, 1, "stp-st");82ltq_gpio_request(5, 1, 0, 1, "stp-d");83ltq_gpio_request(6, 1, 0, 1, "stp-sh");8485/* sane defaults */86ltq_stp_w32(0, LTQ_STP_AR);87ltq_stp_w32(0, LTQ_STP_CPU0);88ltq_stp_w32(0, LTQ_STP_CPU1);89ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);90ltq_stp_w32(0, LTQ_STP_CON1);9192/* rising or falling edge */93ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);9495/* per default stp 15-0 are set */96ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);9798/* stp are update periodically by the FPI bus */99ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);100101/* set stp update speed */102ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);103104/* tell the hardware that pin (led) 0 and 1 are controlled105* by the dsl arc106*/107ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);108109ltq_pmu_enable(PMU_LED);110return 0;111}112113static int __devinit ltq_stp_probe(struct platform_device *pdev)114{115struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);116int ret = 0;117118if (!res)119return -ENOENT;120res = devm_request_mem_region(&pdev->dev, res->start,121resource_size(res), dev_name(&pdev->dev));122if (!res) {123dev_err(&pdev->dev, "failed to request STP memory\n");124return -EBUSY;125}126ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,127resource_size(res));128if (!ltq_stp_membase) {129dev_err(&pdev->dev, "failed to remap STP memory\n");130return -ENOMEM;131}132ret = gpiochip_add(<q_stp_chip);133if (!ret)134ret = ltq_stp_hw_init();135136return ret;137}138139static struct platform_driver ltq_stp_driver = {140.probe = ltq_stp_probe,141.driver = {142.name = "ltq_stp",143.owner = THIS_MODULE,144},145};146147int __init ltq_stp_init(void)148{149int ret = platform_driver_register(<q_stp_driver);150151if (ret)152pr_info("ltq_stp: error registering platfom driver");153return ret;154}155156postcore_initcall(ltq_stp_init);157158159