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

soc: aspeed: lpc-snoop: Lift channel config to const structs

The shifts and masks for each channel are defined by hardware and
are not something that changes at runtime. Accordingly, describe the
information in an array of const structs and associate elements with
each channel instance, removing the need for the switch and handling of
its default case.

Link: https://patch.msgid.link/20250616-aspeed-lpc-snoop-fixes-v2-10-3cdd59c934d3@codeconstruct.com.au
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>

+45 -54
+45 -54
drivers/soc/aspeed/aspeed-lpc-snoop.c
··· 63 63 ASPEED_LPC_SNOOP_INDEX_MAX = ASPEED_LPC_SNOOP_INDEX_1, 64 64 }; 65 65 66 + struct aspeed_lpc_snoop_channel_cfg { 67 + enum aspeed_lpc_snoop_index index; 68 + u32 hicr5_en; 69 + u32 snpwadr_mask; 70 + u32 snpwadr_shift; 71 + u32 hicrb_en; 72 + }; 73 + 66 74 struct aspeed_lpc_snoop_channel { 75 + const struct aspeed_lpc_snoop_channel_cfg *cfg; 67 76 bool enabled; 68 77 struct kfifo fifo; 69 78 wait_queue_head_t wq; ··· 84 75 int irq; 85 76 struct clk *clk; 86 77 struct aspeed_lpc_snoop_channel chan[ASPEED_LPC_SNOOP_INDEX_MAX + 1]; 78 + }; 79 + 80 + static const struct aspeed_lpc_snoop_channel_cfg channel_cfgs[ASPEED_LPC_SNOOP_INDEX_MAX + 1] = { 81 + { 82 + .index = ASPEED_LPC_SNOOP_INDEX_0, 83 + .hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W, 84 + .snpwadr_mask = SNPWADR_CH0_MASK, 85 + .snpwadr_shift = SNPWADR_CH0_SHIFT, 86 + .hicrb_en = HICRB_ENSNP0D, 87 + }, 88 + { 89 + .index = ASPEED_LPC_SNOOP_INDEX_1, 90 + .hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W, 91 + .snpwadr_mask = SNPWADR_CH1_MASK, 92 + .snpwadr_shift = SNPWADR_CH1_SHIFT, 93 + .hicrb_en = HICRB_ENSNP1D, 94 + }, 87 95 }; 88 96 89 97 static struct aspeed_lpc_snoop_channel *snoop_file_to_chan(struct file *file) ··· 215 189 } 216 190 217 191 __attribute__((nonnull)) 218 - static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, 219 - struct device *dev, 220 - enum aspeed_lpc_snoop_index index, u16 lpc_port) 192 + static int aspeed_lpc_enable_snoop(struct device *dev, 193 + struct aspeed_lpc_snoop *lpc_snoop, 194 + struct aspeed_lpc_snoop_channel *channel, 195 + const struct aspeed_lpc_snoop_channel_cfg *cfg, 196 + u16 lpc_port) 221 197 { 222 198 const struct aspeed_lpc_snoop_model_data *model_data; 223 - u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en; 224 - struct aspeed_lpc_snoop_channel *channel; 225 199 int rc = 0; 226 - 227 - channel = &lpc_snoop->chan[index]; 228 200 229 201 if (WARN_ON(channel->enabled)) 230 202 return -EBUSY; 231 203 232 204 init_waitqueue_head(&channel->wq); 233 205 206 + channel->cfg = cfg; 234 207 channel->miscdev.minor = MISC_DYNAMIC_MINOR; 235 208 channel->miscdev.fops = &snoop_fops; 236 209 channel->miscdev.parent = dev; 237 210 238 211 channel->miscdev.name = 239 - devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, index); 212 + devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, cfg->index); 240 213 if (!channel->miscdev.name) 241 214 return -ENOMEM; 242 215 ··· 248 223 goto err_free_fifo; 249 224 250 225 /* Enable LPC snoop channel at requested port */ 251 - switch (index) { 252 - case 0: 253 - hicr5_en = HICR5_EN_SNP0W | HICR5_ENINT_SNP0W; 254 - snpwadr_mask = SNPWADR_CH0_MASK; 255 - snpwadr_shift = SNPWADR_CH0_SHIFT; 256 - hicrb_en = HICRB_ENSNP0D; 257 - break; 258 - case 1: 259 - hicr5_en = HICR5_EN_SNP1W | HICR5_ENINT_SNP1W; 260 - snpwadr_mask = SNPWADR_CH1_MASK; 261 - snpwadr_shift = SNPWADR_CH1_SHIFT; 262 - hicrb_en = HICRB_ENSNP1D; 263 - break; 264 - default: 265 - rc = -EINVAL; 266 - goto err_misc_deregister; 267 - } 268 - 269 - regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en); 270 - regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask, 271 - lpc_port << snpwadr_shift); 226 + regmap_set_bits(lpc_snoop->regmap, HICR5, cfg->hicr5_en); 227 + regmap_update_bits(lpc_snoop->regmap, SNPWADR, cfg->snpwadr_mask, 228 + lpc_port << cfg->snpwadr_shift); 272 229 273 230 model_data = of_device_get_match_data(dev); 274 231 if (model_data && model_data->has_hicrb_ensnp) 275 - regmap_update_bits(lpc_snoop->regmap, HICRB, hicrb_en, hicrb_en); 232 + regmap_set_bits(lpc_snoop->regmap, HICRB, cfg->hicrb_en); 276 233 277 234 channel->enabled = true; 278 235 279 236 return 0; 280 237 281 - err_misc_deregister: 282 - misc_deregister(&channel->miscdev); 283 238 err_free_fifo: 284 239 kfifo_free(&channel->fifo); 285 240 return rc; ··· 267 262 268 263 __attribute__((nonnull)) 269 264 static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop, 270 - enum aspeed_lpc_snoop_index index) 265 + struct aspeed_lpc_snoop_channel *channel) 271 266 { 272 - struct aspeed_lpc_snoop_channel *channel; 273 - 274 - channel = &lpc_snoop->chan[index]; 275 - 276 267 if (!channel->enabled) 277 268 return; 278 269 279 270 /* Disable interrupts along with the device */ 280 - switch (index) { 281 - case 0: 282 - regmap_update_bits(lpc_snoop->regmap, HICR5, 283 - HICR5_EN_SNP0W | HICR5_ENINT_SNP0W, 284 - 0); 285 - break; 286 - case 1: 287 - regmap_update_bits(lpc_snoop->regmap, HICR5, 288 - HICR5_EN_SNP1W | HICR5_ENINT_SNP1W, 289 - 0); 290 - break; 291 - default: 292 - return; 293 - } 271 + regmap_clear_bits(lpc_snoop->regmap, HICR5, channel->cfg->hicr5_en); 294 272 295 273 channel->enabled = false; 296 274 /* Consider improving safety wrt concurrent reader(s) */ ··· 286 298 struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev); 287 299 288 300 /* Disable both snoop channels */ 289 - aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_0); 290 - aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_1); 301 + aspeed_lpc_disable_snoop(lpc_snoop, &lpc_snoop->chan[0]); 302 + aspeed_lpc_disable_snoop(lpc_snoop, &lpc_snoop->chan[1]); 291 303 } 292 304 293 305 static int aspeed_lpc_snoop_probe(struct platform_device *pdev) ··· 326 338 if (rc) 327 339 return rc; 328 340 341 + static_assert(ARRAY_SIZE(channel_cfgs) == ARRAY_SIZE(lpc_snoop->chan), 342 + "Broken implementation assumption regarding cfg count"); 329 343 for (idx = ASPEED_LPC_SNOOP_INDEX_0; idx <= ASPEED_LPC_SNOOP_INDEX_MAX; idx++) { 330 344 u32 port; 331 345 ··· 335 345 if (rc) 336 346 break; 337 347 338 - rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, idx, port); 348 + rc = aspeed_lpc_enable_snoop(dev, lpc_snoop, &lpc_snoop->chan[idx], 349 + &channel_cfgs[idx], port); 339 350 if (rc) 340 351 goto cleanup_channels; 341 352 }