Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Olof Johansson: "Some of the larger changes this merge window: - Removal of drivers for Exynos5440, a Samsung SoC that never saw widespread use. - Uniphier support for USB3 and SPI reset handling - Syste control and SRAM drivers and bindings for Allwinner platforms - Qualcomm AOSS (Always-on subsystem) reset controller drivers - Raspberry Pi hwmon driver for voltage - Mediatek pwrap (pmic) support for MT6797 SoC" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (52 commits) drivers/firmware: psci_checker: stash and use topology_core_cpumask for hotplug tests soc: fsl: cleanup Kconfig menu soc: fsl: dpio: Convert DPIO documentation to .rst staging: fsl-mc: Remove remaining files staging: fsl-mc: Move DPIO from staging to drivers/soc/fsl staging: fsl-dpaa2: eth: move generic FD defines to DPIO soc: fsl: qe: gpio: Add qe_gpio_set_multiple usb: host: exynos: Remove support for Exynos5440 clk: samsung: Remove support for Exynos5440 soc: sunxi: Add the A13, A23 and H3 system control compatibles reset: uniphier: add reset control support for SPI cpufreq: exynos: Remove support for Exynos5440 ata: ahci-platform: Remove support for Exynos5440 soc: imx6qp: Use GENPD_FLAG_ALWAYS_ON for PU errata soc: mediatek: pwrap: add mt6351 driver for mt6797 SoCs soc: mediatek: pwrap: add pwrap driver for mt6797 SoCs soc: mediatek: pwrap: fix cipher init setting error dt-bindings: pwrap: mediatek: add pwrap support for MT6797 reset: uniphier: add USB3 core reset control dt-bindings: reset: uniphier: add USB3 core reset support ...
This commit is contained in:
@@ -82,6 +82,15 @@ config RESET_PISTACHIO
|
||||
help
|
||||
This enables the reset driver for ImgTec Pistachio SoCs.
|
||||
|
||||
config RESET_QCOM_AOSS
|
||||
bool "Qcom AOSS Reset Driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
help
|
||||
This enables the AOSS (always on subsystem) reset driver
|
||||
for Qualcomm SDM845 SoCs. Say Y if you want to control
|
||||
reset signals provided by AOSS for Modem, Venus, ADSP,
|
||||
GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
|
||||
|
||||
config RESET_SIMPLE
|
||||
bool "Simple Reset Controller Driver" if COMPILE_TEST
|
||||
default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
|
||||
@@ -138,6 +147,16 @@ config RESET_UNIPHIER
|
||||
Say Y if you want to control reset signals provided by System Control
|
||||
block, Media I/O block, Peripheral Block.
|
||||
|
||||
config RESET_UNIPHIER_USB3
|
||||
tristate "USB3 reset driver for UniPhier SoCs"
|
||||
depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
|
||||
default ARCH_UNIPHIER
|
||||
select RESET_SIMPLE
|
||||
help
|
||||
Support for the USB3 core reset on UniPhier SoCs.
|
||||
Say Y if you want to control reset signals provided by
|
||||
USB3 glue layer.
|
||||
|
||||
config RESET_ZYNQ
|
||||
bool "ZYNQ Reset Driver" if COMPILE_TEST
|
||||
default ARCH_ZYNQ
|
||||
|
@@ -14,11 +14,13 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
|
||||
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
|
||||
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
|
||||
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
|
||||
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
|
||||
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
|
||||
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
|
||||
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
|
||||
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
|
||||
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
|
||||
|
||||
|
133
drivers/reset/reset-qcom-aoss.c
Normal file
133
drivers/reset/reset-qcom-aoss.c
Normal file
@@ -0,0 +1,133 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <dt-bindings/reset/qcom,sdm845-aoss.h>
|
||||
|
||||
struct qcom_aoss_reset_map {
|
||||
unsigned int reg;
|
||||
};
|
||||
|
||||
struct qcom_aoss_desc {
|
||||
const struct qcom_aoss_reset_map *resets;
|
||||
size_t num_resets;
|
||||
};
|
||||
|
||||
struct qcom_aoss_reset_data {
|
||||
struct reset_controller_dev rcdev;
|
||||
void __iomem *base;
|
||||
const struct qcom_aoss_desc *desc;
|
||||
};
|
||||
|
||||
static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
|
||||
[AOSS_CC_MSS_RESTART] = {0x10000},
|
||||
[AOSS_CC_CAMSS_RESTART] = {0x11000},
|
||||
[AOSS_CC_VENUS_RESTART] = {0x12000},
|
||||
[AOSS_CC_GPU_RESTART] = {0x13000},
|
||||
[AOSS_CC_DISPSS_RESTART] = {0x14000},
|
||||
[AOSS_CC_WCSS_RESTART] = {0x20000},
|
||||
[AOSS_CC_LPASS_RESTART] = {0x30000},
|
||||
};
|
||||
|
||||
static const struct qcom_aoss_desc sdm845_aoss_desc = {
|
||||
.resets = sdm845_aoss_resets,
|
||||
.num_resets = ARRAY_SIZE(sdm845_aoss_resets),
|
||||
};
|
||||
|
||||
static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
|
||||
struct reset_controller_dev *rcdev)
|
||||
{
|
||||
return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
|
||||
}
|
||||
|
||||
static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long idx)
|
||||
{
|
||||
struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
|
||||
const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
|
||||
|
||||
writel(1, data->base + map->reg);
|
||||
/* Wait 6 32kHz sleep cycles for reset */
|
||||
usleep_range(200, 300);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long idx)
|
||||
{
|
||||
struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
|
||||
const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
|
||||
|
||||
writel(0, data->base + map->reg);
|
||||
/* Wait 6 32kHz sleep cycles for reset */
|
||||
usleep_range(200, 300);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long idx)
|
||||
{
|
||||
qcom_aoss_control_assert(rcdev, idx);
|
||||
|
||||
return qcom_aoss_control_deassert(rcdev, idx);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops qcom_aoss_reset_ops = {
|
||||
.reset = qcom_aoss_control_reset,
|
||||
.assert = qcom_aoss_control_assert,
|
||||
.deassert = qcom_aoss_control_deassert,
|
||||
};
|
||||
|
||||
static int qcom_aoss_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_aoss_reset_data *data;
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct qcom_aoss_desc *desc;
|
||||
struct resource *res;
|
||||
|
||||
desc = of_device_get_match_data(dev);
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->desc = desc;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
data->rcdev.owner = THIS_MODULE;
|
||||
data->rcdev.ops = &qcom_aoss_reset_ops;
|
||||
data->rcdev.nr_resets = desc->num_resets;
|
||||
data->rcdev.of_node = dev->of_node;
|
||||
|
||||
return devm_reset_controller_register(dev, &data->rcdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_aoss_reset_of_match[] = {
|
||||
{ .compatible = "qcom,sdm845-aoss-cc", .data = &sdm845_aoss_desc },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver qcom_aoss_reset_driver = {
|
||||
.probe = qcom_aoss_reset_probe,
|
||||
.driver = {
|
||||
.name = "qcom_aoss_reset",
|
||||
.of_match_table = qcom_aoss_reset_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(qcom_aoss_reset_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@@ -87,6 +87,7 @@ const struct reset_control_ops reset_simple_ops = {
|
||||
.deassert = reset_simple_deassert,
|
||||
.status = reset_simple_status,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(reset_simple_ops);
|
||||
|
||||
/**
|
||||
* struct reset_simple_devdata - simple reset controller properties
|
||||
|
171
drivers/reset/reset-uniphier-usb3.c
Normal file
171
drivers/reset/reset-uniphier-usb3.c
Normal file
@@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
|
||||
// Copyright 2018 Socionext Inc.
|
||||
// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "reset-simple.h"
|
||||
|
||||
#define MAX_CLKS 2
|
||||
#define MAX_RSTS 2
|
||||
|
||||
struct uniphier_usb3_reset_soc_data {
|
||||
int nclks;
|
||||
const char * const *clock_names;
|
||||
int nrsts;
|
||||
const char * const *reset_names;
|
||||
};
|
||||
|
||||
struct uniphier_usb3_reset_priv {
|
||||
struct clk_bulk_data clk[MAX_CLKS];
|
||||
struct reset_control *rst[MAX_RSTS];
|
||||
struct reset_simple_data rdata;
|
||||
const struct uniphier_usb3_reset_soc_data *data;
|
||||
};
|
||||
|
||||
static int uniphier_usb3_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct uniphier_usb3_reset_priv *priv;
|
||||
struct resource *res;
|
||||
resource_size_t size;
|
||||
const char *name;
|
||||
int i, ret, nr;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
|
||||
priv->data->nrsts > MAX_RSTS))
|
||||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
size = resource_size(res);
|
||||
priv->rdata.membase = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->rdata.membase))
|
||||
return PTR_ERR(priv->rdata.membase);
|
||||
|
||||
for (i = 0; i < priv->data->nclks; i++)
|
||||
priv->clk[i].id = priv->data->clock_names[i];
|
||||
ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < priv->data->nrsts; i++) {
|
||||
name = priv->data->reset_names[i];
|
||||
priv->rst[i] = devm_reset_control_get_shared(dev, name);
|
||||
if (IS_ERR(priv->rst[i]))
|
||||
return PTR_ERR(priv->rst[i]);
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (nr = 0; nr < priv->data->nrsts; nr++) {
|
||||
ret = reset_control_deassert(priv->rst[nr]);
|
||||
if (ret)
|
||||
goto out_rst_assert;
|
||||
}
|
||||
|
||||
spin_lock_init(&priv->rdata.lock);
|
||||
priv->rdata.rcdev.owner = THIS_MODULE;
|
||||
priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
|
||||
priv->rdata.rcdev.ops = &reset_simple_ops;
|
||||
priv->rdata.rcdev.of_node = dev->of_node;
|
||||
priv->rdata.active_low = true;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
|
||||
if (ret)
|
||||
goto out_rst_assert;
|
||||
|
||||
return 0;
|
||||
|
||||
out_rst_assert:
|
||||
while (nr--)
|
||||
reset_control_assert(priv->rst[nr]);
|
||||
|
||||
clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uniphier_usb3_reset_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->data->nrsts; i++)
|
||||
reset_control_assert(priv->rst[i]);
|
||||
|
||||
clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const uniphier_pro4_clock_reset_names[] = {
|
||||
"gio", "link",
|
||||
};
|
||||
|
||||
static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
|
||||
.nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
|
||||
.clock_names = uniphier_pro4_clock_reset_names,
|
||||
.nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
|
||||
.reset_names = uniphier_pro4_clock_reset_names,
|
||||
};
|
||||
|
||||
static const char * const uniphier_pxs2_clock_reset_names[] = {
|
||||
"link",
|
||||
};
|
||||
|
||||
static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
|
||||
.nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
|
||||
.clock_names = uniphier_pxs2_clock_reset_names,
|
||||
.nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
|
||||
.reset_names = uniphier_pxs2_clock_reset_names,
|
||||
};
|
||||
|
||||
static const struct of_device_id uniphier_usb3_reset_match[] = {
|
||||
{
|
||||
.compatible = "socionext,uniphier-pro4-usb3-reset",
|
||||
.data = &uniphier_pro4_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-pxs2-usb3-reset",
|
||||
.data = &uniphier_pxs2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-ld20-usb3-reset",
|
||||
.data = &uniphier_pxs2_data,
|
||||
},
|
||||
{
|
||||
.compatible = "socionext,uniphier-pxs3-usb3-reset",
|
||||
.data = &uniphier_pxs2_data,
|
||||
},
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
|
||||
|
||||
static struct platform_driver uniphier_usb3_reset_driver = {
|
||||
.probe = uniphier_usb3_reset_probe,
|
||||
.remove = uniphier_usb3_reset_remove,
|
||||
.driver = {
|
||||
.name = "uniphier-usb3-reset",
|
||||
.of_match_table = uniphier_usb3_reset_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(uniphier_usb3_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
|
||||
MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
|
||||
MODULE_LICENSE("GPL");
|
@@ -202,6 +202,12 @@ static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
|
||||
#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
|
||||
UNIPHIER_RESETX((id), 0x114, 24 + (ch))
|
||||
|
||||
#define UNIPHIER_PERI_RESET_SCSSI(id) \
|
||||
UNIPHIER_RESETX((id), 0x110, 17)
|
||||
|
||||
#define UNIPHIER_PERI_RESET_MCSSI(id) \
|
||||
UNIPHIER_RESETX((id), 0x114, 14)
|
||||
|
||||
static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_UART(0, 0),
|
||||
UNIPHIER_PERI_RESET_UART(1, 1),
|
||||
@@ -212,6 +218,7 @@ static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_I2C(6, 2),
|
||||
UNIPHIER_PERI_RESET_I2C(7, 3),
|
||||
UNIPHIER_PERI_RESET_I2C(8, 4),
|
||||
UNIPHIER_PERI_RESET_SCSSI(11),
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
@@ -227,6 +234,8 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
|
||||
UNIPHIER_PERI_RESET_FI2C(8, 4),
|
||||
UNIPHIER_PERI_RESET_FI2C(9, 5),
|
||||
UNIPHIER_PERI_RESET_FI2C(10, 6),
|
||||
UNIPHIER_PERI_RESET_SCSSI(11),
|
||||
UNIPHIER_PERI_RESET_MCSSI(12),
|
||||
UNIPHIER_RESET_END,
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user