1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * SoC driver for Cirrus EP93xx chips. 4 * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me> 5 * 6 * Based on a rewrite of arch/arm/mach-ep93xx/core.c 7 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 8 * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> 9 * 10 * Thanks go to Michael Burian and Ray Lehtiniemi for their key 11 * role in the ep93xx Linux community. 12 */ 13 14 #include <linux/bits.h> 15 #include <linux/cleanup.h> 16 #include <linux/init.h> 17 #include <linux/mfd/syscon.h> 18 #include <linux/of.h> 19 #include <linux/of_fdt.h> 20 #include <linux/platform_device.h> 21 #include <linux/regmap.h> 22 #include <linux/slab.h> 23 #include <linux/spinlock.h> 24 #include <linux/sys_soc.h> 25 26 #include <linux/soc/cirrus/ep93xx.h> 27 28 #define EP93XX_SYSCON_DEVCFG 0x80 29 30 #define EP93XX_SWLOCK_MAGICK 0xaa 31 #define EP93XX_SYSCON_SWLOCK 0xc0 32 #define EP93XX_SYSCON_SYSCFG 0x9c 33 #define EP93XX_SYSCON_SYSCFG_REV_MASK GENMASK(31, 28) 34 #define EP93XX_SYSCON_SYSCFG_REV_SHIFT 28 35 36 struct ep93xx_map_info { 37 spinlock_t lock; 38 void __iomem *base; 39 struct regmap *map; 40 }; 41 42 /* 43 * EP93xx System Controller software locked register write 44 * 45 * Logic safeguards are included to condition the control signals for 46 * power connection to the matrix to prevent part damage. In addition, a 47 * software lock register is included that must be written with 0xAA 48 * before each register write to change the values of the four switch 49 * matrix control registers. 50 */ 51 static void ep93xx_regmap_write(struct regmap *map, spinlock_t *lock, 52 unsigned int reg, unsigned int val) 53 { 54 guard(spinlock_irqsave)(lock); 55 56 regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK); 57 regmap_write(map, reg, val); 58 } 59 60 static void ep93xx_regmap_update_bits(struct regmap *map, spinlock_t *lock, 61 unsigned int reg, unsigned int mask, 62 unsigned int val) 63 { 64 guard(spinlock_irqsave)(lock); 65 66 regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK); 67 /* force write is required to clear swlock if no changes are made */ 68 regmap_update_bits_base(map, reg, mask, val, NULL, false, true); 69 } 70 71 static void ep93xx_unregister_adev(void *_adev) 72 { 73 struct auxiliary_device *adev = _adev; 74 75 auxiliary_device_delete(adev); 76 auxiliary_device_uninit(adev); 77 } 78 79 static void ep93xx_adev_release(struct device *dev) 80 { 81 struct auxiliary_device *adev = to_auxiliary_dev(dev); 82 struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev); 83 84 kfree(rdev); 85 } 86 87 static struct auxiliary_device __init *ep93xx_adev_alloc(struct device *parent, 88 const char *name, 89 struct ep93xx_map_info *info) 90 { 91 struct ep93xx_regmap_adev *rdev __free(kfree) = NULL; 92 struct auxiliary_device *adev; 93 int ret; 94 95 rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 96 if (!rdev) 97 return ERR_PTR(-ENOMEM); 98 99 rdev->map = info->map; 100 rdev->base = info->base; 101 rdev->lock = &info->lock; 102 rdev->write = ep93xx_regmap_write; 103 rdev->update_bits = ep93xx_regmap_update_bits; 104 105 adev = &rdev->adev; 106 adev->name = name; 107 adev->dev.parent = parent; 108 adev->dev.release = ep93xx_adev_release; 109 110 ret = auxiliary_device_init(adev); 111 if (ret) 112 return ERR_PTR(ret); 113 114 return &no_free_ptr(rdev)->adev; 115 } 116 117 static int __init ep93xx_controller_register(struct device *parent, const char *name, 118 struct ep93xx_map_info *info) 119 { 120 struct auxiliary_device *adev; 121 int ret; 122 123 adev = ep93xx_adev_alloc(parent, name, info); 124 if (IS_ERR(adev)) 125 return PTR_ERR(adev); 126 127 ret = auxiliary_device_add(adev); 128 if (ret) { 129 auxiliary_device_uninit(adev); 130 return ret; 131 } 132 133 return devm_add_action_or_reset(parent, ep93xx_unregister_adev, adev); 134 } 135 136 static unsigned int __init ep93xx_soc_revision(struct regmap *map) 137 { 138 unsigned int val; 139 140 regmap_read(map, EP93XX_SYSCON_SYSCFG, &val); 141 val &= EP93XX_SYSCON_SYSCFG_REV_MASK; 142 val >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; 143 return val; 144 } 145 146 static const char __init *ep93xx_get_soc_rev(unsigned int rev) 147 { 148 switch (rev) { 149 case EP93XX_CHIP_REV_D0: 150 return "D0"; 151 case EP93XX_CHIP_REV_D1: 152 return "D1"; 153 case EP93XX_CHIP_REV_E0: 154 return "E0"; 155 case EP93XX_CHIP_REV_E1: 156 return "E1"; 157 case EP93XX_CHIP_REV_E2: 158 return "E2"; 159 default: 160 return "unknown"; 161 } 162 } 163 164 static const char *pinctrl_names[] __initconst = { 165 "pinctrl-ep9301", /* EP93XX_9301_SOC */ 166 "pinctrl-ep9307", /* EP93XX_9307_SOC */ 167 "pinctrl-ep9312", /* EP93XX_9312_SOC */ 168 }; 169 170 static int __init ep93xx_syscon_probe(struct platform_device *pdev) 171 { 172 enum ep93xx_soc_model model; 173 struct ep93xx_map_info *map_info; 174 struct soc_device_attribute *attrs; 175 struct soc_device *soc_dev; 176 struct device *dev = &pdev->dev; 177 struct regmap *map; 178 void __iomem *base; 179 unsigned int rev; 180 int ret; 181 182 model = (enum ep93xx_soc_model)(uintptr_t)device_get_match_data(dev); 183 184 map = device_node_to_regmap(dev->of_node); 185 if (IS_ERR(map)) 186 return PTR_ERR(map); 187 188 base = devm_platform_ioremap_resource(pdev, 0); 189 if (IS_ERR(base)) 190 return PTR_ERR(base); 191 192 attrs = devm_kzalloc(dev, sizeof(*attrs), GFP_KERNEL); 193 if (!attrs) 194 return -ENOMEM; 195 196 rev = ep93xx_soc_revision(map); 197 198 attrs->machine = of_flat_dt_get_machine_name(); 199 attrs->family = "Cirrus Logic EP93xx"; 200 attrs->revision = ep93xx_get_soc_rev(rev); 201 202 soc_dev = soc_device_register(attrs); 203 if (IS_ERR(soc_dev)) 204 return PTR_ERR(soc_dev); 205 206 map_info = devm_kzalloc(dev, sizeof(*map_info), GFP_KERNEL); 207 if (!map_info) 208 return -ENOMEM; 209 210 spin_lock_init(&map_info->lock); 211 map_info->map = map; 212 map_info->base = base; 213 214 ret = ep93xx_controller_register(dev, pinctrl_names[model], map_info); 215 if (ret) 216 dev_err(dev, "registering pinctrl controller failed\n"); 217 218 /* 219 * EP93xx SSP clock rate was doubled in version E2. For more information 220 * see section 6 "2x SSP (Synchronous Serial Port) Clock – Revision E2 only": 221 * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf 222 */ 223 if (rev == EP93XX_CHIP_REV_E2) 224 ret = ep93xx_controller_register(dev, "clk-ep93xx.e2", map_info); 225 else 226 ret = ep93xx_controller_register(dev, "clk-ep93xx", map_info); 227 if (ret) 228 dev_err(dev, "registering clock controller failed\n"); 229 230 ret = ep93xx_controller_register(dev, "reset-ep93xx", map_info); 231 if (ret) 232 dev_err(dev, "registering reset controller failed\n"); 233 234 return 0; 235 } 236 237 static const struct of_device_id ep9301_syscon_of_device_ids[] = { 238 { .compatible = "cirrus,ep9301-syscon", .data = (void *)EP93XX_9301_SOC }, 239 { .compatible = "cirrus,ep9302-syscon", .data = (void *)EP93XX_9301_SOC }, 240 { .compatible = "cirrus,ep9307-syscon", .data = (void *)EP93XX_9307_SOC }, 241 { .compatible = "cirrus,ep9312-syscon", .data = (void *)EP93XX_9312_SOC }, 242 { .compatible = "cirrus,ep9315-syscon", .data = (void *)EP93XX_9312_SOC }, 243 { /* sentinel */ } 244 }; 245 246 static struct platform_driver ep9301_syscon_driver = { 247 .driver = { 248 .name = "ep9301-syscon", 249 .of_match_table = ep9301_syscon_of_device_ids, 250 }, 251 }; 252 builtin_platform_driver_probe(ep9301_syscon_driver, ep93xx_syscon_probe); 253