1*907a2b7eSGrygorii Strashko // SPDX-License-Identifier: GPL-2.0 2*907a2b7eSGrygorii Strashko /* 3*907a2b7eSGrygorii Strashko * TI K3 SoC info driver 4*907a2b7eSGrygorii Strashko * 5*907a2b7eSGrygorii Strashko * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com 6*907a2b7eSGrygorii Strashko */ 7*907a2b7eSGrygorii Strashko 8*907a2b7eSGrygorii Strashko #include <linux/mfd/syscon.h> 9*907a2b7eSGrygorii Strashko #include <linux/of.h> 10*907a2b7eSGrygorii Strashko #include <linux/of_address.h> 11*907a2b7eSGrygorii Strashko #include <linux/regmap.h> 12*907a2b7eSGrygorii Strashko #include <linux/platform_device.h> 13*907a2b7eSGrygorii Strashko #include <linux/slab.h> 14*907a2b7eSGrygorii Strashko #include <linux/string.h> 15*907a2b7eSGrygorii Strashko #include <linux/sys_soc.h> 16*907a2b7eSGrygorii Strashko 17*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_REG 0 18*907a2b7eSGrygorii Strashko /* 19*907a2b7eSGrygorii Strashko * Bits: 20*907a2b7eSGrygorii Strashko * 31-28 VARIANT Device variant 21*907a2b7eSGrygorii Strashko * 27-12 PARTNO Part number 22*907a2b7eSGrygorii Strashko * 11-1 MFG Indicates TI as manufacturer (0x17) 23*907a2b7eSGrygorii Strashko * 1 Always 1 24*907a2b7eSGrygorii Strashko */ 25*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT (28) 26*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_VARIANT_MASK GENMASK(31, 28) 27*907a2b7eSGrygorii Strashko 28*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT (12) 29*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_PARTNO_MASK GENMASK(27, 12) 30*907a2b7eSGrygorii Strashko 31*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_MFG_SHIFT (1) 32*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_MFG_MASK GENMASK(11, 1) 33*907a2b7eSGrygorii Strashko 34*907a2b7eSGrygorii Strashko #define CTRLMMR_WKUP_JTAGID_MFG_TI 0x17 35*907a2b7eSGrygorii Strashko 36*907a2b7eSGrygorii Strashko static const struct k3_soc_id { 37*907a2b7eSGrygorii Strashko unsigned int id; 38*907a2b7eSGrygorii Strashko const char *family_name; 39*907a2b7eSGrygorii Strashko } k3_soc_ids[] = { 40*907a2b7eSGrygorii Strashko { 0xBB5A, "AM65X" }, 41*907a2b7eSGrygorii Strashko { 0xBB64, "J721E" }, 42*907a2b7eSGrygorii Strashko }; 43*907a2b7eSGrygorii Strashko 44*907a2b7eSGrygorii Strashko static int 45*907a2b7eSGrygorii Strashko k3_chipinfo_partno_to_names(unsigned int partno, 46*907a2b7eSGrygorii Strashko struct soc_device_attribute *soc_dev_attr) 47*907a2b7eSGrygorii Strashko { 48*907a2b7eSGrygorii Strashko int i; 49*907a2b7eSGrygorii Strashko 50*907a2b7eSGrygorii Strashko for (i = 0; i < ARRAY_SIZE(k3_soc_ids); i++) 51*907a2b7eSGrygorii Strashko if (partno == k3_soc_ids[i].id) { 52*907a2b7eSGrygorii Strashko soc_dev_attr->family = k3_soc_ids[i].family_name; 53*907a2b7eSGrygorii Strashko return 0; 54*907a2b7eSGrygorii Strashko } 55*907a2b7eSGrygorii Strashko 56*907a2b7eSGrygorii Strashko return -EINVAL; 57*907a2b7eSGrygorii Strashko } 58*907a2b7eSGrygorii Strashko 59*907a2b7eSGrygorii Strashko static int k3_chipinfo_probe(struct platform_device *pdev) 60*907a2b7eSGrygorii Strashko { 61*907a2b7eSGrygorii Strashko struct device_node *node = pdev->dev.of_node; 62*907a2b7eSGrygorii Strashko struct soc_device_attribute *soc_dev_attr; 63*907a2b7eSGrygorii Strashko struct device *dev = &pdev->dev; 64*907a2b7eSGrygorii Strashko struct soc_device *soc_dev; 65*907a2b7eSGrygorii Strashko struct regmap *regmap; 66*907a2b7eSGrygorii Strashko u32 partno_id; 67*907a2b7eSGrygorii Strashko u32 variant; 68*907a2b7eSGrygorii Strashko u32 jtag_id; 69*907a2b7eSGrygorii Strashko u32 mfg; 70*907a2b7eSGrygorii Strashko int ret; 71*907a2b7eSGrygorii Strashko 72*907a2b7eSGrygorii Strashko regmap = device_node_to_regmap(node); 73*907a2b7eSGrygorii Strashko if (IS_ERR(regmap)) 74*907a2b7eSGrygorii Strashko return PTR_ERR(regmap); 75*907a2b7eSGrygorii Strashko 76*907a2b7eSGrygorii Strashko ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id); 77*907a2b7eSGrygorii Strashko if (ret < 0) 78*907a2b7eSGrygorii Strashko return ret; 79*907a2b7eSGrygorii Strashko 80*907a2b7eSGrygorii Strashko mfg = (jtag_id & CTRLMMR_WKUP_JTAGID_MFG_MASK) >> 81*907a2b7eSGrygorii Strashko CTRLMMR_WKUP_JTAGID_MFG_SHIFT; 82*907a2b7eSGrygorii Strashko 83*907a2b7eSGrygorii Strashko if (mfg != CTRLMMR_WKUP_JTAGID_MFG_TI) { 84*907a2b7eSGrygorii Strashko dev_err(dev, "Invalid MFG SoC\n"); 85*907a2b7eSGrygorii Strashko return -ENODEV; 86*907a2b7eSGrygorii Strashko } 87*907a2b7eSGrygorii Strashko 88*907a2b7eSGrygorii Strashko variant = (jtag_id & CTRLMMR_WKUP_JTAGID_VARIANT_MASK) >> 89*907a2b7eSGrygorii Strashko CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT; 90*907a2b7eSGrygorii Strashko variant++; 91*907a2b7eSGrygorii Strashko 92*907a2b7eSGrygorii Strashko partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >> 93*907a2b7eSGrygorii Strashko CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT; 94*907a2b7eSGrygorii Strashko 95*907a2b7eSGrygorii Strashko soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 96*907a2b7eSGrygorii Strashko if (!soc_dev_attr) 97*907a2b7eSGrygorii Strashko return -ENOMEM; 98*907a2b7eSGrygorii Strashko 99*907a2b7eSGrygorii Strashko soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", variant); 100*907a2b7eSGrygorii Strashko if (!soc_dev_attr->revision) { 101*907a2b7eSGrygorii Strashko ret = -ENOMEM; 102*907a2b7eSGrygorii Strashko goto err; 103*907a2b7eSGrygorii Strashko } 104*907a2b7eSGrygorii Strashko 105*907a2b7eSGrygorii Strashko ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr); 106*907a2b7eSGrygorii Strashko if (ret) { 107*907a2b7eSGrygorii Strashko dev_err(dev, "Unknown SoC JTAGID[0x%08X]\n", jtag_id); 108*907a2b7eSGrygorii Strashko ret = -ENODEV; 109*907a2b7eSGrygorii Strashko goto err_free_rev; 110*907a2b7eSGrygorii Strashko } 111*907a2b7eSGrygorii Strashko 112*907a2b7eSGrygorii Strashko node = of_find_node_by_path("/"); 113*907a2b7eSGrygorii Strashko of_property_read_string(node, "model", &soc_dev_attr->machine); 114*907a2b7eSGrygorii Strashko of_node_put(node); 115*907a2b7eSGrygorii Strashko 116*907a2b7eSGrygorii Strashko soc_dev = soc_device_register(soc_dev_attr); 117*907a2b7eSGrygorii Strashko if (IS_ERR(soc_dev)) { 118*907a2b7eSGrygorii Strashko ret = PTR_ERR(soc_dev); 119*907a2b7eSGrygorii Strashko goto err_free_rev; 120*907a2b7eSGrygorii Strashko } 121*907a2b7eSGrygorii Strashko 122*907a2b7eSGrygorii Strashko dev_info(dev, "Family:%s rev:%s JTAGID[0x%08x] Detected\n", 123*907a2b7eSGrygorii Strashko soc_dev_attr->family, 124*907a2b7eSGrygorii Strashko soc_dev_attr->revision, jtag_id); 125*907a2b7eSGrygorii Strashko 126*907a2b7eSGrygorii Strashko return 0; 127*907a2b7eSGrygorii Strashko 128*907a2b7eSGrygorii Strashko err_free_rev: 129*907a2b7eSGrygorii Strashko kfree(soc_dev_attr->revision); 130*907a2b7eSGrygorii Strashko err: 131*907a2b7eSGrygorii Strashko kfree(soc_dev_attr); 132*907a2b7eSGrygorii Strashko return ret; 133*907a2b7eSGrygorii Strashko } 134*907a2b7eSGrygorii Strashko 135*907a2b7eSGrygorii Strashko static const struct of_device_id k3_chipinfo_of_match[] = { 136*907a2b7eSGrygorii Strashko { .compatible = "ti,am654-chipid", }, 137*907a2b7eSGrygorii Strashko { /* sentinel */ }, 138*907a2b7eSGrygorii Strashko }; 139*907a2b7eSGrygorii Strashko 140*907a2b7eSGrygorii Strashko static struct platform_driver k3_chipinfo_driver = { 141*907a2b7eSGrygorii Strashko .driver = { 142*907a2b7eSGrygorii Strashko .name = "k3-chipinfo", 143*907a2b7eSGrygorii Strashko .of_match_table = k3_chipinfo_of_match, 144*907a2b7eSGrygorii Strashko }, 145*907a2b7eSGrygorii Strashko .probe = k3_chipinfo_probe, 146*907a2b7eSGrygorii Strashko }; 147*907a2b7eSGrygorii Strashko 148*907a2b7eSGrygorii Strashko static int __init k3_chipinfo_init(void) 149*907a2b7eSGrygorii Strashko { 150*907a2b7eSGrygorii Strashko return platform_driver_register(&k3_chipinfo_driver); 151*907a2b7eSGrygorii Strashko } 152*907a2b7eSGrygorii Strashko subsys_initcall(k3_chipinfo_init); 153