Samsung SoC drivers for v6.20

1. Several improvements in Exynos ChipID Socinfo driver and finally
    adding Google GS101 SoC support.
 
 2. Few cleanups from old code.
 
 3. Documenting Axis Artpec-9 SoC PMU (Power Management Unit).
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEE3dJiKD0RGyM7briowTdm5oaLg9cFAmlrzYAQHGtyemtAa2Vy
 bmVsLm9yZwAKCRDBN2bmhouD14ZAD/0X2xrfzOMX/+IMsr42MKvHMy3+YJdpRT96
 dOw/Jk2eqbL850TlYp5uxN5WPdGsPuqKvF84wtnwjM6erh9gS2yceX6eD64xaGIn
 JYB3IUOwBl2vOquoteNa01PG0mpgXzJESVBl/OmgnpT6CJWkBuPxLQaHQX3eTGSa
 VXXwwziWP+01B+DWCQEhrAoa4Ytnl/qVrGBFwHD2wY6gvxi6hMpbwKBjhHsHIAIt
 Wh8DPak9SswYz9ERZ5lGBajNIwnFLOeJiVTmnKLMINDYX2vfIEoclyhRIVykDo5D
 4uqhIaUF0ZDMfvRkml9wajHO3NRagZxczTtvLGGE5boNJSeWYJv+RFuq+ruvYNz8
 m5Xqlu27Fz5hiREwyawVzp1hJtvP80xEBCaucUoBdJB2w+R37OsXhBkaLugyE8DX
 CMobbafFiJ0af5BqAYTEGHhP4dwUn1LM8GV55ivK69psdnQMu2hftLS05PWXxqlG
 eNvJBXv94Vh6lWCVKQQbv6rrE87u91xr+WJSExYVlB/s5asSZEBLuqMDG4bKdQbw
 73kJrL4TkOMbtZIjbF7oMwG3PJeiWwH6IklFqL0p8DDAcYijLTifWnZCbeDLDgQL
 SnCiT0HXGXcJZ0BRq1SuqNwk67z+UK7/8V+a8vOHfaw44TLjqNADeW0KrhMdT3og
 73mUYCQ4MA==
 =frGu
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmlw8WkACgkQmmx57+YA
 GNmPyRAAj2d7LzXrZTvtVOdpDSQ136OPLVKmKOhrEarZEhQc20SAUs8ugJdDHTd7
 046I82GQo5gRD1D/DLPywSrb0bF6gxvhj/6tSBg05rXGf4c9IVwABEh/pymCoIDC
 L57zhnIFBDMSz6Xcbwkmz1DRNozl+Lg5+F4sXvGKF3CRL4uN0747CY/buT0t6Bl5
 fw19u15gicS/Nq8wTzI3uJiQcxNzjV+GKZbXAF2yTAomU+xBdbJzq+oe90hCHYft
 y6WNQ8HTQ79rBraCK4WciOb7lglE0SL5ZRjVIJy80tmpbOm2UksTInkEd/tzB6nP
 +ODNHyx99mMou2MwhHU1PDnVh4HT0f+6ZiYXymt7TJ+5z0r7c5dfgWQvtCZBfGXj
 nX53ftx21/5IXVvB9t498zG4r7xemhisV/0bSWtEHxqk1axS69f9n0dbSKlZmp5A
 eKqqMd0FM7FSOwgF+tF127hUv3sigL5+ez3lmxSBfH8CFR9MkuQNILJgJ5J5KeAM
 tprOxwvpToXWoTmZ/yNa+Nud60fNkHjDivHJU2xSfw1JT9siuAoQB0Cn8Kj5UJT1
 Sp/DMEUejYoP/DpjrNNCODpC6TKWn3qqlfdBmYwMuvmjHQ5AFlIxCsWkMCOJPszr
 cA2FwowwT2u7fYWRmDG55oo3RbYJGvB76j2rfyRIHdRCplqtWto=
 =FBvX
 -----END PGP SIGNATURE-----

Merge tag 'samsung-drivers-6.20' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/drivers

Samsung SoC drivers for v6.20

1. Several improvements in Exynos ChipID Socinfo driver and finally
   adding Google GS101 SoC support.

2. Few cleanups from old code.

3. Documenting Axis Artpec-9 SoC PMU (Power Management Unit).

* tag 'samsung-drivers-6.20' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
  ARM: s3c: remove a leftover hwmon-s3c.h header file
  dt-bindings: soc: samsung: exynos-pmu: Drop unnecessary select schema
  soc: samsung: exynos-chipid: add google,gs101-otp support
  soc: samsung: exynos-chipid: downgrade dev_info to dev_dbg for soc info
  soc: samsung: exynos-chipid: rename method
  dt-bindings: nvmem: add google,gs101-otp
  soc: samsung: exynos-chipid: use dev_err_probe where appropiate
  soc: samsung: exynos-chipid: use devm action to unregister soc device
  dt-bindings: samsung: exynos-pmu: Add compatible for ARTPEC-9 SoC

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2026-01-21 16:31:46 +01:00
commit ee405f1a3b
4 changed files with 154 additions and 99 deletions

