mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
pinctrl: remove sirf atlas/prima drivers
The CSR SiRF prima2/atlas platforms are getting removed, so this driver is no longer needed. Cc: Barry Song <baohua@kernel.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Barry Song <baohua@kernel.org> Link: https://lore.kernel.org/r/20210120132045.2127659-4-arnd@kernel.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
484c58d660
commit
c41e02c384
@ -1,50 +0,0 @@
|
||||
CSR SiRFatlas7 GPIO controller bindings
|
||||
|
||||
Required properties:
|
||||
- compatible : "sirf,atlas7-gpio"
|
||||
- reg : Address range of the pinctrl registers
|
||||
- interrupts : Interrupts used by every GPIO group
|
||||
- gpio-banks : How many gpio banks on this controller
|
||||
- gpio-controller : Indicates this device is a GPIO controller
|
||||
- interrupt-controller : Marks the device node as an interrupt controller
|
||||
|
||||
The GPIO controller also acts as an interrupt controller. It uses the default
|
||||
two cells specifier as described in Documentation/devicetree/bindings/
|
||||
interrupt-controller/interrupts.txt.
|
||||
|
||||
Example:
|
||||
|
||||
gpio_0: gpio_mediam@17040000 {
|
||||
compatible = "sirf,atlas7-gpio";
|
||||
reg = <0x17040000 0x1000>;
|
||||
interrupts = <0 13 0>, <0 14 0>;
|
||||
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
|
||||
gpio-banks = <2>;
|
||||
gpio-ranges = <&pinctrl 0 0 0>,
|
||||
<&pinctrl 32 0 0>;
|
||||
gpio-ranges-group-names = "lvds_gpio_grp",
|
||||
"uart_nand_gpio_grp";
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led1 {
|
||||
gpios = <&gpio_1 15 0>;
|
||||
...
|
||||
};
|
||||
|
||||
led2 {
|
||||
gpios = <&gpio_2 34 0>;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
Please refer to gpio.txt in this directory for details of the common
|
||||
gpio properties used by devices.
|
@ -1,109 +0,0 @@
|
||||
CSR SiRFatlas7 pinmux controller
|
||||
|
||||
Required properties:
|
||||
- compatible : "sirf,atlas7-ioc"
|
||||
- reg : Address range of the pinctrl registers
|
||||
|
||||
For example, pinctrl might have properties like the following:
|
||||
pinctrl: ioc@18880000 {
|
||||
compatible = "sirf,atlas7-ioc";
|
||||
reg = <0x18880000 0x1000>;
|
||||
|
||||
a_ac97_pmx: ac97@0 {
|
||||
ac97 {
|
||||
groups = "audio_ac97_grp";
|
||||
function = "audio_ac97";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
sd2_pmx: sd2@0 {
|
||||
sd2 {
|
||||
groups = "sd2_grp0";
|
||||
function = "sd2";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
|
||||
sample0_cfg: sample0@0 {
|
||||
sample0 {
|
||||
pins = "ldd_0", "ldd_1";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
sample1_cfg: sample1@0 {
|
||||
sample1 {
|
||||
pins = "ldd_2", "ldd_3";
|
||||
input-schmitt-enable;
|
||||
};
|
||||
};
|
||||
|
||||
sample2_cfg: sample2@0 {
|
||||
sample2 {
|
||||
groups = "uart4_nopause_grp";
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
|
||||
sample3_cfg: sample3@0 {
|
||||
sample3 {
|
||||
pins = "ldd_4", "ldd_5";
|
||||
drive-strength = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Please refer to pinctrl-bindings.txt in this directory for details of the common
|
||||
pinctrl bindings used by client devices.
|
||||
|
||||
SiRFatlas7's pinmux nodes act as a container for an arbitrary number of subnodes.
|
||||
Each of these subnodes represents some desired configuration for a group of pins.
|
||||
|
||||
Required subnode-properties:
|
||||
- groups : An array of strings. Each string contains the name of a group.
|
||||
- function: A string containing the name of the function to mux to the
|
||||
group.
|
||||
|
||||
Valid values for group and function names can be found from looking at the
|
||||
group and function arrays in driver files:
|
||||
drivers/pinctrl/pinctrl-sirf.c
|
||||
|
||||
For example, pinctrl might have subnodes like the following:
|
||||
sd0_pmx: sd0@0 {
|
||||
sd0 {
|
||||
groups = "sd0_grp";
|
||||
function = "sd0";
|
||||
};
|
||||
};
|
||||
|
||||
sd1_pmx0: sd1@0 {
|
||||
sd1 {
|
||||
groups = "sd1_grp0";
|
||||
function = "sd1_m0";
|
||||
};
|
||||
};
|
||||
|
||||
sd1_pmx1: sd1@1 {
|
||||
sd1 {
|
||||
groups = "sd1_grp1";
|
||||
function = "sd1_m1";
|
||||
};
|
||||
};
|
||||
|
||||
For a specific board, if it wants to use sd1,
|
||||
it can add the following to its board-specific .dts file.
|
||||
sd1: sd@12340000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sd1_pmx0>;
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
sd1: sd@12340000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sd1_pmx1>;
|
||||
}
|
@ -226,14 +226,6 @@ config PINCTRL_SINGLE
|
||||
help
|
||||
This selects the device tree based generic pinctrl driver.
|
||||
|
||||
config PINCTRL_SIRF
|
||||
bool "CSR SiRFprimaII pin controller driver"
|
||||
depends on ARCH_SIRF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB_IRQCHIP
|
||||
|
||||
config PINCTRL_SX150X
|
||||
bool "Semtech SX150x I2C GPIO expander pinctrl driver"
|
||||
depends on I2C=y
|
||||
|
@ -31,7 +31,6 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
|
||||
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
|
||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
|
||||
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
|
||||
|
@ -1,7 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# CSR SiRFsoc pinmux support
|
||||
|
||||
obj-y += pinctrl-sirf.o
|
||||
obj-y += pinctrl-prima2.o
|
||||
obj-y += pinctrl-atlas6.o
|
||||
obj-y += pinctrl-atlas7.o
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,894 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* pinmux driver for CSR SiRFprimaII
|
||||
*
|
||||
* Authors:
|
||||
* Rongjun Ying <rongjun.ying@csr.com>
|
||||
* Yuping Luo <yuping.luo@csr.com>
|
||||
* Barry Song <baohua.song@csr.com>
|
||||
*
|
||||
* Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
|
||||
* company.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include "pinctrl-sirf.h"
|
||||
|
||||
#define DRIVER_NAME "pinmux-sirf"
|
||||
|
||||
struct sirfsoc_gpio_bank {
|
||||
int id;
|
||||
int parent_irq;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct sirfsoc_gpio_chip {
|
||||
struct of_mm_gpio_chip chip;
|
||||
struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct sirfsoc_pin_group *sirfsoc_pin_groups;
|
||||
static int sirfsoc_pingrp_cnt;
|
||||
|
||||
static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return sirfsoc_pingrp_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pin_groups[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned selector,
|
||||
const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
{
|
||||
*pins = sirfsoc_pin_groups[selector].pins;
|
||||
*num_pins = sirfsoc_pin_groups[selector].num_pins;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned offset)
|
||||
{
|
||||
seq_printf(s, " " DRIVER_NAME);
|
||||
}
|
||||
|
||||
static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device_node *np;
|
||||
struct property *prop;
|
||||
const char *function, *group;
|
||||
int ret, index = 0, count = 0;
|
||||
|
||||
/* calculate number of maps required */
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = of_property_read_string(np, "sirf,function", &function);
|
||||
if (ret < 0) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "sirf,pins");
|
||||
if (ret < 0) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
count += ret;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
dev_err(spmx->dev, "No child nodes passed via DT\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*map = kcalloc(count, sizeof(**map), GFP_KERNEL);
|
||||
if (!*map)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
of_property_read_string(np, "sirf,function", &function);
|
||||
of_property_for_each_string(np, "sirf,pins", prop, group) {
|
||||
(*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[index].data.mux.group = group;
|
||||
(*map)[index].data.mux.function = function;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
*num_maps = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops sirfsoc_pctrl_ops = {
|
||||
.get_groups_count = sirfsoc_get_groups_count,
|
||||
.get_group_name = sirfsoc_get_group_name,
|
||||
.get_group_pins = sirfsoc_get_group_pins,
|
||||
.pin_dbg_show = sirfsoc_pin_dbg_show,
|
||||
.dt_node_to_map = sirfsoc_dt_node_to_map,
|
||||
.dt_free_map = sirfsoc_dt_free_map,
|
||||
};
|
||||
|
||||
static struct sirfsoc_pmx_func *sirfsoc_pmx_functions;
|
||||
static int sirfsoc_pmxfunc_cnt;
|
||||
|
||||
static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx,
|
||||
unsigned selector, bool enable)
|
||||
{
|
||||
int i;
|
||||
const struct sirfsoc_padmux *mux =
|
||||
sirfsoc_pmx_functions[selector].padmux;
|
||||
const struct sirfsoc_muxmask *mask = mux->muxmask;
|
||||
|
||||
for (i = 0; i < mux->muxmask_counts; i++) {
|
||||
u32 muxval;
|
||||
muxval = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
if (enable)
|
||||
muxval = muxval & ~mask[i].mask;
|
||||
else
|
||||
muxval = muxval | mask[i].mask;
|
||||
writel(muxval, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
}
|
||||
|
||||
if (mux->funcmask && enable) {
|
||||
u32 func_en_val;
|
||||
|
||||
func_en_val =
|
||||
readl(spmx->rsc_virtbase + mux->ctrlreg);
|
||||
func_en_val =
|
||||
(func_en_val & ~mux->funcmask) | (mux->funcval);
|
||||
writel(func_en_val, spmx->rsc_virtbase + mux->ctrlreg);
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_set_mux(struct pinctrl_dev *pmxdev,
|
||||
unsigned selector,
|
||||
unsigned group)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
sirfsoc_pinmux_endisable(spmx, selector, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
|
||||
{
|
||||
return sirfsoc_pmxfunc_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pmx_functions[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned selector,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
*groups = sirfsoc_pmx_functions[selector].groups;
|
||||
*num_groups = sirfsoc_pmx_functions[selector].num_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
int group = range->id;
|
||||
|
||||
u32 muxval;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
|
||||
muxval = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(group));
|
||||
muxval = muxval | (1 << (offset - range->pin_base));
|
||||
writel(muxval, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(group));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinmux_ops sirfsoc_pinmux_ops = {
|
||||
.set_mux = sirfsoc_pinmux_set_mux,
|
||||
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
|
||||
.get_function_name = sirfsoc_pinmux_get_func_name,
|
||||
.get_function_groups = sirfsoc_pinmux_get_groups,
|
||||
.gpio_request_enable = sirfsoc_pinmux_request_gpio,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc sirfsoc_pinmux_desc = {
|
||||
.name = DRIVER_NAME,
|
||||
.pctlops = &sirfsoc_pctrl_ops,
|
||||
.pmxops = &sirfsoc_pinmux_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void __iomem *sirfsoc_rsc_of_iomap(void)
|
||||
{
|
||||
const struct of_device_id rsc_ids[] = {
|
||||
{ .compatible = "sirf,prima2-rsc" },
|
||||
{}
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, rsc_ids);
|
||||
if (!np)
|
||||
panic("unable to find compatible rsc node in dtb\n");
|
||||
|
||||
return of_iomap(np, 0);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec,
|
||||
u32 *flags)
|
||||
{
|
||||
if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return gpiospec->args[0];
|
||||
}
|
||||
|
||||
static const struct of_device_id pinmux_ids[] = {
|
||||
{ .compatible = "sirf,prima2-pinctrl", .data = &prima2_pinctrl_data, },
|
||||
{ .compatible = "sirf,atlas6-pinctrl", .data = &atlas6_pinctrl_data, },
|
||||
{}
|
||||
};
|
||||
|
||||
static int sirfsoc_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct sirfsoc_pmx *spmx;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct sirfsoc_pinctrl_data *pdata;
|
||||
|
||||
/* Create state holders etc for this driver */
|
||||
spmx = devm_kzalloc(&pdev->dev, sizeof(*spmx), GFP_KERNEL);
|
||||
if (!spmx)
|
||||
return -ENOMEM;
|
||||
|
||||
spmx->dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, spmx);
|
||||
|
||||
spmx->gpio_virtbase = of_iomap(np, 0);
|
||||
if (!spmx->gpio_virtbase) {
|
||||
dev_err(&pdev->dev, "can't map gpio registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spmx->rsc_virtbase = sirfsoc_rsc_of_iomap();
|
||||
if (!spmx->rsc_virtbase) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "can't map rsc registers\n");
|
||||
goto out_no_rsc_remap;
|
||||
}
|
||||
|
||||
pdata = of_match_node(pinmux_ids, np)->data;
|
||||
sirfsoc_pin_groups = pdata->grps;
|
||||
sirfsoc_pingrp_cnt = pdata->grps_cnt;
|
||||
sirfsoc_pmx_functions = pdata->funcs;
|
||||
sirfsoc_pmxfunc_cnt = pdata->funcs_cnt;
|
||||
sirfsoc_pinmux_desc.pins = pdata->pads;
|
||||
sirfsoc_pinmux_desc.npins = pdata->pads_cnt;
|
||||
|
||||
|
||||
/* Now register the pin controller and all pins it handles */
|
||||
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
|
||||
if (IS_ERR(spmx->pmx)) {
|
||||
dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n");
|
||||
ret = PTR_ERR(spmx->pmx);
|
||||
goto out_no_pmx;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_pmx:
|
||||
iounmap(spmx->rsc_virtbase);
|
||||
out_no_rsc_remap:
|
||||
iounmap(spmx->gpio_virtbase);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sirfsoc_pinmux_suspend_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
spmx->gpio_regs[i][j] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
spmx->ints_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
spmx->paden_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
spmx->dspen_regs = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
spmx->rsc_regs[i] = readl(spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_resume_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
writel(spmx->gpio_regs[i][j], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
writel(spmx->ints_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
writel(spmx->paden_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
writel(spmx->dspen_regs, spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
writel(spmx->rsc_regs[i], spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sirfsoc_pinmux_pm_ops = {
|
||||
.suspend_noirq = sirfsoc_pinmux_suspend_noirq,
|
||||
.resume_noirq = sirfsoc_pinmux_resume_noirq,
|
||||
.freeze_noirq = sirfsoc_pinmux_suspend_noirq,
|
||||
.restore_noirq = sirfsoc_pinmux_resume_noirq,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver sirfsoc_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = pinmux_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &sirfsoc_pinmux_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = sirfsoc_pinmux_probe,
|
||||
};
|
||||
|
||||
static int __init sirfsoc_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&sirfsoc_pinmux_driver);
|
||||
}
|
||||
arch_initcall(sirfsoc_pinmux_init);
|
||||
|
||||
static inline struct sirfsoc_gpio_bank *
|
||||
sirfsoc_gpio_to_bank(struct sirfsoc_gpio_chip *sgpio, unsigned int offset)
|
||||
{
|
||||
return &sgpio->sgpio_bank[offset / SIRFSOC_GPIO_BANK_SIZE];
|
||||
}
|
||||
|
||||
static inline int sirfsoc_gpio_to_bankoff(unsigned int offset)
|
||||
{
|
||||
return offset % SIRFSOC_GPIO_BANK_SIZE;
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
}
|
||||
|
||||
static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_chip *sgpio,
|
||||
struct sirfsoc_gpio_bank *bank,
|
||||
int idx)
|
||||
{
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(sgpio, bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, d->hwirq);
|
||||
int idx = sirfsoc_gpio_to_bankoff(d->hwirq);
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + offset);
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_STS_MASK | SIRFSOC_GPIO_CTL_OUT_EN_MASK);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_NONE:
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip sirfsoc_irq_chip = {
|
||||
.name = "sirf-gpio-irq",
|
||||
.irq_ack = sirfsoc_gpio_irq_ack,
|
||||
.irq_mask = sirfsoc_gpio_irq_mask,
|
||||
.irq_unmask = sirfsoc_gpio_irq_unmask,
|
||||
.irq_set_type = sirfsoc_gpio_irq_type,
|
||||
};
|
||||
|
||||
static void sirfsoc_gpio_handle_irq(struct irq_desc *desc)
|
||||
{
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(gc);
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
u32 status, ctrl;
|
||||
int idx = 0;
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
bank = &sgpio->sgpio_bank[i];
|
||||
if (bank->parent_irq == irq)
|
||||
break;
|
||||
}
|
||||
BUG_ON(i == SIRFSOC_GPIO_NO_OF_BANKS);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
status = readl(sgpio->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
|
||||
if (!status) {
|
||||
printk(KERN_WARNING
|
||||
"%s: gpio id %d status %#x no interrupt is flagged\n",
|
||||
__func__, bank->id, status);
|
||||
handle_bad_irq(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
while (status) {
|
||||
ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
|
||||
|
||||
/*
|
||||
* Here we must check whether the corresponding GPIO's interrupt
|
||||
* has been enabled, otherwise just skip it
|
||||
*/
|
||||
if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
|
||||
pr_debug("%s: gpio id %d idx %d happens\n",
|
||||
__func__, bank->id, idx);
|
||||
generic_handle_irq(irq_find_mapping(gc->irq.domain, idx +
|
||||
bank->id * SIRFSOC_GPIO_BANK_SIZE));
|
||||
}
|
||||
|
||||
idx++;
|
||||
status = status >> 1;
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_chip *sgpio,
|
||||
unsigned ctrl_offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(sgpio->chip.regs + ctrl_offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(val, sgpio->chip.regs + ctrl_offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
unsigned long flags;
|
||||
|
||||
if (pinctrl_gpio_request(chip->base + offset))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
/*
|
||||
* default status:
|
||||
* set direction as input and mask irq
|
||||
*/
|
||||
sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
__sirfsoc_gpio_irq_mask(sgpio, bank, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(sgpio, bank, offset);
|
||||
sirfsoc_gpio_set_input(sgpio, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
pinctrl_gpio_free(chip->base + offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
|
||||
int idx = sirfsoc_gpio_to_bankoff(gpio);
|
||||
unsigned long flags;
|
||||
unsigned offset;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_input(sgpio, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_chip *sgpio,
|
||||
struct sirfsoc_gpio_bank *bank,
|
||||
unsigned offset,
|
||||
int value)
|
||||
{
|
||||
u32 out_ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
out_ctrl = readl(sgpio->chip.regs + offset);
|
||||
if (value)
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(out_ctrl, sgpio->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned gpio, int value)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio);
|
||||
int idx = sirfsoc_gpio_to_bankoff(gpio);
|
||||
u32 offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio->lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_output(sgpio, bank, offset, value);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
val = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct sirfsoc_gpio_chip *sgpio = gpiochip_get_data(chip);
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, offset);
|
||||
u32 ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
ctrl = readl(sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
if (value)
|
||||
ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
writel(ctrl, sgpio->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_pullup(struct sirfsoc_gpio_chip *sgpio,
|
||||
const u32 *pullups)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pullups;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio->chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_pulldown(struct sirfsoc_gpio_chip *sgpio,
|
||||
const u32 *pulldowns)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pulldowns;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio->chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio->chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_probe(struct device_node *np)
|
||||
{
|
||||
int i, err = 0;
|
||||
struct sirfsoc_gpio_chip *sgpio;
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
void __iomem *regs;
|
||||
struct platform_device *pdev;
|
||||
struct gpio_irq_chip *girq;
|
||||
|
||||
u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
sgpio = devm_kzalloc(&pdev->dev, sizeof(*sgpio), GFP_KERNEL);
|
||||
if (!sgpio) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_device;
|
||||
}
|
||||
spin_lock_init(&sgpio->lock);
|
||||
|
||||
regs = of_iomap(np, 0);
|
||||
if (!regs) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_device;
|
||||
}
|
||||
|
||||
sgpio->chip.gc.request = sirfsoc_gpio_request;
|
||||
sgpio->chip.gc.free = sirfsoc_gpio_free;
|
||||
sgpio->chip.gc.direction_input = sirfsoc_gpio_direction_input;
|
||||
sgpio->chip.gc.get = sirfsoc_gpio_get_value;
|
||||
sgpio->chip.gc.direction_output = sirfsoc_gpio_direction_output;
|
||||
sgpio->chip.gc.set = sirfsoc_gpio_set_value;
|
||||
sgpio->chip.gc.base = 0;
|
||||
sgpio->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS;
|
||||
sgpio->chip.gc.label = kasprintf(GFP_KERNEL, "%pOF", np);
|
||||
sgpio->chip.gc.of_node = np;
|
||||
sgpio->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
|
||||
sgpio->chip.gc.of_gpio_n_cells = 2;
|
||||
sgpio->chip.gc.parent = &pdev->dev;
|
||||
sgpio->chip.regs = regs;
|
||||
|
||||
girq = &sgpio->chip.gc.irq;
|
||||
girq->chip = &sirfsoc_irq_chip;
|
||||
girq->parent_handler = sirfsoc_gpio_handle_irq;
|
||||
girq->num_parents = SIRFSOC_GPIO_NO_OF_BANKS;
|
||||
girq->parents = devm_kcalloc(&pdev->dev, SIRFSOC_GPIO_NO_OF_BANKS,
|
||||
sizeof(*girq->parents),
|
||||
GFP_KERNEL);
|
||||
if (!girq->parents) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_device;
|
||||
}
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
bank = &sgpio->sgpio_bank[i];
|
||||
spin_lock_init(&bank->lock);
|
||||
bank->parent_irq = platform_get_irq(pdev, i);
|
||||
if (bank->parent_irq < 0) {
|
||||
err = bank->parent_irq;
|
||||
goto out;
|
||||
}
|
||||
girq->parents[i] = bank->parent_irq;
|
||||
}
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_level_irq;
|
||||
|
||||
err = gpiochip_add_data(&sgpio->chip.gc, sgpio);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "%pOF: error in probe function with status %d\n",
|
||||
np, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = gpiochip_add_pin_range(&sgpio->chip.gc, dev_name(&pdev->dev),
|
||||
0, 0, SIRFSOC_GPIO_BANK_SIZE * SIRFSOC_GPIO_NO_OF_BANKS);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"could not add gpiochip pin range\n");
|
||||
goto out_no_range;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pullups", pullups,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pullup(sgpio, pullups);
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pulldown(sgpio, pulldowns);
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_range:
|
||||
gpiochip_remove(&sgpio->chip.gc);
|
||||
out:
|
||||
iounmap(regs);
|
||||
out_put_device:
|
||||
put_device(&pdev->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init sirfsoc_gpio_init(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, pinmux_ids);
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
return sirfsoc_gpio_probe(np);
|
||||
}
|
||||
subsys_initcall(sirfsoc_gpio_init);
|
@ -1,116 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* pinmux driver shared headfile for CSR SiRFsoc
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*/
|
||||
|
||||
#ifndef __PINMUX_SIRF_H__
|
||||
#define __PINMUX_SIRF_H__
|
||||
|
||||
#define SIRFSOC_NUM_PADS 622
|
||||
#define SIRFSOC_RSC_USB_UART_SHARE 0
|
||||
#define SIRFSOC_RSC_PIN_MUX 0x4
|
||||
|
||||
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
|
||||
#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90)
|
||||
#define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4)
|
||||
#define SIRFSOC_GPIO_DSP_EN0 (0x80)
|
||||
#define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C)
|
||||
|
||||
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
|
||||
#define SIRFSOC_GPIO_CTL_INTR_HIGH_MASK 0x2
|
||||
#define SIRFSOC_GPIO_CTL_INTR_TYPE_MASK 0x4
|
||||
#define SIRFSOC_GPIO_CTL_INTR_EN_MASK 0x8
|
||||
#define SIRFSOC_GPIO_CTL_INTR_STS_MASK 0x10
|
||||
#define SIRFSOC_GPIO_CTL_OUT_EN_MASK 0x20
|
||||
#define SIRFSOC_GPIO_CTL_DATAOUT_MASK 0x40
|
||||
#define SIRFSOC_GPIO_CTL_DATAIN_MASK 0x80
|
||||
#define SIRFSOC_GPIO_CTL_PULL_MASK 0x100
|
||||
#define SIRFSOC_GPIO_CTL_PULL_HIGH 0x200
|
||||
#define SIRFSOC_GPIO_CTL_DSP_INT 0x400
|
||||
|
||||
#define SIRFSOC_GPIO_NO_OF_BANKS 5
|
||||
#define SIRFSOC_GPIO_BANK_SIZE 32
|
||||
#define SIRFSOC_GPIO_NUM(bank, index) (((bank)*(32)) + (index))
|
||||
|
||||
/**
|
||||
* @dev: a pointer back to containing device
|
||||
* @virtbase: the offset to the controller in virtual memory
|
||||
*/
|
||||
struct sirfsoc_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pmx;
|
||||
void __iomem *gpio_virtbase;
|
||||
void __iomem *rsc_virtbase;
|
||||
u32 gpio_regs[SIRFSOC_GPIO_NO_OF_BANKS][SIRFSOC_GPIO_BANK_SIZE];
|
||||
u32 ints_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 paden_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 dspen_regs;
|
||||
u32 rsc_regs[3];
|
||||
};
|
||||
|
||||
/* SIRFSOC_GPIO_PAD_EN set */
|
||||
struct sirfsoc_muxmask {
|
||||
unsigned long group;
|
||||
unsigned long mask;
|
||||
};
|
||||
|
||||
struct sirfsoc_padmux {
|
||||
unsigned long muxmask_counts;
|
||||
const struct sirfsoc_muxmask *muxmask;
|
||||
/* RSC_PIN_MUX set */
|
||||
unsigned long ctrlreg;
|
||||
unsigned long funcmask;
|
||||
unsigned long funcval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sirfsoc_pin_group - describes a SiRFprimaII pin group
|
||||
* @name: the name of this specific pin group
|
||||
* @pins: an array of discrete physical pins used in this group, taken
|
||||
* from the driver-local pin enumeration space
|
||||
* @num_pins: the number of pins in this group array, i.e. the number of
|
||||
* elements in .pins so we can iterate over that array
|
||||
*/
|
||||
struct sirfsoc_pin_group {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
const unsigned num_pins;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PIN_GROUP(n, p) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.pins = p, \
|
||||
.num_pins = ARRAY_SIZE(p), \
|
||||
}
|
||||
|
||||
struct sirfsoc_pmx_func {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
const unsigned num_groups;
|
||||
const struct sirfsoc_padmux *padmux;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PMX_FUNCTION(n, g, m) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.groups = g, \
|
||||
.num_groups = ARRAY_SIZE(g), \
|
||||
.padmux = &m, \
|
||||
}
|
||||
|
||||
struct sirfsoc_pinctrl_data {
|
||||
struct pinctrl_pin_desc *pads;
|
||||
int pads_cnt;
|
||||
struct sirfsoc_pin_group *grps;
|
||||
int grps_cnt;
|
||||
struct sirfsoc_pmx_func *funcs;
|
||||
int funcs_cnt;
|
||||
};
|
||||
|
||||
extern struct sirfsoc_pinctrl_data prima2_pinctrl_data;
|
||||
extern struct sirfsoc_pinctrl_data atlas6_pinctrl_data;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user