提交 cdfe3175 编写于 作者: L Linus Walleij

Merge tag 'mvebu-pinctrl-3.15' of git://git.infradead.org/linux-mvebu into pinctrl-mvebu

mvebu pinctrl changes for v3.15

 - various cleanup and refactorization
 - add drivers for the Armada 375, 380, and 385 SoCs
 - prepare dove for SoC code moving into mach-mvebu
 - DT documentation updates
Marvell Dove Platforms Device Tree Bindings
-----------------------------------------------
Boards with a Marvell Dove SoC shall have the following properties:
Required root node property:
- compatible: must contain "marvell,dove";
* Global Configuration registers
Global Configuration registers of Dove SoC are shared by a syscon node.
Required properties:
- compatible: must contain "marvell,dove-global-config" and "syscon".
- reg: base address and size of the Global Configuration registers.
Example:
gconf: global-config@e802c {
compatible = "marvell,dove-global-config", "syscon";
reg = <0xe802c 0x14>;
};
...@@ -5,6 +5,7 @@ part and usage. ...@@ -5,6 +5,7 @@ part and usage.
Required properties: Required properties:
- compatible: "marvell,88f6710-pinctrl" - compatible: "marvell,88f6710-pinctrl"
- reg: register specifier of MPP registers
Available mpp pins/groups and functions: Available mpp pins/groups and functions:
Note: brackets (x) are not part of the mpp name for marvell,function and given Note: brackets (x) are not part of the mpp name for marvell,function and given
......
* Marvell Armada 375 SoC pinctrl driver for mpp
Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
part and usage.
Required properties:
- compatible: "marvell,88f6720-pinctrl"
- reg: register specifier of MPP registers
Available mpp pins/groups and functions:
Note: brackets (x) are not part of the mpp name for marvell,function and given
only for more detailed description in this document.
name pins functions
================================================================================
mpp0 0 gpio, dev(ad2), spi0(cs1), spi1(cs1)
mpp1 1 gpio, dev(ad3), spi0(mosi), spi1(mosi)
mpp2 2 gpio, dev(ad4), ptp(eventreq), led(c0), audio(sdi)
mpp3 3 gpio, dev(ad5), ptp(triggen), led(p3), audio(mclk)
mpp4 4 gpio, dev(ad6), spi0(miso), spi1(miso)
mpp5 5 gpio, dev(ad7), spi0(cs2), spi1(cs2)
mpp6 6 gpio, dev(ad0), led(p1), audio(rclk)
mpp7 7 gpio, dev(ad1), ptp(clk), led(p2), audio(extclk)
mpp8 8 gpio, dev (bootcs), spi0(cs0), spi1(cs0)
mpp9 9 gpio, nf(wen), spi0(sck), spi1(sck)
mpp10 10 gpio, nf(ren), dram(vttctrl), led(c1)
mpp11 11 gpio, dev(a0), led(c2), audio(sdo)
mpp12 12 gpio, dev(a1), audio(bclk)
mpp13 13 gpio, dev(readyn), pcie0(rstoutn), pcie1(rstoutn)
mpp14 14 gpio, i2c0(sda), uart1(txd)
mpp15 15 gpio, i2c0(sck), uart1(rxd)
mpp16 16 gpio, uart0(txd)
mpp17 17 gpio, uart0(rxd)
mpp18 18 gpio, tdm(intn)
mpp19 19 gpio, tdm(rstn)
mpp20 20 gpio, tdm(pclk)
mpp21 21 gpio, tdm(fsync)
mpp22 22 gpio, tdm(drx)
mpp23 23 gpio, tdm(dtx)
mpp24 24 gpio, led(p0), ge1(rxd0), sd(cmd), uart0(rts)
mpp25 25 gpio, led(p2), ge1(rxd1), sd(d0), uart0(cts)
mpp26 26 gpio, pcie0(clkreq), ge1(rxd2), sd(d2), uart1(rts)
mpp27 27 gpio, pcie1(clkreq), ge1(rxd3), sd(d1), uart1(cts)
mpp28 28 gpio, led(p3), ge1(txctl), sd(clk)
mpp29 29 gpio, pcie1(clkreq), ge1(rxclk), sd(d3)
mpp30 30 gpio, ge1(txd0), spi1(cs0)
mpp31 31 gpio, ge1(txd1), spi1(mosi)
mpp32 32 gpio, ge1(txd2), spi1(sck), ptp(triggen)
mpp33 33 gpio, ge1(txd3), spi1(miso)
mpp34 34 gpio, ge1(txclkout), spi1(sck)
mpp35 35 gpio, ge1(rxctl), spi1(cs1), spi0(cs2)
mpp36 36 gpio, pcie0(clkreq)
mpp37 37 gpio, pcie0(clkreq), tdm(intn), ge(mdc)
mpp38 38 gpio, pcie1(clkreq), ge(mdio)
mpp39 39 gpio, ref(clkout)
mpp40 40 gpio, uart1(txd)
mpp41 41 gpio, uart1(rxd)
mpp42 42 gpio, spi1(cs2), led(c0)
mpp43 43 gpio, sata0(prsnt), dram(vttctrl)
mpp44 44 gpio, sata0(prsnt)
mpp45 45 gpio, spi0(cs2), pcie0(rstoutn)
mpp46 46 gpio, led(p0), ge0(txd0), ge1(txd0)
mpp47 47 gpio, led(p1), ge0(txd1), ge1(txd1)
mpp48 48 gpio, led(p2), ge0(txd2), ge1(txd2)
mpp49 49 gpio, led(p3), ge0(txd3), ge1(txd3)
mpp50 50 gpio, led(c0), ge0(rxd0), ge1(rxd0)
mpp51 51 gpio, led(c1), ge0(rxd1), ge1(rxd1)
mpp52 52 gpio, led(c2), ge0(rxd2), ge1(rxd2)
mpp53 53 gpio, pcie1(rstoutn), ge0(rxd3), ge1(rxd3)
mpp54 54 gpio, pcie0(rstoutn), ge0(rxctl), ge1(rxctl)
mpp55 55 gpio, ge0(rxclk), ge1(rxclk)
mpp56 56 gpio, ge0(txclkout), ge1(txclkout)
mpp57 57 gpio, ge0(txctl), ge1(txctl)
mpp58 58 gpio, led(c0)
mpp59 59 gpio, led(c1)
mpp60 60 gpio, uart1(txd), led(c2)
mpp61 61 gpio, i2c1(sda), uart1(rxd), spi1(cs2), led(p0)
mpp62 62 gpio, i2c1(sck), led(p1)
mpp63 63 gpio, ptp(triggen), led(p2)
mpp64 64 gpio, dram(vttctrl), led(p3)
mpp65 65 gpio, sata1(prsnt)
mpp66 66 gpio, ptp(eventreq), spi1(cs3)
* Marvell Armada 380/385 SoC pinctrl driver for mpp
Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
part and usage.
Required properties:
- compatible: "marvell,88f6810-pinctrl", "marvell,88f6820-pinctrl" or
"marvell,88f6828-pinctrl" depending on the specific variant of the
SoC being used.
- reg: register specifier of MPP registers
Available mpp pins/groups and functions:
Note: brackets (x) are not part of the mpp name for marvell,function and given
only for more detailed description in this document.
name pins functions
================================================================================
mpp0 0 gpio, ua0(rxd)
mpp1 1 gpio, ua0(txd)
mpp2 2 gpio, i2c0(sck)
mpp3 3 gpio, i2c0(sda)
mpp4 4 gpio, ge(mdc), ua1(txd), ua0(rts)
mpp5 5 gpio, ge(mdio), ua1(rxd), ua0(cts)
mpp6 6 gpio, ge0(txclkout), ge0(crs), dev(cs3)
mpp7 7 gpio, ge0(txd0), dev(ad9)
mpp8 8 gpio, ge0(txd1), dev(ad10)
mpp9 9 gpio, ge0(txd2), dev(ad11)
mpp10 10 gpio, ge0(txd3), dev(ad12)
mpp11 11 gpio, ge0(txctl), dev(ad13)
mpp12 12 gpio, ge0(rxd0), pcie0(rstout), pcie1(rstout) [1], spi0(cs1), dev(ad14)
mpp13 13 gpio, ge0(rxd1), pcie0(clkreq), pcie1(clkreq) [1], spi0(cs2), dev(ad15)
mpp14 14 gpio, ge0(rxd2), ptp(clk), m(vtt_ctrl), spi0(cs3), dev(wen1)
mpp15 15 gpio, ge0(rxd3), ge(mdc slave), pcie0(rstout), spi0(mosi), pcie1(rstout) [1]
mpp16 16 gpio, ge0(rxctl), ge(mdio slave), m(decc_err), spi0(miso), pcie0(clkreq)
mpp17 17 gpio, ge0(rxclk), ptp(clk), ua1(rxd), spi0(sck), sata1(prsnt)
mpp18 18 gpio, ge0(rxerr), ptp(trig_gen), ua1(txd), spi0(cs0), pcie1(rstout) [1]
mpp19 19 gpio, ge0(col), ptp(event_req), pcie0(clkreq), sata1(prsnt), ua0(cts)
mpp20 20 gpio, ge0(txclk), ptp(clk), pcie1(rstout) [1], sata0(prsnt), ua0(rts)
mpp21 21 gpio, spi0(cs1), ge1(rxd0), sata0(prsnt), sd0(cmd), dev(bootcs)
mpp22 22 gpio, spi0(mosi), dev(ad0)
mpp23 23 gpio, spi0(sck), dev(ad2)
mpp24 24 gpio, spi0(miso), ua0(cts), ua1(rxd), sd0(d4), dev(ready)
mpp25 25 gpio, spi0(cs0), ua0(rts), ua1(txd), sd0(d5), dev(cs0)
mpp26 26 gpio, spi0(cs2), i2c1(sck), sd0(d6), dev(cs1)
mpp27 27 gpio, spi0(cs3), ge1(txclkout), i2c1(sda), sd0(d7), dev(cs2)
mpp28 28 gpio, ge1(txd0), sd0(clk), dev(ad5)
mpp29 29 gpio, ge1(txd1), dev(ale0)
mpp30 30 gpio, ge1(txd2), dev(oen)
mpp31 31 gpio, ge1(txd3), dev(ale1)
mpp32 32 gpio, ge1(txctl), dev(wen0)
mpp33 33 gpio, m(decc_err), dev(ad3)
mpp34 34 gpio, dev(ad1)
mpp35 35 gpio, ref(clk_out1), dev(a1)
mpp36 36 gpio, ptp(trig_gen), dev(a0)
mpp37 37 gpio, ptp(clk), ge1(rxclk), sd0(d3), dev(ad8)
mpp38 38 gpio, ptp(event_req), ge1(rxd1), ref(clk_out0), sd0(d0), dev(ad4)
mpp39 39 gpio, i2c1(sck), ge1(rxd2), ua0(cts), sd0(d1), dev(a2)
mpp40 40 gpio, i2c1(sda), ge1(rxd3), ua0(rts), sd0(d2), dev(ad6)
mpp41 41 gpio, ua1(rxd), ge1(rxctl), ua0(cts), spi1(cs3), dev(burst/last)
mpp42 42 gpio, ua1(txd), ua0(rts), dev(ad7)
mpp43 43 gpio, pcie0(clkreq), m(vtt_ctrl), m(decc_err), pcie0(rstout), dev(clkout)
mpp44 44 gpio, sata0(prsnt), sata1(prsnt), sata2(prsnt) [2], sata3(prsnt) [3], pcie0(rstout)
mpp45 45 gpio, ref(clk_out0), pcie0(rstout), pcie1(rstout) [1], pcie2(rstout), pcie3(rstout)
mpp46 46 gpio, ref(clk_out1), pcie0(rstout), pcie1(rstout) [1], pcie2(rstout), pcie3(rstout)
mpp47 47 gpio, sata0(prsnt), sata1(prsnt), sata2(prsnt) [2], spi1(cs2), sata3(prsnt) [2]
mpp48 48 gpio, sata0(prsnt), m(vtt_ctrl), tdm2c(pclk), audio(mclk), sd0(d4)
mpp49 49 gpio, sata2(prsnt) [2], sata3(prsnt) [2], tdm2c(fsync), audio(lrclk), sd0(d5)
mpp50 50 gpio, pcie0(rstout), pcie1(rstout) [1], tdm2c(drx), audio(extclk), sd0(cmd)
mpp51 51 gpio, tdm2c(dtx), audio(sdo), m(decc_err)
mpp52 52 gpio, pcie0(rstout), pcie1(rstout) [1], tdm2c(intn), audio(sdi), sd0(d6)
mpp53 53 gpio, sata1(prsnt), sata0(prsnt), tdm2c(rstn), audio(bclk), sd0(d7)
mpp54 54 gpio, sata0(prsnt), sata1(prsnt), pcie0(rstout), pcie1(rstout) [1], sd0(d3)
mpp55 55 gpio, ua1(cts), ge(mdio), pcie1(clkreq) [1], spi1(cs1), sd0(d0)
mpp56 56 gpio, ua1(rts), ge(mdc), m(decc_err), spi1(mosi)
mpp57 57 gpio, spi1(sck), sd0(clk)
mpp58 58 gpio, pcie1(clkreq) [1], i2c1(sck), pcie2(clkreq), spi1(miso), sd0(d1)
mpp59 59 gpio, pcie0(rstout), i2c1(sda), pcie1(rstout) [1], spi1(cs0), sd0(d2)
[1]: only available on 88F6820 and 88F6828
[2]: only available on 88F6828
...@@ -6,6 +6,7 @@ part and usage. ...@@ -6,6 +6,7 @@ part and usage.
Required properties: Required properties:
- compatible: "marvell,mv78230-pinctrl", "marvell,mv78260-pinctrl", - compatible: "marvell,mv78230-pinctrl", "marvell,mv78260-pinctrl",
"marvell,mv78460-pinctrl" "marvell,mv78460-pinctrl"
- reg: register specifier of MPP registers
This driver supports all Armada XP variants, i.e. mv78230, mv78260, and mv78460. This driver supports all Armada XP variants, i.e. mv78230, mv78260, and mv78460.
......
...@@ -6,6 +6,7 @@ part and usage. ...@@ -6,6 +6,7 @@ part and usage.
Required properties: Required properties:
- compatible: "marvell,dove-pinctrl" - compatible: "marvell,dove-pinctrl"
- clocks: (optional) phandle of pdma clock - clocks: (optional) phandle of pdma clock
- reg: register specifiers of MPP, MPP4, and PMU MPP registers
Available mpp pins/groups and functions: Available mpp pins/groups and functions:
Note: brackets (x) are not part of the mpp name for marvell,function and given Note: brackets (x) are not part of the mpp name for marvell,function and given
......
...@@ -8,6 +8,7 @@ Required properties: ...@@ -8,6 +8,7 @@ Required properties:
"marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl", "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
"marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl" "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
"marvell,98dx4122-pinctrl" "marvell,98dx4122-pinctrl"
- reg: register specifier of MPP registers
This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x. This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
It also support the 88f6281-based variant in the 98dx412x Bobcat SoCs. It also support the 88f6281-based variant in the 98dx412x Bobcat SoCs.
......
...@@ -37,7 +37,7 @@ uart1: serial@12100 { ...@@ -37,7 +37,7 @@ uart1: serial@12100 {
pinctrl: pinctrl@d0200 { pinctrl: pinctrl@d0200 {
compatible = "marvell,dove-pinctrl"; compatible = "marvell,dove-pinctrl";
reg = <0xd0200 0x20>; reg = <0xd0200 0x14>, <0xd0440 0x04>, <0xd802c 0x08>;
pmx_uart1_sw: pmx-uart1-sw { pmx_uart1_sw: pmx-uart1-sw {
marvell,pins = "mpp_uart1"; marvell,pins = "mpp_uart1";
......
...@@ -8,6 +8,7 @@ config PINCTRL_MVEBU ...@@ -8,6 +8,7 @@ config PINCTRL_MVEBU
config PINCTRL_DOVE config PINCTRL_DOVE
bool bool
select PINCTRL_MVEBU select PINCTRL_MVEBU
select MFD_SYSCON
config PINCTRL_KIRKWOOD config PINCTRL_KIRKWOOD
bool bool
...@@ -17,6 +18,14 @@ config PINCTRL_ARMADA_370 ...@@ -17,6 +18,14 @@ config PINCTRL_ARMADA_370
bool bool
select PINCTRL_MVEBU select PINCTRL_MVEBU
config PINCTRL_ARMADA_375
bool
select PINCTRL_MVEBU
config PINCTRL_ARMADA_38X
bool
select PINCTRL_MVEBU
config PINCTRL_ARMADA_XP config PINCTRL_ARMADA_XP
bool bool
select PINCTRL_MVEBU select PINCTRL_MVEBU
......
...@@ -2,4 +2,6 @@ obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o ...@@ -2,4 +2,6 @@ obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
obj-$(CONFIG_PINCTRL_ARMADA_375) += pinctrl-armada-375.o
obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o
obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
...@@ -23,6 +23,18 @@ ...@@ -23,6 +23,18 @@
#include "pinctrl-mvebu.h" #include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = { static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
MPP_MODE(0, MPP_MODE(0,
MPP_FUNCTION(0x0, "gpio", NULL), MPP_FUNCTION(0x0, "gpio", NULL),
...@@ -373,7 +385,7 @@ static struct of_device_id armada_370_pinctrl_of_match[] = { ...@@ -373,7 +385,7 @@ static struct of_device_id armada_370_pinctrl_of_match[] = {
}; };
static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = { static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
MPP_REG_CTRL(0, 65), MPP_FUNC_CTRL(0, 65, NULL, armada_370_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = { static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
...@@ -385,6 +397,12 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = { ...@@ -385,6 +397,12 @@ static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
static int armada_370_pinctrl_probe(struct platform_device *pdev) static int armada_370_pinctrl_probe(struct platform_device *pdev)
{ {
struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info; struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = 0; /* no variants for Armada 370 */ soc->variant = 0; /* no variants for Armada 370 */
soc->controls = mv88f6710_mpp_controls; soc->controls = mv88f6710_mpp_controls;
......
/*
* Marvell Armada 375 pinctrl driver based on mvebu pinctrl core
*
* Copyright (C) 2012 Marvell
*
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_375_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_375_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
static struct mvebu_mpp_mode mv88f6720_mpp_modes[] = {
MPP_MODE(0,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad2"),
MPP_FUNCTION(0x2, "spi0", "cs1"),
MPP_FUNCTION(0x3, "spi1", "cs1"),
MPP_FUNCTION(0x5, "nand", "io2")),
MPP_MODE(1,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad3"),
MPP_FUNCTION(0x2, "spi0", "mosi"),
MPP_FUNCTION(0x3, "spi1", "mosi"),
MPP_FUNCTION(0x5, "nand", "io3")),
MPP_MODE(2,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad4"),
MPP_FUNCTION(0x2, "ptp", "eventreq"),
MPP_FUNCTION(0x3, "led", "c0"),
MPP_FUNCTION(0x4, "audio", "sdi"),
MPP_FUNCTION(0x5, "nand", "io4"),
MPP_FUNCTION(0x6, "spi1", "mosi")),
MPP_MODE(3,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad5"),
MPP_FUNCTION(0x2, "ptp", "triggen"),
MPP_FUNCTION(0x3, "led", "p3"),
MPP_FUNCTION(0x4, "audio", "mclk"),
MPP_FUNCTION(0x5, "nand", "io5"),
MPP_FUNCTION(0x6, "spi1", "miso")),
MPP_MODE(4,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad6"),
MPP_FUNCTION(0x2, "spi0", "miso"),
MPP_FUNCTION(0x3, "spi1", "miso"),
MPP_FUNCTION(0x5, "nand", "io6")),
MPP_MODE(5,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad7"),
MPP_FUNCTION(0x2, "spi0", "cs2"),
MPP_FUNCTION(0x3, "spi1", "cs2"),
MPP_FUNCTION(0x5, "nand", "io7"),
MPP_FUNCTION(0x6, "spi1", "miso")),
MPP_MODE(6,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad0"),
MPP_FUNCTION(0x3, "led", "p1"),
MPP_FUNCTION(0x4, "audio", "rclk"),
MPP_FUNCTION(0x5, "nand", "io0")),
MPP_MODE(7,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "ad1"),
MPP_FUNCTION(0x2, "ptp", "clk"),
MPP_FUNCTION(0x3, "led", "p2"),
MPP_FUNCTION(0x4, "audio", "extclk"),
MPP_FUNCTION(0x5, "nand", "io1")),
MPP_MODE(8,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev ", "bootcs"),
MPP_FUNCTION(0x2, "spi0", "cs0"),
MPP_FUNCTION(0x3, "spi1", "cs0"),
MPP_FUNCTION(0x5, "nand", "ce")),
MPP_MODE(9,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "nf", "wen"),
MPP_FUNCTION(0x2, "spi0", "sck"),
MPP_FUNCTION(0x3, "spi1", "sck"),
MPP_FUNCTION(0x5, "nand", "we")),
MPP_MODE(10,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "nf", "ren"),
MPP_FUNCTION(0x2, "dram", "vttctrl"),
MPP_FUNCTION(0x3, "led", "c1"),
MPP_FUNCTION(0x5, "nand", "re"),
MPP_FUNCTION(0x6, "spi1", "sck")),
MPP_MODE(11,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "a0"),
MPP_FUNCTION(0x3, "led", "c2"),
MPP_FUNCTION(0x4, "audio", "sdo"),
MPP_FUNCTION(0x5, "nand", "cle")),
MPP_MODE(12,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "a1"),
MPP_FUNCTION(0x4, "audio", "bclk"),
MPP_FUNCTION(0x5, "nand", "ale")),
MPP_MODE(13,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "dev", "readyn"),
MPP_FUNCTION(0x2, "pcie0", "rstoutn"),
MPP_FUNCTION(0x3, "pcie1", "rstoutn"),
MPP_FUNCTION(0x5, "nand", "rb"),
MPP_FUNCTION(0x6, "spi1", "mosi")),
MPP_MODE(14,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "i2c0", "sda"),
MPP_FUNCTION(0x3, "uart1", "txd")),
MPP_MODE(15,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "i2c0", "sck"),
MPP_FUNCTION(0x3, "uart1", "rxd")),
MPP_MODE(16,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "uart0", "txd")),
MPP_MODE(17,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "uart0", "rxd")),
MPP_MODE(18,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "tdm", "intn")),
MPP_MODE(19,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "tdm", "rstn")),
MPP_MODE(20,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "tdm", "pclk")),
MPP_MODE(21,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "tdm", "fsync")),
MPP_MODE(22,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "tdm", "drx")),
MPP_MODE(23,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "tdm", "dtx")),
MPP_MODE(24,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p0"),
MPP_FUNCTION(0x2, "ge1", "rxd0"),
MPP_FUNCTION(0x3, "sd", "cmd"),
MPP_FUNCTION(0x4, "uart0", "rts"),
MPP_FUNCTION(0x5, "spi0", "cs0"),
MPP_FUNCTION(0x6, "dev", "cs1")),
MPP_MODE(25,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p2"),
MPP_FUNCTION(0x2, "ge1", "rxd1"),
MPP_FUNCTION(0x3, "sd", "d0"),
MPP_FUNCTION(0x4, "uart0", "cts"),
MPP_FUNCTION(0x5, "spi0", "mosi"),
MPP_FUNCTION(0x6, "dev", "cs2")),
MPP_MODE(26,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie0", "clkreq"),
MPP_FUNCTION(0x2, "ge1", "rxd2"),
MPP_FUNCTION(0x3, "sd", "d2"),
MPP_FUNCTION(0x4, "uart1", "rts"),
MPP_FUNCTION(0x5, "spi0", "cs1"),
MPP_FUNCTION(0x6, "led", "c1")),
MPP_MODE(27,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie1", "clkreq"),
MPP_FUNCTION(0x2, "ge1", "rxd3"),
MPP_FUNCTION(0x3, "sd", "d1"),
MPP_FUNCTION(0x4, "uart1", "cts"),
MPP_FUNCTION(0x5, "spi0", "miso"),
MPP_FUNCTION(0x6, "led", "c2")),
MPP_MODE(28,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p3"),
MPP_FUNCTION(0x2, "ge1", "txctl"),
MPP_FUNCTION(0x3, "sd", "clk"),
MPP_FUNCTION(0x5, "dram", "vttctrl")),
MPP_MODE(29,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie1", "clkreq"),
MPP_FUNCTION(0x2, "ge1", "rxclk"),
MPP_FUNCTION(0x3, "sd", "d3"),
MPP_FUNCTION(0x5, "spi0", "sck"),
MPP_FUNCTION(0x6, "pcie0", "rstoutn")),
MPP_MODE(30,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge1", "txd0"),
MPP_FUNCTION(0x3, "spi1", "cs0"),
MPP_FUNCTION(0x5, "led", "p3"),
MPP_FUNCTION(0x6, "ptp", "eventreq")),
MPP_MODE(31,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge1", "txd1"),
MPP_FUNCTION(0x3, "spi1", "mosi"),
MPP_FUNCTION(0x5, "led", "p0")),
MPP_MODE(32,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge1", "txd2"),
MPP_FUNCTION(0x3, "spi1", "sck"),
MPP_FUNCTION(0x4, "ptp", "triggen"),
MPP_FUNCTION(0x5, "led", "c0")),
MPP_MODE(33,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge1", "txd3"),
MPP_FUNCTION(0x3, "spi1", "miso"),
MPP_FUNCTION(0x5, "led", "p2")),
MPP_MODE(34,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge1", "txclkout"),
MPP_FUNCTION(0x3, "spi1", "sck"),
MPP_FUNCTION(0x5, "led", "c1")),
MPP_MODE(35,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge1", "rxctl"),
MPP_FUNCTION(0x3, "spi1", "cs1"),
MPP_FUNCTION(0x4, "spi0", "cs2"),
MPP_FUNCTION(0x5, "led", "p1")),
MPP_MODE(36,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie0", "clkreq"),
MPP_FUNCTION(0x5, "led", "c2")),
MPP_MODE(37,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie0", "clkreq"),
MPP_FUNCTION(0x2, "tdm", "intn"),
MPP_FUNCTION(0x4, "ge", "mdc")),
MPP_MODE(38,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie1", "clkreq"),
MPP_FUNCTION(0x4, "ge", "mdio")),
MPP_MODE(39,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x4, "ref", "clkout"),
MPP_FUNCTION(0x5, "led", "p3")),
MPP_MODE(40,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x4, "uart1", "txd"),
MPP_FUNCTION(0x5, "led", "p0")),
MPP_MODE(41,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x4, "uart1", "rxd"),
MPP_FUNCTION(0x5, "led", "p1")),
MPP_MODE(42,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x3, "spi1", "cs2"),
MPP_FUNCTION(0x4, "led", "c0"),
MPP_FUNCTION(0x6, "ptp", "clk")),
MPP_MODE(43,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "sata0", "prsnt"),
MPP_FUNCTION(0x4, "dram", "vttctrl"),
MPP_FUNCTION(0x5, "led", "c1")),
MPP_MODE(44,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x4, "sata0", "prsnt")),
MPP_MODE(45,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "spi0", "cs2"),
MPP_FUNCTION(0x4, "pcie0", "rstoutn"),
MPP_FUNCTION(0x5, "led", "c2"),
MPP_FUNCTION(0x6, "spi1", "cs2")),
MPP_MODE(46,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p0"),
MPP_FUNCTION(0x2, "ge0", "txd0"),
MPP_FUNCTION(0x3, "ge1", "txd0"),
MPP_FUNCTION(0x6, "dev", "wen1")),
MPP_MODE(47,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p1"),
MPP_FUNCTION(0x2, "ge0", "txd1"),
MPP_FUNCTION(0x3, "ge1", "txd1"),
MPP_FUNCTION(0x5, "ptp", "triggen"),
MPP_FUNCTION(0x6, "dev", "ale0")),
MPP_MODE(48,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p2"),
MPP_FUNCTION(0x2, "ge0", "txd2"),
MPP_FUNCTION(0x3, "ge1", "txd2"),
MPP_FUNCTION(0x6, "dev", "ale1")),
MPP_MODE(49,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "p3"),
MPP_FUNCTION(0x2, "ge0", "txd3"),
MPP_FUNCTION(0x3, "ge1", "txd3"),
MPP_FUNCTION(0x6, "dev", "a2")),
MPP_MODE(50,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "c0"),
MPP_FUNCTION(0x2, "ge0", "rxd0"),
MPP_FUNCTION(0x3, "ge1", "rxd0"),
MPP_FUNCTION(0x5, "ptp", "eventreq"),
MPP_FUNCTION(0x6, "dev", "ad12")),
MPP_MODE(51,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "c1"),
MPP_FUNCTION(0x2, "ge0", "rxd1"),
MPP_FUNCTION(0x3, "ge1", "rxd1"),
MPP_FUNCTION(0x6, "dev", "ad8")),
MPP_MODE(52,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "led", "c2"),
MPP_FUNCTION(0x2, "ge0", "rxd2"),
MPP_FUNCTION(0x3, "ge1", "rxd2"),
MPP_FUNCTION(0x5, "i2c0", "sda"),
MPP_FUNCTION(0x6, "dev", "ad9")),
MPP_MODE(53,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie1", "rstoutn"),
MPP_FUNCTION(0x2, "ge0", "rxd3"),
MPP_FUNCTION(0x3, "ge1", "rxd3"),
MPP_FUNCTION(0x5, "i2c0", "sck"),
MPP_FUNCTION(0x6, "dev", "ad10")),
MPP_MODE(54,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "pcie0", "rstoutn"),
MPP_FUNCTION(0x2, "ge0", "rxctl"),
MPP_FUNCTION(0x3, "ge1", "rxctl"),
MPP_FUNCTION(0x6, "dev", "ad11")),
MPP_MODE(55,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge0", "rxclk"),
MPP_FUNCTION(0x3, "ge1", "rxclk"),
MPP_FUNCTION(0x6, "dev", "cs0")),
MPP_MODE(56,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge0", "txclkout"),
MPP_FUNCTION(0x3, "ge1", "txclkout"),
MPP_FUNCTION(0x6, "dev", "oe")),
MPP_MODE(57,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ge0", "txctl"),
MPP_FUNCTION(0x3, "ge1", "txctl"),
MPP_FUNCTION(0x6, "dev", "wen0")),
MPP_MODE(58,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x4, "led", "c0")),
MPP_MODE(59,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x4, "led", "c1")),
MPP_MODE(60,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "uart1", "txd"),
MPP_FUNCTION(0x4, "led", "c2"),
MPP_FUNCTION(0x6, "dev", "ad13")),
MPP_MODE(61,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "i2c1", "sda"),
MPP_FUNCTION(0x2, "uart1", "rxd"),
MPP_FUNCTION(0x3, "spi1", "cs2"),
MPP_FUNCTION(0x4, "led", "p0"),
MPP_FUNCTION(0x6, "dev", "ad14")),
MPP_MODE(62,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "i2c1", "sck"),
MPP_FUNCTION(0x4, "led", "p1"),
MPP_FUNCTION(0x6, "dev", "ad15")),
MPP_MODE(63,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ptp", "triggen"),
MPP_FUNCTION(0x4, "led", "p2"),
MPP_FUNCTION(0x6, "dev", "burst")),
MPP_MODE(64,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "dram", "vttctrl"),
MPP_FUNCTION(0x4, "led", "p3")),
MPP_MODE(65,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "sata1", "prsnt")),
MPP_MODE(66,
MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x2, "ptp", "eventreq"),
MPP_FUNCTION(0x4, "spi1", "cs3"),
MPP_FUNCTION(0x5, "pcie0", "rstoutn"),
MPP_FUNCTION(0x6, "dev", "cs3")),
};
static struct mvebu_pinctrl_soc_info armada_375_pinctrl_info;
static struct of_device_id armada_375_pinctrl_of_match[] = {
{ .compatible = "marvell,mv88f6720-pinctrl" },
{ },
};
static struct mvebu_mpp_ctrl mv88f6720_mpp_controls[] = {
MPP_FUNC_CTRL(0, 69, NULL, armada_375_mpp_ctrl),
};
static struct pinctrl_gpio_range mv88f6720_mpp_gpio_ranges[] = {
MPP_GPIO_RANGE(0, 0, 0, 32),
MPP_GPIO_RANGE(1, 32, 32, 32),
MPP_GPIO_RANGE(2, 64, 64, 3),
};
static int armada_375_pinctrl_probe(struct platform_device *pdev)
{
struct mvebu_pinctrl_soc_info *soc = &armada_375_pinctrl_info;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = 0; /* no variants for Armada 375 */
soc->controls = mv88f6720_mpp_controls;
soc->ncontrols = ARRAY_SIZE(mv88f6720_mpp_controls);
soc->modes = mv88f6720_mpp_modes;
soc->nmodes = ARRAY_SIZE(mv88f6720_mpp_modes);
soc->gpioranges = mv88f6720_mpp_gpio_ranges;
soc->ngpioranges = ARRAY_SIZE(mv88f6720_mpp_gpio_ranges);
pdev->dev.platform_data = soc;
return mvebu_pinctrl_probe(pdev);
}
static int armada_375_pinctrl_remove(struct platform_device *pdev)
{
return mvebu_pinctrl_remove(pdev);
}
static struct platform_driver armada_375_pinctrl_driver = {
.driver = {
.name = "armada-375-pinctrl",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(armada_375_pinctrl_of_match),
},
.probe = armada_375_pinctrl_probe,
.remove = armada_375_pinctrl_remove,
};
module_platform_driver(armada_375_pinctrl_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada 375 pinctrl driver");
MODULE_LICENSE("GPL v2");
此差异已折叠。
...@@ -33,6 +33,18 @@ ...@@ -33,6 +33,18 @@
#include "pinctrl-mvebu.h" #include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
enum armada_xp_variant { enum armada_xp_variant {
V_MV78230 = BIT(0), V_MV78230 = BIT(0),
V_MV78260 = BIT(1), V_MV78260 = BIT(1),
...@@ -366,7 +378,7 @@ static struct of_device_id armada_xp_pinctrl_of_match[] = { ...@@ -366,7 +378,7 @@ static struct of_device_id armada_xp_pinctrl_of_match[] = {
}; };
static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = { static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
MPP_REG_CTRL(0, 48), MPP_FUNC_CTRL(0, 48, NULL, armada_xp_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = { static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
...@@ -375,7 +387,7 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = { ...@@ -375,7 +387,7 @@ static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
}; };
static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = { static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
MPP_REG_CTRL(0, 66), MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = { static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
...@@ -385,7 +397,7 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = { ...@@ -385,7 +397,7 @@ static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
}; };
static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = { static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
MPP_REG_CTRL(0, 66), MPP_FUNC_CTRL(0, 66, NULL, armada_xp_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = { static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
...@@ -399,10 +411,16 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev) ...@@ -399,10 +411,16 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info; struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
const struct of_device_id *match = const struct of_device_id *match =
of_match_device(armada_xp_pinctrl_of_match, &pdev->dev); of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
struct resource *res;
if (!match) if (!match)
return -ENODEV; return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
soc->variant = (unsigned) match->data & 0xff; soc->variant = (unsigned) match->data & 0xff;
switch (soc->variant) { switch (soc->variant) {
......
...@@ -18,107 +18,122 @@ ...@@ -18,107 +18,122 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/regmap.h>
#include "pinctrl-mvebu.h" #include "pinctrl-mvebu.h"
#define DOVE_SB_REGS_VIRT_BASE IOMEM(0xfde00000) /* Internal registers can be configured at any 1 MiB aligned address */
#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0200) #define INT_REGS_MASK ~(SZ_1M - 1)
#define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10) #define MPP4_REGS_OFFS 0xd0440
#define DOVE_AU0_AC97_SEL BIT(16) #define PMU_REGS_OFFS 0xd802c
#define DOVE_PMU_SIGNAL_SELECT_0 (DOVE_SB_REGS_VIRT_BASE + 0xd802C) #define GC_REGS_OFFS 0xe802c
#define DOVE_PMU_SIGNAL_SELECT_1 (DOVE_SB_REGS_VIRT_BASE + 0xd8030)
#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C) /* MPP Base registers */
#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C) #define PMU_MPP_GENERAL_CTRL 0x10
#define DOVE_TWSI_ENABLE_OPTION1 BIT(7) #define AU0_AC97_SEL BIT(16)
#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE + 0xe8030)
#define DOVE_TWSI_ENABLE_OPTION2 BIT(20) /* MPP Control 4 register */
#define DOVE_TWSI_ENABLE_OPTION3 BIT(21) #define SPI_GPIO_SEL BIT(5)
#define DOVE_TWSI_OPTION3_GPIO BIT(22) #define UART1_GPIO_SEL BIT(4)
#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE + 0xe8034) #define AU1_GPIO_SEL BIT(3)
#define DOVE_SSP_ON_AU1 BIT(0) #define CAM_GPIO_SEL BIT(2)
#define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xe803c) #define SD1_GPIO_SEL BIT(1)
#define DOVE_AU1_SPDIFO_GPIO_EN BIT(1) #define SD0_GPIO_SEL BIT(0)
#define DOVE_NAND_GPIO_EN BIT(0)
#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0400) /* PMU Signal Select registers */
#define DOVE_MPP_CTRL4_VIRT_BASE (DOVE_GPIO_LO_VIRT_BASE + 0x40) #define PMU_SIGNAL_SELECT_0 0x00
#define DOVE_SPI_GPIO_SEL BIT(5) #define PMU_SIGNAL_SELECT_1 0x04
#define DOVE_UART1_GPIO_SEL BIT(4)
#define DOVE_AU1_GPIO_SEL BIT(3) /* Global Config regmap registers */
#define DOVE_CAM_GPIO_SEL BIT(2) #define GLOBAL_CONFIG_1 0x00
#define DOVE_SD1_GPIO_SEL BIT(1) #define TWSI_ENABLE_OPTION1 BIT(7)
#define DOVE_SD0_GPIO_SEL BIT(0) #define GLOBAL_CONFIG_2 0x04
#define TWSI_ENABLE_OPTION2 BIT(20)
#define MPPS_PER_REG 8 #define TWSI_ENABLE_OPTION3 BIT(21)
#define MPP_BITS 4 #define TWSI_OPTION3_GPIO BIT(22)
#define MPP_MASK 0xf #define SSP_CTRL_STATUS_1 0x08
#define SSP_ON_AU1 BIT(0)
#define MPP_GENERAL_CONFIG 0x10
#define AU1_SPDIFO_GPIO_EN BIT(1)
#define NAND_GPIO_EN BIT(0)
#define CONFIG_PMU BIT(4) #define CONFIG_PMU BIT(4)
static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl, static void __iomem *mpp_base;
unsigned long *config) static void __iomem *mpp4_base;
static void __iomem *pmu_base;
static struct regmap *gconfmap;
static int dove_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int dove_mpp_ctrl_set(unsigned pid, unsigned long config)
{ {
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS; return default_mpp_ctrl_set(mpp_base, pid, config);
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS; }
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
static int dove_pmu_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
unsigned long func; unsigned long func;
if (pmu & (1 << ctrl->pid)) { if ((pmu & BIT(pid)) == 0)
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off); return default_mpp_ctrl_get(mpp_base, pid, config);
*config = (func >> shift) & MPP_MASK;
*config |= CONFIG_PMU; func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
} else { *config = (func >> shift) & MVEBU_MPP_MASK;
func = readl(DOVE_MPP_VIRT_BASE + off); *config |= CONFIG_PMU;
*config = (func >> shift) & MPP_MASK;
}
return 0; return 0;
} }
static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl, static int dove_pmu_mpp_ctrl_set(unsigned pid, unsigned long config)
unsigned long config)
{ {
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS; unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS; unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
unsigned long func; unsigned long func;
if (config & CONFIG_PMU) { if ((config & CONFIG_PMU) == 0) {
writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL); writel(pmu & ~BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off); return default_mpp_ctrl_set(mpp_base, pid, config);
func &= ~(MPP_MASK << shift);
func |= (config & MPP_MASK) << shift;
writel(func, DOVE_PMU_SIGNAL_SELECT_0 + off);
} else {
writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
func = readl(DOVE_MPP_VIRT_BASE + off);
func &= ~(MPP_MASK << shift);
func |= (config & MPP_MASK) << shift;
writel(func, DOVE_MPP_VIRT_BASE + off);
} }
writel(pmu | BIT(pid), mpp_base + PMU_MPP_GENERAL_CTRL);
func = readl(pmu_base + PMU_SIGNAL_SELECT_0 + off);
func &= ~(MVEBU_MPP_MASK << shift);
func |= (config & MVEBU_MPP_MASK) << shift;
writel(func, pmu_base + PMU_SIGNAL_SELECT_0 + off);
return 0; return 0;
} }
static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl, static int dove_mpp4_ctrl_get(unsigned pid, unsigned long *config)
unsigned long *config)
{ {
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); unsigned long mpp4 = readl(mpp4_base);
unsigned long mask; unsigned long mask;
switch (ctrl->pid) { switch (pid) {
case 24: /* mpp_camera */ case 24: /* mpp_camera */
mask = DOVE_CAM_GPIO_SEL; mask = CAM_GPIO_SEL;
break; break;
case 40: /* mpp_sdio0 */ case 40: /* mpp_sdio0 */
mask = DOVE_SD0_GPIO_SEL; mask = SD0_GPIO_SEL;
break; break;
case 46: /* mpp_sdio1 */ case 46: /* mpp_sdio1 */
mask = DOVE_SD1_GPIO_SEL; mask = SD1_GPIO_SEL;
break; break;
case 58: /* mpp_spi0 */ case 58: /* mpp_spi0 */
mask = DOVE_SPI_GPIO_SEL; mask = SPI_GPIO_SEL;
break; break;
case 62: /* mpp_uart1 */ case 62: /* mpp_uart1 */
mask = DOVE_UART1_GPIO_SEL; mask = UART1_GPIO_SEL;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -129,27 +144,26 @@ static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl, ...@@ -129,27 +144,26 @@ static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0; return 0;
} }
static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl, static int dove_mpp4_ctrl_set(unsigned pid, unsigned long config)
unsigned long config)
{ {
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); unsigned long mpp4 = readl(mpp4_base);
unsigned long mask; unsigned long mask;
switch (ctrl->pid) { switch (pid) {
case 24: /* mpp_camera */ case 24: /* mpp_camera */
mask = DOVE_CAM_GPIO_SEL; mask = CAM_GPIO_SEL;
break; break;
case 40: /* mpp_sdio0 */ case 40: /* mpp_sdio0 */
mask = DOVE_SD0_GPIO_SEL; mask = SD0_GPIO_SEL;
break; break;
case 46: /* mpp_sdio1 */ case 46: /* mpp_sdio1 */
mask = DOVE_SD1_GPIO_SEL; mask = SD1_GPIO_SEL;
break; break;
case 58: /* mpp_spi0 */ case 58: /* mpp_spi0 */
mask = DOVE_SPI_GPIO_SEL; mask = SPI_GPIO_SEL;
break; break;
case 62: /* mpp_uart1 */ case 62: /* mpp_uart1 */
mask = DOVE_UART1_GPIO_SEL; mask = UART1_GPIO_SEL;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -159,74 +173,69 @@ static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl, ...@@ -159,74 +173,69 @@ static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
if (config) if (config)
mpp4 |= mask; mpp4 |= mask;
writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE); writel(mpp4, mpp4_base);
return 0; return 0;
} }
static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl, static int dove_nand_ctrl_get(unsigned pid, unsigned long *config)
unsigned long *config)
{ {
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); unsigned int gmpp;
*config = ((gmpp & DOVE_NAND_GPIO_EN) != 0); regmap_read(gconfmap, MPP_GENERAL_CONFIG, &gmpp);
*config = ((gmpp & NAND_GPIO_EN) != 0);
return 0; return 0;
} }
static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl, static int dove_nand_ctrl_set(unsigned pid, unsigned long config)
unsigned long config)
{ {
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); regmap_update_bits(gconfmap, MPP_GENERAL_CONFIG,
NAND_GPIO_EN,
gmpp &= ~DOVE_NAND_GPIO_EN; (config) ? NAND_GPIO_EN : 0);
if (config)
gmpp |= DOVE_NAND_GPIO_EN;
writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
return 0; return 0;
} }
static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl, static int dove_audio0_ctrl_get(unsigned pid, unsigned long *config)
unsigned long *config)
{ {
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
*config = ((pmu & DOVE_AU0_AC97_SEL) != 0); *config = ((pmu & AU0_AC97_SEL) != 0);
return 0; return 0;
} }
static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl, static int dove_audio0_ctrl_set(unsigned pid, unsigned long config)
unsigned long config)
{ {
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); unsigned long pmu = readl(mpp_base + PMU_MPP_GENERAL_CTRL);
pmu &= ~DOVE_AU0_AC97_SEL; pmu &= ~AU0_AC97_SEL;
if (config) if (config)
pmu |= DOVE_AU0_AC97_SEL; pmu |= AU0_AC97_SEL;
writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL); writel(pmu, mpp_base + PMU_MPP_GENERAL_CTRL);
return 0; return 0;
} }
static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl, static int dove_audio1_ctrl_get(unsigned pid, unsigned long *config)
unsigned long *config)
{ {
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); unsigned int mpp4 = readl(mpp4_base);
unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1); unsigned int sspc1;
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); unsigned int gmpp;
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); unsigned int gcfg2;
regmap_read(gconfmap, SSP_CTRL_STATUS_1, &sspc1);
regmap_read(gconfmap, MPP_GENERAL_CONFIG, &gmpp);
regmap_read(gconfmap, GLOBAL_CONFIG_2, &gcfg2);
*config = 0; *config = 0;
if (mpp4 & DOVE_AU1_GPIO_SEL) if (mpp4 & AU1_GPIO_SEL)
*config |= BIT(3); *config |= BIT(3);
if (sspc1 & DOVE_SSP_ON_AU1) if (sspc1 & SSP_ON_AU1)
*config |= BIT(2); *config |= BIT(2);
if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN) if (gmpp & AU1_SPDIFO_GPIO_EN)
*config |= BIT(1); *config |= BIT(1);
if (gcfg2 & DOVE_TWSI_OPTION3_GPIO) if (gcfg2 & TWSI_OPTION3_GPIO)
*config |= BIT(0); *config |= BIT(0);
/* SSP/TWSI only if I2S1 not set*/ /* SSP/TWSI only if I2S1 not set*/
...@@ -238,35 +247,24 @@ static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl, ...@@ -238,35 +247,24 @@ static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
return 0; return 0;
} }
static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl, static int dove_audio1_ctrl_set(unsigned pid, unsigned long config)
unsigned long config)
{ {
unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); unsigned int mpp4 = readl(mpp4_base);
unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
/* mpp4 &= ~AU1_GPIO_SEL;
* clear all audio1 related bits before configure
*/
gcfg2 &= ~DOVE_TWSI_OPTION3_GPIO;
gmpp &= ~DOVE_AU1_SPDIFO_GPIO_EN;
sspc1 &= ~DOVE_SSP_ON_AU1;
mpp4 &= ~DOVE_AU1_GPIO_SEL;
if (config & BIT(0))
gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
if (config & BIT(1))
gmpp |= DOVE_AU1_SPDIFO_GPIO_EN;
if (config & BIT(2))
sspc1 |= DOVE_SSP_ON_AU1;
if (config & BIT(3)) if (config & BIT(3))
mpp4 |= DOVE_AU1_GPIO_SEL; mpp4 |= AU1_GPIO_SEL;
writel(mpp4, mpp4_base);
writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
writel(sspc1, DOVE_SSP_CTRL_STATUS_1); regmap_update_bits(gconfmap, SSP_CTRL_STATUS_1,
writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE); SSP_ON_AU1,
writel(gcfg2, DOVE_GLOBAL_CONFIG_2); (config & BIT(2)) ? SSP_ON_AU1 : 0);
regmap_update_bits(gconfmap, MPP_GENERAL_CONFIG,
AU1_SPDIFO_GPIO_EN,
(config & BIT(1)) ? AU1_SPDIFO_GPIO_EN : 0);
regmap_update_bits(gconfmap, GLOBAL_CONFIG_2,
TWSI_OPTION3_GPIO,
(config & BIT(0)) ? TWSI_OPTION3_GPIO : 0);
return 0; return 0;
} }
...@@ -276,11 +274,11 @@ static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl, ...@@ -276,11 +274,11 @@ static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
* break other functions. If you require all mpps as gpio * break other functions. If you require all mpps as gpio
* enforce gpio setting by pinctrl mapping. * enforce gpio setting by pinctrl mapping.
*/ */
static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid) static int dove_audio1_ctrl_gpio_req(unsigned pid)
{ {
unsigned long config; unsigned long config;
dove_audio1_ctrl_get(ctrl, &config); dove_audio1_ctrl_get(pid, &config);
switch (config) { switch (config) {
case 0x02: /* i2s1 : gpio[56:57] */ case 0x02: /* i2s1 : gpio[56:57] */
...@@ -303,76 +301,62 @@ static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid) ...@@ -303,76 +301,62 @@ static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
} }
/* mpp[52:57] has gpio pins capable of in and out */ /* mpp[52:57] has gpio pins capable of in and out */
static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid, static int dove_audio1_ctrl_gpio_dir(unsigned pid, bool input)
bool input)
{ {
if (pid < 52 || pid > 57) if (pid < 52 || pid > 57)
return -ENOTSUPP; return -ENOTSUPP;
return 0; return 0;
} }
static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl, static int dove_twsi_ctrl_get(unsigned pid, unsigned long *config)
unsigned long *config)
{ {
unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1); unsigned int gcfg1;
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); unsigned int gcfg2;
regmap_read(gconfmap, GLOBAL_CONFIG_1, &gcfg1);
regmap_read(gconfmap, GLOBAL_CONFIG_2, &gcfg2);
*config = 0; *config = 0;
if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1) if (gcfg1 & TWSI_ENABLE_OPTION1)
*config = 1; *config = 1;
else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2) else if (gcfg2 & TWSI_ENABLE_OPTION2)
*config = 2; *config = 2;
else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3) else if (gcfg2 & TWSI_ENABLE_OPTION3)
*config = 3; *config = 3;
return 0; return 0;
} }
static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl, static int dove_twsi_ctrl_set(unsigned pid, unsigned long config)
unsigned long config)
{ {
unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1); unsigned int gcfg1 = 0;
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); unsigned int gcfg2 = 0;
gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION3);
switch (config) { switch (config) {
case 1: case 1:
gcfg1 |= DOVE_TWSI_ENABLE_OPTION1; gcfg1 = TWSI_ENABLE_OPTION1;
break; break;
case 2: case 2:
gcfg2 |= DOVE_TWSI_ENABLE_OPTION2; gcfg2 = TWSI_ENABLE_OPTION2;
break; break;
case 3: case 3:
gcfg2 |= DOVE_TWSI_ENABLE_OPTION3; gcfg2 = TWSI_ENABLE_OPTION3;
break; break;
} }
writel(gcfg1, DOVE_GLOBAL_CONFIG_1); regmap_update_bits(gconfmap, GLOBAL_CONFIG_1,
writel(gcfg2, DOVE_GLOBAL_CONFIG_2); TWSI_ENABLE_OPTION1,
gcfg1);
regmap_update_bits(gconfmap, GLOBAL_CONFIG_2,
TWSI_ENABLE_OPTION2 | TWSI_ENABLE_OPTION3,
gcfg2);
return 0; return 0;
} }
static struct mvebu_mpp_ctrl dove_mpp_controls[] = { static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl), MPP_FUNC_CTRL(0, 15, NULL, dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl), MPP_FUNC_CTRL(16, 23, NULL, dove_mpp_ctrl),
MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
MPP_REG_CTRL(16, 23),
MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl), MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl), MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl), MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
...@@ -772,8 +756,17 @@ static struct of_device_id dove_pinctrl_of_match[] = { ...@@ -772,8 +756,17 @@ static struct of_device_id dove_pinctrl_of_match[] = {
{ } { }
}; };
static struct regmap_config gc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = 5,
};
static int dove_pinctrl_probe(struct platform_device *pdev) static int dove_pinctrl_probe(struct platform_device *pdev)
{ {
struct resource *res, *mpp_res;
struct resource fb_res;
const struct of_device_id *match = const struct of_device_id *match =
of_match_device(dove_pinctrl_of_match, &pdev->dev); of_match_device(dove_pinctrl_of_match, &pdev->dev);
pdev->dev.platform_data = (void *)match->data; pdev->dev.platform_data = (void *)match->data;
...@@ -789,6 +782,58 @@ static int dove_pinctrl_probe(struct platform_device *pdev) ...@@ -789,6 +782,58 @@ static int dove_pinctrl_probe(struct platform_device *pdev)
} }
clk_prepare_enable(clk); clk_prepare_enable(clk);
mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, mpp_res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
/* prepare fallback resource */
memcpy(&fb_res, mpp_res, sizeof(struct resource));
fb_res.start = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
dev_warn(&pdev->dev, "falling back to hardcoded MPP4 resource\n");
adjust_resource(&fb_res,
(mpp_res->start & INT_REGS_MASK) + MPP4_REGS_OFFS, 0x4);
res = &fb_res;
}
mpp4_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp4_base))
return PTR_ERR(mpp4_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
if (!res) {
dev_warn(&pdev->dev, "falling back to hardcoded PMU resource\n");
adjust_resource(&fb_res,
(mpp_res->start & INT_REGS_MASK) + PMU_REGS_OFFS, 0x8);
res = &fb_res;
}
pmu_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pmu_base))
return PTR_ERR(pmu_base);
gconfmap = syscon_regmap_lookup_by_compatible("marvell,dove-global-config");
if (IS_ERR(gconfmap)) {
void __iomem *gc_base;
dev_warn(&pdev->dev, "falling back to hardcoded global registers\n");
adjust_resource(&fb_res,
(mpp_res->start & INT_REGS_MASK) + GC_REGS_OFFS, 0x14);
gc_base = devm_ioremap_resource(&pdev->dev, &fb_res);
if (IS_ERR(gc_base))
return PTR_ERR(gc_base);
gconfmap = devm_regmap_init_mmio(&pdev->dev,
gc_base, &gc_regmap_config);
if (IS_ERR(gconfmap))
return PTR_ERR(gconfmap);
}
/* Warn on any missing DT resource */
WARN(fb_res.start, FW_BUG "Missing pinctrl regs in DTB. Please update your firmware.\n");
return mvebu_pinctrl_probe(pdev); return mvebu_pinctrl_probe(pdev);
} }
......
...@@ -21,6 +21,18 @@ ...@@ -21,6 +21,18 @@
#include "pinctrl-mvebu.h" #include "pinctrl-mvebu.h"
static void __iomem *mpp_base;
static int kirkwood_mpp_ctrl_get(unsigned pid, unsigned long *config)
{
return default_mpp_ctrl_get(mpp_base, pid, config);
}
static int kirkwood_mpp_ctrl_set(unsigned pid, unsigned long config)
{
return default_mpp_ctrl_set(mpp_base, pid, config);
}
#define V(f6180, f6190, f6192, f6281, f6282, dx4122) \ #define V(f6180, f6190, f6192, f6281, f6282, dx4122) \
((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \ ((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
(f6281 << 3) | (f6282 << 4) | (dx4122 << 5)) (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
...@@ -359,7 +371,7 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = { ...@@ -359,7 +371,7 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
}; };
static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = { static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
MPP_REG_CTRL(0, 29), MPP_FUNC_CTRL(0, 29, NULL, kirkwood_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = { static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
...@@ -367,7 +379,7 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = { ...@@ -367,7 +379,7 @@ static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
}; };
static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = { static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
MPP_REG_CTRL(0, 35), MPP_FUNC_CTRL(0, 35, NULL, kirkwood_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = { static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
...@@ -376,7 +388,7 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = { ...@@ -376,7 +388,7 @@ static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
}; };
static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = { static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
MPP_REG_CTRL(0, 49), MPP_FUNC_CTRL(0, 49, NULL, kirkwood_mpp_ctrl),
}; };
static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = { static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
...@@ -456,9 +468,16 @@ static struct of_device_id kirkwood_pinctrl_of_match[] = { ...@@ -456,9 +468,16 @@ static struct of_device_id kirkwood_pinctrl_of_match[] = {
static int kirkwood_pinctrl_probe(struct platform_device *pdev) static int kirkwood_pinctrl_probe(struct platform_device *pdev)
{ {
struct resource *res;
const struct of_device_id *match = const struct of_device_id *match =
of_match_device(kirkwood_pinctrl_of_match, &pdev->dev); of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
pdev->dev.platform_data = (void *)match->data; pdev->dev.platform_data = (void *)match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mpp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mpp_base))
return PTR_ERR(mpp_base);
return mvebu_pinctrl_probe(pdev); return mvebu_pinctrl_probe(pdev);
} }
......
...@@ -50,7 +50,6 @@ struct mvebu_pinctrl { ...@@ -50,7 +50,6 @@ struct mvebu_pinctrl {
struct device *dev; struct device *dev;
struct pinctrl_dev *pctldev; struct pinctrl_dev *pctldev;
struct pinctrl_desc desc; struct pinctrl_desc desc;
void __iomem *base;
struct mvebu_pinctrl_group *groups; struct mvebu_pinctrl_group *groups;
unsigned num_groups; unsigned num_groups;
struct mvebu_pinctrl_function *functions; struct mvebu_pinctrl_function *functions;
...@@ -138,43 +137,6 @@ static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name( ...@@ -138,43 +137,6 @@ static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
return NULL; return NULL;
} }
/*
* Common mpp pin configuration registers on MVEBU are
* registers of eight 4-bit values for each mpp setting.
* Register offset and bit mask are calculated accordingly below.
*/
static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
struct mvebu_pinctrl_group *grp,
unsigned long *config)
{
unsigned pin = grp->gid;
unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
*config = readl(pctl->base + off);
*config >>= shift;
*config &= MPP_MASK;
return 0;
}
static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
struct mvebu_pinctrl_group *grp,
unsigned long config)
{
unsigned pin = grp->gid;
unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
unsigned long reg;
reg = readl(pctl->base + off);
reg &= ~(MPP_MASK << shift);
reg |= (config << shift);
writel(reg, pctl->base + off);
return 0;
}
static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev, static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
unsigned gid, unsigned long *config) unsigned gid, unsigned long *config)
{ {
...@@ -184,10 +146,7 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev, ...@@ -184,10 +146,7 @@ static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
if (!grp->ctrl) if (!grp->ctrl)
return -EINVAL; return -EINVAL;
if (grp->ctrl->mpp_get) return grp->ctrl->mpp_get(grp->pins[0], config);
return grp->ctrl->mpp_get(grp->ctrl, config);
return mvebu_common_mpp_get(pctl, grp, config);
} }
static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev, static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
...@@ -202,11 +161,7 @@ static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev, ...@@ -202,11 +161,7 @@ static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
return -EINVAL; return -EINVAL;
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
if (grp->ctrl->mpp_set) ret = grp->ctrl->mpp_set(grp->pins[0], configs[i]);
ret = grp->ctrl->mpp_set(grp->ctrl, configs[i]);
else
ret = mvebu_common_mpp_set(pctl, grp, configs[i]);
if (ret) if (ret)
return ret; return ret;
} /* for each config */ } /* for each config */
...@@ -347,7 +302,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, ...@@ -347,7 +302,7 @@ static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
return -EINVAL; return -EINVAL;
if (grp->ctrl->mpp_gpio_req) if (grp->ctrl->mpp_gpio_req)
return grp->ctrl->mpp_gpio_req(grp->ctrl, offset); return grp->ctrl->mpp_gpio_req(offset);
setting = mvebu_pinctrl_find_gpio_setting(pctl, grp); setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
if (!setting) if (!setting)
...@@ -370,7 +325,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, ...@@ -370,7 +325,7 @@ static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
return -EINVAL; return -EINVAL;
if (grp->ctrl->mpp_gpio_dir) if (grp->ctrl->mpp_gpio_dir)
return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input); return grp->ctrl->mpp_gpio_dir(offset, input);
setting = mvebu_pinctrl_find_gpio_setting(pctl, grp); setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
if (!setting) if (!setting)
...@@ -593,11 +548,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev, ...@@ -593,11 +548,12 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
int mvebu_pinctrl_probe(struct platform_device *pdev) int mvebu_pinctrl_probe(struct platform_device *pdev)
{ {
struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev); struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
struct resource *res;
struct mvebu_pinctrl *pctl; struct mvebu_pinctrl *pctl;
void __iomem *base;
struct pinctrl_pin_desc *pdesc; struct pinctrl_pin_desc *pdesc;
unsigned gid, n, k; unsigned gid, n, k;
unsigned size, noname = 0;
char *noname_buf;
void *p;
int ret; int ret;
if (!soc || !soc->controls || !soc->modes) { if (!soc || !soc->controls || !soc->modes) {
...@@ -605,11 +561,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) ...@@ -605,11 +561,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl), pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
GFP_KERNEL); GFP_KERNEL);
if (!pctl) { if (!pctl) {
...@@ -623,7 +574,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) ...@@ -623,7 +574,6 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->desc.pmxops = &mvebu_pinmux_ops; pctl->desc.pmxops = &mvebu_pinmux_ops;
pctl->desc.confops = &mvebu_pinconf_ops; pctl->desc.confops = &mvebu_pinconf_ops;
pctl->variant = soc->variant; pctl->variant = soc->variant;
pctl->base = base;
pctl->dev = &pdev->dev; pctl->dev = &pdev->dev;
platform_set_drvdata(pdev, pctl); platform_set_drvdata(pdev, pctl);
...@@ -633,33 +583,23 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) ...@@ -633,33 +583,23 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->desc.npins = 0; pctl->desc.npins = 0;
for (n = 0; n < soc->ncontrols; n++) { for (n = 0; n < soc->ncontrols; n++) {
struct mvebu_mpp_ctrl *ctrl = &soc->controls[n]; struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
char *names;
pctl->desc.npins += ctrl->npins; pctl->desc.npins += ctrl->npins;
/* initial control pins */ /* initialize control's pins[] array */
for (k = 0; k < ctrl->npins; k++) for (k = 0; k < ctrl->npins; k++)
ctrl->pins[k] = ctrl->pid + k; ctrl->pins[k] = ctrl->pid + k;
/* special soc specific control */ /*
if (ctrl->mpp_get || ctrl->mpp_set) { * We allow to pass controls with NULL name that we treat
if (!ctrl->name || !ctrl->mpp_get || !ctrl->mpp_set) { * as a range of one-pin groups with generic mvebu register
dev_err(&pdev->dev, "wrong soc control info\n"); * controls.
return -EINVAL; */
} if (!ctrl->name) {
pctl->num_groups += ctrl->npins;
noname += ctrl->npins;
} else {
pctl->num_groups += 1; pctl->num_groups += 1;
continue;
} }
/* generic mvebu register control */
names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
if (!names) {
dev_err(&pdev->dev, "failed to alloc mpp names\n");
return -ENOMEM;
}
for (k = 0; k < ctrl->npins; k++)
sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
ctrl->name = names;
pctl->num_groups += ctrl->npins;
} }
pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins * pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
...@@ -673,12 +613,17 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) ...@@ -673,12 +613,17 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pdesc[n].number = n; pdesc[n].number = n;
pctl->desc.pins = pdesc; pctl->desc.pins = pdesc;
pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups * /*
sizeof(struct mvebu_pinctrl_group), GFP_KERNEL); * allocate groups and name buffers for unnamed groups.
if (!pctl->groups) { */
dev_err(&pdev->dev, "failed to alloc pinctrl groups\n"); size = pctl->num_groups * sizeof(*pctl->groups) + noname * 8;
p = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!p) {
dev_err(&pdev->dev, "failed to alloc group data\n");
return -ENOMEM; return -ENOMEM;
} }
pctl->groups = p;
noname_buf = p + pctl->num_groups * sizeof(*pctl->groups);
/* assign mpp controls to groups */ /* assign mpp controls to groups */
gid = 0; gid = 0;
...@@ -690,17 +635,26 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) ...@@ -690,17 +635,26 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
pctl->groups[gid].pins = ctrl->pins; pctl->groups[gid].pins = ctrl->pins;
pctl->groups[gid].npins = ctrl->npins; pctl->groups[gid].npins = ctrl->npins;
/* generic mvebu register control maps to a number of groups */ /*
if (!ctrl->mpp_get && !ctrl->mpp_set) { * We treat unnamed controls as a range of one-pin groups
* with generic mvebu register controls. Use one group for
* each in this range and assign a default group name.
*/
if (!ctrl->name) {
pctl->groups[gid].name = noname_buf;
pctl->groups[gid].npins = 1; pctl->groups[gid].npins = 1;
sprintf(noname_buf, "mpp%d", ctrl->pid+0);
noname_buf += 8;
for (k = 1; k < ctrl->npins; k++) { for (k = 1; k < ctrl->npins; k++) {
gid++; gid++;
pctl->groups[gid].gid = gid; pctl->groups[gid].gid = gid;
pctl->groups[gid].ctrl = ctrl; pctl->groups[gid].ctrl = ctrl;
pctl->groups[gid].name = &ctrl->name[8*k]; pctl->groups[gid].name = noname_buf;
pctl->groups[gid].pins = &ctrl->pins[k]; pctl->groups[gid].pins = &ctrl->pins[k];
pctl->groups[gid].npins = 1; pctl->groups[gid].npins = 1;
sprintf(noname_buf, "mpp%d", ctrl->pid+k);
noname_buf += 8;
} }
} }
gid++; gid++;
......
...@@ -28,20 +28,19 @@ ...@@ -28,20 +28,19 @@
* between two or more different settings, e.g. assign mpp pin 13 to * between two or more different settings, e.g. assign mpp pin 13 to
* uart1 or sata. * uart1 or sata.
* *
* If optional mpp_get/_set functions are set these are used to get/set * The mpp_get/_set functions are mandatory and are used to get/set a
* a specific mode. Otherwise it is assumed that the mpp control is based * specific mode. The optional mpp_gpio_req/_dir functions can be used
* on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir * to allow pin settings with varying gpio pins.
* functions can be used to allow pin settings with varying gpio pins.
*/ */
struct mvebu_mpp_ctrl { struct mvebu_mpp_ctrl {
const char *name; const char *name;
u8 pid; u8 pid;
u8 npins; u8 npins;
unsigned *pins; unsigned *pins;
int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config); int (*mpp_get)(unsigned pid, unsigned long *config);
int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config); int (*mpp_set)(unsigned pid, unsigned long config);
int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid); int (*mpp_gpio_req)(unsigned pid);
int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input); int (*mpp_gpio_dir)(unsigned pid, bool input);
}; };
/** /**
...@@ -114,18 +113,6 @@ struct mvebu_pinctrl_soc_info { ...@@ -114,18 +113,6 @@ struct mvebu_pinctrl_soc_info {
int ngpioranges; int ngpioranges;
}; };
#define MPP_REG_CTRL(_idl, _idh) \
{ \
.name = NULL, \
.pid = _idl, \
.npins = _idh - _idl + 1, \
.pins = (unsigned[_idh - _idl + 1]) { }, \
.mpp_get = NULL, \
.mpp_set = NULL, \
.mpp_gpio_req = NULL, \
.mpp_gpio_dir = NULL, \
}
#define MPP_FUNC_CTRL(_idl, _idh, _name, _func) \ #define MPP_FUNC_CTRL(_idl, _idh, _name, _func) \
{ \ { \
.name = _name, \ .name = _name, \
...@@ -186,6 +173,34 @@ struct mvebu_pinctrl_soc_info { ...@@ -186,6 +173,34 @@ struct mvebu_pinctrl_soc_info {
.npins = _npins, \ .npins = _npins, \
} }
#define MVEBU_MPPS_PER_REG 8
#define MVEBU_MPP_BITS 4
#define MVEBU_MPP_MASK 0xf
static inline int default_mpp_ctrl_get(void __iomem *base, unsigned int pid,
unsigned long *config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
*config = (readl(base + off) >> shift) & MVEBU_MPP_MASK;
return 0;
}
static inline int default_mpp_ctrl_set(void __iomem *base, unsigned int pid,
unsigned long config)
{
unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
unsigned long reg;
reg = readl(base + off) & ~(MVEBU_MPP_MASK << shift);
writel(reg | (config << shift), base + off);
return 0;
}
int mvebu_pinctrl_probe(struct platform_device *pdev); int mvebu_pinctrl_probe(struct platform_device *pdev);
int mvebu_pinctrl_remove(struct platform_device *pdev); int mvebu_pinctrl_remove(struct platform_device *pdev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册