18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Marvell Armada ap806 pinctrl driver based on mvebu pinctrl core
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Marvell
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
88c2ecf20Sopenharmony_ci * Hanna Hawa <hannah@marvell.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/err.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/io.h>
148c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
158c2ecf20Sopenharmony_ci#include <linux/of.h>
168c2ecf20Sopenharmony_ci#include <linux/of_device.h>
178c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include "pinctrl-mvebu.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic struct mvebu_mpp_mode armada_ap806_mpp_modes[] = {
228c2ecf20Sopenharmony_ci	MPP_MODE(0,
238c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
248c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "clk"),
258c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "spi0",    "clk")),
268c2ecf20Sopenharmony_ci	MPP_MODE(1,
278c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
288c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "cmd"),
298c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "spi0",    "miso")),
308c2ecf20Sopenharmony_ci	MPP_MODE(2,
318c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
328c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d0"),
338c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "spi0",    "mosi")),
348c2ecf20Sopenharmony_ci	MPP_MODE(3,
358c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
368c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d1"),
378c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "spi0",    "cs0n")),
388c2ecf20Sopenharmony_ci	MPP_MODE(4,
398c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
408c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d2"),
418c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "i2c0",    "sda")),
428c2ecf20Sopenharmony_ci	MPP_MODE(5,
438c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
448c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d3"),
458c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "i2c0",    "sdk")),
468c2ecf20Sopenharmony_ci	MPP_MODE(6,
478c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
488c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "ds")),
498c2ecf20Sopenharmony_ci	MPP_MODE(7,
508c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
518c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d4"),
528c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "uart1",   "rxd")),
538c2ecf20Sopenharmony_ci	MPP_MODE(8,
548c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
558c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d5"),
568c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "uart1",   "txd")),
578c2ecf20Sopenharmony_ci	MPP_MODE(9,
588c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
598c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d6"),
608c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "spi0",    "cs1n")),
618c2ecf20Sopenharmony_ci	MPP_MODE(10,
628c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
638c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "d7")),
648c2ecf20Sopenharmony_ci	MPP_MODE(11,
658c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
668c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "uart0",   "txd")),
678c2ecf20Sopenharmony_ci	MPP_MODE(12,
688c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
698c2ecf20Sopenharmony_ci		 MPP_FUNCTION(1, "sdio",    "pw_off"),
708c2ecf20Sopenharmony_ci		 MPP_FUNCTION(2, "sdio",    "hw_rst")),
718c2ecf20Sopenharmony_ci	MPP_MODE(13,
728c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL)),
738c2ecf20Sopenharmony_ci	MPP_MODE(14,
748c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL)),
758c2ecf20Sopenharmony_ci	MPP_MODE(15,
768c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL)),
778c2ecf20Sopenharmony_ci	MPP_MODE(16,
788c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL)),
798c2ecf20Sopenharmony_ci	MPP_MODE(17,
808c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL)),
818c2ecf20Sopenharmony_ci	MPP_MODE(18,
828c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL)),
838c2ecf20Sopenharmony_ci	MPP_MODE(19,
848c2ecf20Sopenharmony_ci		 MPP_FUNCTION(0, "gpio",    NULL),
858c2ecf20Sopenharmony_ci		 MPP_FUNCTION(3, "uart0",   "rxd"),
868c2ecf20Sopenharmony_ci		 MPP_FUNCTION(4, "sdio",    "pw_off")),
878c2ecf20Sopenharmony_ci};
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic struct mvebu_pinctrl_soc_info armada_ap806_pinctrl_info;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic const struct of_device_id armada_ap806_pinctrl_of_match[] = {
928c2ecf20Sopenharmony_ci	{
938c2ecf20Sopenharmony_ci		.compatible = "marvell,ap806-pinctrl",
948c2ecf20Sopenharmony_ci	},
958c2ecf20Sopenharmony_ci	{ },
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic const struct mvebu_mpp_ctrl armada_ap806_mpp_controls[] = {
998c2ecf20Sopenharmony_ci	MPP_FUNC_CTRL(0, 19, NULL, mvebu_regmap_mpp_ctrl),
1008c2ecf20Sopenharmony_ci};
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic struct pinctrl_gpio_range armada_ap806_mpp_gpio_ranges[] = {
1038c2ecf20Sopenharmony_ci	MPP_GPIO_RANGE(0,   0,  0, 20),
1048c2ecf20Sopenharmony_ci};
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic int armada_ap806_pinctrl_probe(struct platform_device *pdev)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	struct mvebu_pinctrl_soc_info *soc = &armada_ap806_pinctrl_info;
1098c2ecf20Sopenharmony_ci	const struct of_device_id *match =
1108c2ecf20Sopenharmony_ci		of_match_device(armada_ap806_pinctrl_of_match, &pdev->dev);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	if (!match || !pdev->dev.parent)
1138c2ecf20Sopenharmony_ci		return -ENODEV;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	soc->variant = 0; /* no variants for Armada AP806 */
1168c2ecf20Sopenharmony_ci	soc->controls = armada_ap806_mpp_controls;
1178c2ecf20Sopenharmony_ci	soc->ncontrols = ARRAY_SIZE(armada_ap806_mpp_controls);
1188c2ecf20Sopenharmony_ci	soc->gpioranges = armada_ap806_mpp_gpio_ranges;
1198c2ecf20Sopenharmony_ci	soc->ngpioranges = ARRAY_SIZE(armada_ap806_mpp_gpio_ranges);
1208c2ecf20Sopenharmony_ci	soc->modes = armada_ap806_mpp_modes;
1218c2ecf20Sopenharmony_ci	soc->nmodes = armada_ap806_mpp_controls[0].npins;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	pdev->dev.platform_data = soc;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	return mvebu_pinctrl_simple_regmap_probe(pdev, pdev->dev.parent, 0);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic struct platform_driver armada_ap806_pinctrl_driver = {
1298c2ecf20Sopenharmony_ci	.driver = {
1308c2ecf20Sopenharmony_ci		.name = "armada-ap806-pinctrl",
1318c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(armada_ap806_pinctrl_of_match),
1328c2ecf20Sopenharmony_ci	},
1338c2ecf20Sopenharmony_ci	.probe = armada_ap806_pinctrl_probe,
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cibuiltin_platform_driver(armada_ap806_pinctrl_driver);
137