Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+154 -99
+61
Documentation/devicetree/bindings/nvmem/google,gs101-otp.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/nvmem/google,gs101-otp.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Google GS101 OTP Controller 8 + 9 + maintainers: 10 + - Tudor Ambarus <tudor.ambarus@linaro.org> 11 + 12 + description: | 13 + OTP controller drives a NVMEM memory where system or user specific data 14 + can be stored. The OTP controller register space is of interest as well 15 + because it contains dedicated registers where it stores the Product ID 16 + and the Chip ID (apart other things like TMU or ASV info). 17 + 18 + allOf: 19 + - $ref: nvmem.yaml# 20 + 21 + properties: 22 + compatible: 23 + items: 24 + - const: google,gs101-otp 25 + 26 + clocks: 27 + maxItems: 1 28 + 29 + clock-names: 30 + const: pclk 31 + 32 + interrupts: 33 + maxItems: 1 34 + 35 + reg: 36 + maxItems: 1 37 + 38 + power-domains: 39 + maxItems: 1 40 + 41 + required: 42 + - compatible 43 + - reg 44 + - clocks 45 + - clock-names 46 + - interrupts 47 + 48 + unevaluatedProperties: false 49 + 50 + examples: 51 + - | 52 + #include <dt-bindings/clock/google,gs101.h> 53 + #include <dt-bindings/interrupt-controller/arm-gic.h> 54 + 55 + efuse@10000000 { 56 + compatible = "google,gs101-otp"; 57 + reg = <0x10000000 0xf084>; 58 + clocks = <&cmu_misc CLK_GOUT_MISC_OTP_CON_TOP_PCLK>; 59 + clock-names = "pclk"; 60 + interrupts = <GIC_SPI 752 IRQ_TYPE_LEVEL_HIGH>; 61 + };
+1 -22
Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
··· 9 9 maintainers: 10 10 - Krzysztof Kozlowski <krzk@kernel.org> 11 11 12 - # Custom select to avoid matching all nodes with 'syscon' 13 - select: 14 - properties: 15 - compatible: 16 - contains: 17 - enum: 18 - - google,gs101-pmu 19 - - samsung,exynos3250-pmu 20 - - samsung,exynos4210-pmu 21 - - samsung,exynos4212-pmu 22 - - samsung,exynos4412-pmu 23 - - samsung,exynos5250-pmu 24 - - samsung,exynos5260-pmu 25 - - samsung,exynos5410-pmu 26 - - samsung,exynos5420-pmu 27 - - samsung,exynos5433-pmu 28 - - samsung,exynos7-pmu 29 - - samsung,exynos850-pmu 30 - - samsung-s5pv210-pmu 31 - required: 32 - - compatible 33 - 34 12 properties: 35 13 compatible: 36 14 oneOf: ··· 30 52 - const: syscon 31 53 - items: 32 54 - enum: 55 + - axis,artpec9-pmu 33 56 - samsung,exynos2200-pmu 34 57 - samsung,exynos7870-pmu 35 58 - samsung,exynos7885-pmu
+92 -41
drivers/soc/samsung/exynos-chipid.c
··· 14 14 15 15 #include <linux/array_size.h> 16 16 #include <linux/device.h> 17 - #include <linux/errno.h> 17 + #include <linux/device/devres.h> 18 + #include <linux/err.h> 19 + #include <linux/ioport.h> 18 20 #include <linux/mfd/syscon.h> 19 21 #include <linux/module.h> 20 22 #include <linux/of.h> ··· 29 27 #include "exynos-asv.h" 30 28 31 29 struct exynos_chipid_variant { 32 - unsigned int rev_reg; /* revision register offset */ 30 + unsigned int main_rev_reg; /* main revision register offset */ 31 + unsigned int sub_rev_reg; /* sub revision register offset */ 33 32 unsigned int main_rev_shift; /* main revision offset in rev_reg */ 34 33 unsigned int sub_rev_shift; /* sub revision offset in rev_reg */ 34 + bool efuse; 35 35 }; 36 36 37 37 struct exynos_chipid_info { ··· 72 68 { "EXYNOS990", 0xE9830000 }, 73 69 { "EXYNOSAUTOV9", 0xAAA80000 }, 74 70 { "EXYNOSAUTOV920", 0x0A920000 }, 71 + /* Compatible with: google,gs101-otp */ 72 + { "GS101", 0x9845000 }, 75 73 }; 76 74 77 - static const char *product_id_to_soc_id(unsigned int product_id) 75 + static const char *exynos_product_id_to_name(unsigned int product_id) 78 76 { 79 77 int i; 80 78 ··· 86 80 return NULL; 87 81 } 88 82 89 - static int exynos_chipid_get_chipid_info(struct regmap *regmap, 90 - const struct exynos_chipid_variant *data, 83 + static int exynos_chipid_get_chipid_info(struct device *dev, 84 + struct regmap *regmap, const struct exynos_chipid_variant *data, 91 85 struct exynos_chipid_info *soc_info) 92 86 { 93 87 int ret; ··· 95 89 96 90 ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &val); 97 91 if (ret < 0) 98 - return ret; 92 + return dev_err_probe(dev, ret, "failed to read Product ID\n"); 99 93 soc_info->product_id = val & EXYNOS_MASK; 100 94 101 - if (data->rev_reg != EXYNOS_CHIPID_REG_PRO_ID) { 102 - ret = regmap_read(regmap, data->rev_reg, &val); 95 + if (data->sub_rev_reg == EXYNOS_CHIPID_REG_PRO_ID) { 96 + /* exynos4210 case */ 97 + main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK; 98 + sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK; 99 + } else { 100 + unsigned int val2; 101 + 102 + ret = regmap_read(regmap, data->sub_rev_reg, &val2); 103 103 if (ret < 0) 104 - return ret; 104 + return dev_err_probe(dev, ret, 105 + "failed to read revision\n"); 106 + 107 + if (data->main_rev_reg == EXYNOS_CHIPID_REG_PRO_ID) 108 + /* gs101 case */ 109 + main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK; 110 + else 111 + /* exynos850 case */ 112 + main_rev = (val2 >> data->main_rev_shift) & EXYNOS_REV_PART_MASK; 113 + 114 + sub_rev = (val2 >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK; 105 115 } 106 - main_rev = (val >> data->main_rev_shift) & EXYNOS_REV_PART_MASK; 107 - sub_rev = (val >> data->sub_rev_shift) & EXYNOS_REV_PART_MASK; 116 + 108 117 soc_info->revision = (main_rev << EXYNOS_REV_PART_SHIFT) | sub_rev; 109 118 110 119 return 0; 120 + } 121 + 122 + static struct regmap *exynos_chipid_get_efuse_regmap(struct platform_device *pdev) 123 + { 124 + struct resource *res; 125 + void __iomem *base; 126 + 127 + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 128 + if (IS_ERR(base)) 129 + return ERR_CAST(base); 130 + 131 + const struct regmap_config reg_config = { 132 + .reg_bits = 32, 133 + .reg_stride = 4, 134 + .val_bits = 32, 135 + .use_relaxed_mmio = true, 136 + .max_register = (resource_size(res) - reg_config.reg_stride), 137 + }; 138 + 139 + return devm_regmap_init_mmio_clk(&pdev->dev, "pclk", base, &reg_config); 140 + } 141 + 142 + static void exynos_chipid_unregister_soc(void *data) 143 + { 144 + soc_device_unregister(data); 111 145 } 112 146 113 147 static int exynos_chipid_probe(struct platform_device *pdev) ··· 163 117 164 118 drv_data = of_device_get_match_data(dev); 165 119 if (!drv_data) 166 - return -EINVAL; 120 + return dev_err_probe(dev, -EINVAL, 121 + "failed to get match data\n"); 167 122 168 - regmap = device_node_to_regmap(dev->of_node); 123 + if (drv_data->efuse) 124 + regmap = exynos_chipid_get_efuse_regmap(pdev); 125 + else 126 + regmap = device_node_to_regmap(dev->of_node); 127 + 169 128 if (IS_ERR(regmap)) 170 - return PTR_ERR(regmap); 129 + return dev_err_probe(dev, PTR_ERR(regmap), 130 + "failed to get regmap\n"); 171 131 172 - ret = exynos_chipid_get_chipid_info(regmap, drv_data, &soc_info); 132 + ret = exynos_chipid_get_chipid_info(dev, regmap, drv_data, &soc_info); 173 133 if (ret < 0) 174 134 return ret; 175 135 ··· 193 141 soc_info.revision); 194 142 if (!soc_dev_attr->revision) 195 143 return -ENOMEM; 196 - soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id); 197 - if (!soc_dev_attr->soc_id) { 198 - pr_err("Unknown SoC\n"); 199 - return -ENODEV; 200 - } 144 + 145 + soc_dev_attr->soc_id = exynos_product_id_to_name(soc_info.product_id); 146 + if (!soc_dev_attr->soc_id) 147 + return dev_err_probe(dev, -ENODEV, "Unknown SoC\n"); 201 148 202 149 /* please note that the actual registration will be deferred */ 203 150 soc_dev = soc_device_register(soc_dev_attr); 204 151 if (IS_ERR(soc_dev)) 205 - return PTR_ERR(soc_dev); 152 + return dev_err_probe(dev, PTR_ERR(soc_dev), 153 + "failed to register to the soc interface\n"); 154 + 155 + ret = devm_add_action_or_reset(dev, exynos_chipid_unregister_soc, 156 + soc_dev); 157 + if (ret) 158 + return dev_err_probe(dev, ret, "failed to add devm action\n"); 206 159 207 160 ret = exynos_asv_init(dev, regmap); 208 161 if (ret) 209 - goto err; 162 + return ret; 210 163 211 - platform_set_drvdata(pdev, soc_dev); 212 - 213 - dev_info(dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", 214 - soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision); 164 + dev_dbg(dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", 165 + soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision); 215 166 216 167 return 0; 217 - 218 - err: 219 - soc_device_unregister(soc_dev); 220 - 221 - return ret; 222 - } 223 - 224 - static void exynos_chipid_remove(struct platform_device *pdev) 225 - { 226 - struct soc_device *soc_dev = platform_get_drvdata(pdev); 227 - 228 - soc_device_unregister(soc_dev); 229 168 } 230 169 231 170 static const struct exynos_chipid_variant exynos4210_chipid_drv_data = { 232 - .rev_reg = 0x0, 233 171 .main_rev_shift = 4, 234 172 .sub_rev_shift = 0, 235 173 }; 236 174 237 175 static const struct exynos_chipid_variant exynos850_chipid_drv_data = { 238 - .rev_reg = 0x10, 176 + .main_rev_reg = 0x10, 177 + .sub_rev_reg = 0x10, 239 178 .main_rev_shift = 20, 240 179 .sub_rev_shift = 16, 241 180 }; 242 181 182 + static const struct exynos_chipid_variant gs101_chipid_drv_data = { 183 + .sub_rev_reg = 0x10, 184 + .sub_rev_shift = 16, 185 + .efuse = true, 186 + }; 187 + 243 188 static const struct of_device_id exynos_chipid_of_device_ids[] = { 244 189 { 190 + .compatible = "google,gs101-otp", 191 + .data = &gs101_chipid_drv_data, 192 + }, { 245 193 .compatible = "samsung,exynos4210-chipid", 246 194 .data = &exynos4210_chipid_drv_data, 247 195 }, { ··· 258 206 .of_match_table = exynos_chipid_of_device_ids, 259 207 }, 260 208 .probe = exynos_chipid_probe, 261 - .remove = exynos_chipid_remove, 262 209 }; 263 210 module_platform_driver(exynos_chipid_driver); 264 211
-36
include/linux/platform_data/hwmon-s3c.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * Copyright 2005 Simtec Electronics 4 - * Ben Dooks <ben@simtec.co.uk> 5 - * http://armlinux.simtec.co.uk/ 6 - * 7 - * S3C - HWMon interface for ADC 8 - */ 9 - 10 - #ifndef __HWMON_S3C_H__ 11 - #define __HWMON_S3C_H__ 12 - 13 - /** 14 - * s3c_hwmon_chcfg - channel configuration 15 - * @name: The name to give this channel. 16 - * @mult: Multiply the ADC value read by this. 17 - * @div: Divide the value from the ADC by this. 18 - * 19 - * The value read from the ADC is converted to a value that 20 - * hwmon expects (mV) by result = (value_read * @mult) / @div. 21 - */ 22 - struct s3c_hwmon_chcfg { 23 - const char *name; 24 - unsigned int mult; 25 - unsigned int div; 26 - }; 27 - 28 - /** 29 - * s3c_hwmon_pdata - HWMON platform data 30 - * @in: One configuration for each possible channel used. 31 - */ 32 - struct s3c_hwmon_pdata { 33 - struct s3c_hwmon_chcfg *in[8]; 34 - }; 35 - 36 - #endif /* __HWMON_S3C_H__ */