View File

@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/nvmem/google,gs101-otp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Google GS101 OTP Controller
maintainers:
- Tudor Ambarus <tudor.ambarus@linaro.org>
description: |
OTP controller drives a NVMEM memory where system or user specific data
can be stored. The OTP controller register space is of interest as well
because it contains dedicated registers where it stores the Product ID
and the Chip ID (apart other things like TMU or ASV info).
allOf:
- $ref: nvmem.yaml#
properties:
compatible:
items:
- const: google,gs101-otp
clocks:
maxItems: 1
clock-names:
const: pclk
interrupts:
maxItems: 1
reg:
maxItems: 1
power-domains:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/google,gs101.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
efuse@10000000 {
compatible = "google,gs101-otp";
reg = <0x10000000 0xf084>;
clocks = <&cmu_misc CLK_GOUT_MISC_OTP_CON_TOP_PCLK>;
clock-names = "pclk";
interrupts = <GIC_SPI 752 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -9,28 +9,6 @@ title: Samsung Exynos SoC series Power Management Unit (PMU)
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
# Custom select to avoid matching all nodes with 'syscon'
select:
properties:
compatible:
contains:
enum:
- google,gs101-pmu
- samsung,exynos3250-pmu
- samsung,exynos4210-pmu
- samsung,exynos4212-pmu
- samsung,exynos4412-pmu
- samsung,exynos5250-pmu
- samsung,exynos5260-pmu
- samsung,exynos5410-pmu
- samsung,exynos5420-pmu
- samsung,exynos5433-pmu
- samsung,exynos7-pmu
- samsung,exynos850-pmu
- samsung-s5pv210-pmu
required:
- compatible
properties:
compatible:
oneOf:
@ -52,6 +30,7 @@ properties:
- const: syscon
- items:
- enum:
- axis,artpec9-pmu
- samsung,exynos2200-pmu
- samsung,exynos7870-pmu
- samsung,exynos7885-pmu

View File

@ -14,7 +14,9 @@
#include <linux/array_size.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/device/devres.h>
#include <linux/err.h>
#include <linux/ioport.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
@ -27,9 +29,11 @@
#include "exynos-asv.h"
struct exynos_chipid_variant {
unsigned int rev_reg; /* revision register offset */
unsigned int main_rev_reg; /* main revision register offset */
unsigned int sub_rev_reg; /* sub revision register offset */
unsigned int main_rev_shift; /* main revision offset in rev_reg */
unsigned int sub_rev_shift; /* sub revision offset in rev_reg */
bool efuse;
};
struct exynos_chipid_info {
@ -68,9 +72,11 @@ static const struct exynos_soc_id {
{ "EXYNOS990", 0xE9830000 },
{ "EXYNOSAUTOV9", 0xAAA80000 },
{ "EXYNOSAUTOV920", 0x0A920000 },
/* Compatible with: google,gs101-otp */
{ "GS101", 0x9845000 },
};
static const char *product_id_to_soc_id(unsigned int product_id)
static const char *exynos_product_id_to_name(unsigned int product_id)
{
int i;
@ -80,8 +86,8 @@ static const char *product_id_to_soc_id(unsigned int product_id)
return NULL;
}
static int exynos_chipid_get_chipid_info(struct regmap *regmap,
const struct exynos_chipid_variant *data,
static int exynos_chipid_get_chipid_info(struct device *dev,
struct regmap *regmap, const struct exynos_chipid_variant *data,
struct exynos_chipid_info *soc_info)
{
int ret;
@ -89,21 +95,61 @@ static int exynos_chipid_get_chipid_info(struct regmap *regmap,
ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &val);
if (ret < 0)
return ret;
return dev_err_probe(dev, ret, "failed to read Product ID\n");
soc_info->product_id = val & EXYNOS_MASK;
if (data->rev_reg != EXYNOS_CHIPID_REG_PRO_ID) {
ret = regmap_read(regmap, data->rev_reg, &val);
if (data->sub_rev_reg == EXYNOS_CHIPID_REG_PRO_ID) {
/* exynos4210 case */
main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK;
sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK;
} else {
unsigned int val2;
ret = regmap_read(regmap, data->sub_rev_reg, &val2);
if (ret < 0)
return ret;
return dev_err_probe(dev, ret,
"failed to read revision\n");
if (data->main_rev_reg == EXYNOS_CHIPID_REG_PRO_ID)
/* gs101 case */
main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK;
else
/* exynos850 case */
main_rev = (val2 >> data->main_rev_shift) & EXYNOS_REV_PART_MASK;
sub_rev = (val2 >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK;
}
main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK;
sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK;
soc_info->revision = (main_rev << EXYNOS_REV_PART_SHIFT) | sub_rev;
return 0;
}
static struct regmap *exynos_chipid_get_efuse_regmap(struct platform_device *pdev)
{
struct resource *res;
void __iomem *base;
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base))
return ERR_CAST(base);
const struct regmap_config reg_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.use_relaxed_mmio = true,
.max_register = (resource_size(res) - reg_config.reg_stride),
};
return devm_regmap_init_mmio_clk(&pdev->dev, "pclk", base, &reg_config);
}
static void exynos_chipid_unregister_soc(void *data)
{
soc_device_unregister(data);
}
static int exynos_chipid_probe(struct platform_device *pdev)
{
const struct exynos_chipid_variant *drv_data;
@ -117,13 +163,19 @@ static int exynos_chipid_probe(struct platform_device *pdev)
drv_data = of_device_get_match_data(dev);
if (!drv_data)
return -EINVAL;
return dev_err_probe(dev, -EINVAL,
"failed to get match data\n");
if (drv_data->efuse)
regmap = exynos_chipid_get_efuse_regmap(pdev);
else
regmap = device_node_to_regmap(dev->of_node);
regmap = device_node_to_regmap(dev->of_node);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return dev_err_probe(dev, PTR_ERR(regmap),
"failed to get regmap\n");
ret = exynos_chipid_get_chipid_info(regmap, drv_data, &soc_info);
ret = exynos_chipid_get_chipid_info(dev, regmap, drv_data, &soc_info);
if (ret < 0)
return ret;
@ -141,55 +193,55 @@ static int exynos_chipid_probe(struct platform_device *pdev)
soc_info.revision);
if (!soc_dev_attr->revision)
return -ENOMEM;
soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
if (!soc_dev_attr->soc_id) {
pr_err("Unknown SoC\n");
return -ENODEV;
}
soc_dev_attr->soc_id = exynos_product_id_to_name(soc_info.product_id);
if (!soc_dev_attr->soc_id)
return dev_err_probe(dev, -ENODEV, "Unknown SoC\n");
/* please note that the actual registration will be deferred */
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev))
return PTR_ERR(soc_dev);
return dev_err_probe(dev, PTR_ERR(soc_dev),
"failed to register to the soc interface\n");
ret = devm_add_action_or_reset(dev, exynos_chipid_unregister_soc,
soc_dev);
if (ret)
return dev_err_probe(dev, ret, "failed to add devm action\n");
ret = exynos_asv_init(dev, regmap);
if (ret)
goto err;
return ret;
platform_set_drvdata(pdev, soc_dev);
dev_info(dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision);
dev_dbg(dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision);
return 0;
err:
soc_device_unregister(soc_dev);
return ret;
}
static void exynos_chipid_remove(struct platform_device *pdev)
{
struct soc_device *soc_dev = platform_get_drvdata(pdev);
soc_device_unregister(soc_dev);
}
static const struct exynos_chipid_variant exynos4210_chipid_drv_data = {
.rev_reg = 0x0,
.main_rev_shift = 4,
.sub_rev_shift = 0,
};
static const struct exynos_chipid_variant exynos850_chipid_drv_data = {
.rev_reg = 0x10,
.main_rev_reg = 0x10,
.sub_rev_reg = 0x10,
.main_rev_shift = 20,
.sub_rev_shift = 16,
};
static const struct exynos_chipid_variant gs101_chipid_drv_data = {
.sub_rev_reg = 0x10,
.sub_rev_shift = 16,
.efuse = true,
};
static const struct of_device_id exynos_chipid_of_device_ids[] = {
{
.compatible = "google,gs101-otp",
.data = &gs101_chipid_drv_data,
}, {
.compatible = "samsung,exynos4210-chipid",
.data = &exynos4210_chipid_drv_data,
}, {
@ -206,7 +258,6 @@ static struct platform_driver exynos_chipid_driver = {
.of_match_table = exynos_chipid_of_device_ids,
},
.probe = exynos_chipid_probe,
.remove = exynos_chipid_remove,
};
module_platform_driver(exynos_chipid_driver);

View File

@ -1,36 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C - HWMon interface for ADC
*/
#ifndef __HWMON_S3C_H__
#define __HWMON_S3C_H__
/**
* s3c_hwmon_chcfg - channel configuration
* @name: The name to give this channel.
* @mult: Multiply the ADC value read by this.
* @div: Divide the value from the ADC by this.
*
* The value read from the ADC is converted to a value that
* hwmon expects (mV) by result = (value_read * @mult) / @div.
*/
struct s3c_hwmon_chcfg {
const char *name;
unsigned int mult;
unsigned int div;
};
/**
* s3c_hwmon_pdata - HWMON platform data
* @in: One configuration for each possible channel used.
*/
struct s3c_hwmon_pdata {
struct s3c_hwmon_chcfg *in[8];
};
#endif /* __HWMON_S3C_H__ */