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

can: sja1000: of: add per-compatible init hook

This commit adds the capability to allocate and init private data
embedded in the sja1000_priv structure on a per-compatible basis. The
device node is passed as a parameter of the init callback to allow
parsing of custom device tree properties.

Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Damien Riegel and committed by
Marc Kleine-Budde
f49cbe6b 80c804bf

+31 -9
+31 -9
drivers/net/can/sja1000/sja1000_platform.c
··· 27 27 #include <linux/can/platform/sja1000.h> 28 28 #include <linux/io.h> 29 29 #include <linux/of.h> 30 + #include <linux/of_device.h> 30 31 #include <linux/of_irq.h> 31 32 32 33 #include "sja1000.h" ··· 40 39 MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus"); 41 40 MODULE_ALIAS("platform:" DRV_NAME); 42 41 MODULE_LICENSE("GPL v2"); 42 + 43 + struct sja1000_of_data { 44 + size_t priv_sz; 45 + int (*init)(struct sja1000_priv *priv, struct device_node *of); 46 + }; 43 47 44 48 static u8 sp_read_reg8(const struct sja1000_priv *priv, int reg) 45 49 { ··· 160 154 priv->cdr |= CDR_CBP; /* default */ 161 155 } 162 156 157 + static const struct of_device_id sp_of_table[] = { 158 + { .compatible = "nxp,sja1000", .data = NULL, }, 159 + { /* sentinel */ }, 160 + }; 161 + MODULE_DEVICE_TABLE(of, sp_of_table); 162 + 163 163 static int sp_probe(struct platform_device *pdev) 164 164 { 165 165 int err, irq = 0; ··· 175 163 struct resource *res_mem, *res_irq = NULL; 176 164 struct sja1000_platform_data *pdata; 177 165 struct device_node *of = pdev->dev.of_node; 166 + const struct of_device_id *of_id; 167 + const struct sja1000_of_data *of_data = NULL; 168 + size_t priv_sz = 0; 178 169 179 170 pdata = dev_get_platdata(&pdev->dev); 180 171 if (!pdata && !of) { ··· 206 191 if (!irq && !res_irq) 207 192 return -ENODEV; 208 193 209 - dev = alloc_sja1000dev(0); 194 + of_id = of_match_device(sp_of_table, &pdev->dev); 195 + if (of_id && of_id->data) { 196 + of_data = of_id->data; 197 + priv_sz = of_data->priv_sz; 198 + } 199 + 200 + dev = alloc_sja1000dev(priv_sz); 210 201 if (!dev) 211 202 return -ENOMEM; 212 203 priv = netdev_priv(dev); ··· 229 208 dev->irq = irq; 230 209 priv->reg_base = addr; 231 210 232 - if (of) 211 + if (of) { 233 212 sp_populate_of(priv, of); 234 - else 213 + 214 + if (of_data && of_data->init) { 215 + err = of_data->init(priv, of); 216 + if (err) 217 + goto exit_free; 218 + } 219 + } else { 235 220 sp_populate(priv, pdata, res_mem->flags); 221 + } 236 222 237 223 platform_set_drvdata(pdev, dev); 238 224 SET_NETDEV_DEV(dev, &pdev->dev); ··· 269 241 270 242 return 0; 271 243 } 272 - 273 - static const struct of_device_id sp_of_table[] = { 274 - {.compatible = "nxp,sja1000"}, 275 - {}, 276 - }; 277 - MODULE_DEVICE_TABLE(of, sp_of_table); 278 244 279 245 static struct platform_driver sp_driver = { 280 246 .probe = sp_probe,