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

powerpc: Add support for multiple gfar mdio interfaces

The old code assumed there was only one, but the 8572 actually has 3.

Also, our usual id, 0xe0024520, gets resolved to -1 somewhere, and this was
preventing the multiple buses from having different ids. So we only keep
the low 20 bits, which have the interesting info, anyway.

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Andy Fleming and committed by
Kumar Gala
4cd7e1cb a47fda93

+39 -47
+39 -47
arch/powerpc/sysdev/fsl_soc.c
··· 207 207 arch_initcall(of_add_fixed_phys); 208 208 #endif /* CONFIG_FIXED_PHY */ 209 209 210 - static int __init gfar_mdio_of_init(void) 210 + static int gfar_mdio_of_init_one(struct device_node *np) 211 211 { 212 - struct device_node *np = NULL; 212 + int k; 213 + struct device_node *child = NULL; 214 + struct gianfar_mdio_data mdio_data; 213 215 struct platform_device *mdio_dev; 214 216 struct resource res; 215 217 int ret; 216 218 217 - np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio"); 219 + memset(&res, 0, sizeof(res)); 220 + memset(&mdio_data, 0, sizeof(mdio_data)); 218 221 219 - /* try the deprecated version */ 220 - if (!np) 221 - np = of_find_compatible_node(np, "mdio", "gianfar"); 222 + ret = of_address_to_resource(np, 0, &res); 223 + if (ret) 224 + return ret; 222 225 223 - if (np) { 224 - int k; 225 - struct device_node *child = NULL; 226 - struct gianfar_mdio_data mdio_data; 226 + mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", 227 + res.start&0xfffff, &res, 1); 228 + if (IS_ERR(mdio_dev)) 229 + return PTR_ERR(mdio_dev); 227 230 228 - memset(&res, 0, sizeof(res)); 229 - memset(&mdio_data, 0, sizeof(mdio_data)); 231 + for (k = 0; k < 32; k++) 232 + mdio_data.irq[k] = PHY_POLL; 230 233 231 - ret = of_address_to_resource(np, 0, &res); 232 - if (ret) 233 - goto err; 234 - 235 - mdio_dev = 236 - platform_device_register_simple("fsl-gianfar_mdio", 237 - res.start, &res, 1); 238 - if (IS_ERR(mdio_dev)) { 239 - ret = PTR_ERR(mdio_dev); 240 - goto err; 234 + while ((child = of_get_next_child(np, child)) != NULL) { 235 + int irq = irq_of_parse_and_map(child, 0); 236 + if (irq != NO_IRQ) { 237 + const u32 *id = of_get_property(child, "reg", NULL); 238 + mdio_data.irq[*id] = irq; 241 239 } 242 - 243 - for (k = 0; k < 32; k++) 244 - mdio_data.irq[k] = PHY_POLL; 245 - 246 - while ((child = of_get_next_child(np, child)) != NULL) { 247 - int irq = irq_of_parse_and_map(child, 0); 248 - if (irq != NO_IRQ) { 249 - const u32 *id = of_get_property(child, 250 - "reg", NULL); 251 - mdio_data.irq[*id] = irq; 252 - } 253 - } 254 - 255 - ret = 256 - platform_device_add_data(mdio_dev, &mdio_data, 257 - sizeof(struct gianfar_mdio_data)); 258 - if (ret) 259 - goto unreg; 260 240 } 261 241 262 - of_node_put(np); 263 - return 0; 242 + ret = platform_device_add_data(mdio_dev, &mdio_data, 243 + sizeof(struct gianfar_mdio_data)); 244 + if (ret) 245 + platform_device_unregister(mdio_dev); 264 246 265 - unreg: 266 - platform_device_unregister(mdio_dev); 267 - err: 268 - of_node_put(np); 269 247 return ret; 248 + } 249 + 250 + static int __init gfar_mdio_of_init(void) 251 + { 252 + struct device_node *np = NULL; 253 + 254 + for_each_compatible_node(np, NULL, "fsl,gianfar-mdio") 255 + gfar_mdio_of_init_one(np); 256 + 257 + /* try the deprecated version */ 258 + for_each_compatible_node(np, "mdio", "gianfar"); 259 + gfar_mdio_of_init_one(np); 260 + 261 + return 0; 270 262 } 271 263 272 264 arch_initcall(gfar_mdio_of_init); ··· 385 393 386 394 gfar_data.phy_id = *id; 387 395 snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%llx", 388 - (unsigned long long)res.start); 396 + (unsigned long long)res.start&0xfffff); 389 397 390 398 of_node_put(phy); 391 399 of_node_put(mdio);