110 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Nuvoton WPCM450 SoC Identification4 *5 * Copyright (C) 2022 Jonathan Neuschäfer6 */7 8#include <linux/mfd/syscon.h>9#include <linux/of.h>10#include <linux/regmap.h>11#include <linux/slab.h>12#include <linux/sys_soc.h>13 14#define GCR_PDID 015#define PDID_CHIP(x) ((x) & 0x00ffffff)16#define CHIP_WPCM450 0x92645017#define PDID_REV(x) ((x) >> 24)18 19struct revision {20 u8 number;21 const char *name;22};23 24static const struct revision revisions[] __initconst = {25 { 0x00, "Z1" },26 { 0x03, "Z2" },27 { 0x04, "Z21" },28 { 0x08, "A1" },29 { 0x09, "A2" },30 { 0x0a, "A3" },31 {}32};33 34static const char * __init get_revision(unsigned int rev)35{36 int i;37 38 for (i = 0; revisions[i].name; i++)39 if (revisions[i].number == rev)40 return revisions[i].name;41 return NULL;42}43 44static struct soc_device_attribute *wpcm450_attr;45static struct soc_device *wpcm450_soc;46 47static int __init wpcm450_soc_init(void)48{49 struct soc_device_attribute *attr;50 struct soc_device *soc;51 const char *revision;52 struct regmap *gcr;53 u32 pdid;54 int ret;55 56 if (!of_machine_is_compatible("nuvoton,wpcm450"))57 return 0;58 59 gcr = syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr");60 if (IS_ERR(gcr))61 return PTR_ERR(gcr);62 ret = regmap_read(gcr, GCR_PDID, &pdid);63 if (ret)64 return ret;65 66 if (PDID_CHIP(pdid) != CHIP_WPCM450) {67 pr_warn("Unknown chip ID in GCR.PDID: 0x%06x\n", PDID_CHIP(pdid));68 return -ENODEV;69 }70 71 revision = get_revision(PDID_REV(pdid));72 if (!revision) {73 pr_warn("Unknown chip revision in GCR.PDID: 0x%02x\n", PDID_REV(pdid));74 return -ENODEV;75 }76 77 attr = kzalloc(sizeof(*attr), GFP_KERNEL);78 if (!attr)79 return -ENOMEM;80 81 attr->family = "Nuvoton NPCM";82 attr->soc_id = "WPCM450";83 attr->revision = revision;84 soc = soc_device_register(attr);85 if (IS_ERR(soc)) {86 kfree(attr);87 pr_warn("Could not register SoC device\n");88 return PTR_ERR(soc);89 }90 91 wpcm450_soc = soc;92 wpcm450_attr = attr;93 return 0;94}95module_init(wpcm450_soc_init);96 97static void __exit wpcm450_soc_exit(void)98{99 if (wpcm450_soc) {100 soc_device_unregister(wpcm450_soc);101 wpcm450_soc = NULL;102 kfree(wpcm450_attr);103 }104}105module_exit(wpcm450_soc_exit);106 107MODULE_LICENSE("GPL");108MODULE_AUTHOR("Jonathan Neuschäfer");109MODULE_DESCRIPTION("Nuvoton WPCM450 SoC Identification driver");110