Commit | Line | Data |
---|---|---|
cdd280b9 TN |
1 | /* |
2 | * linux/arch/arm/mach-omap2/gpmc-smsc911x.c | |
3 | * | |
4 | * Copyright (C) 2009 Li-Pro.Net | |
5 | * Stephan Linz <linz@li-pro.net> | |
6 | * | |
7 | * Modified from linux/arch/arm/mach-omap2/gpmc-smc91x.c | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License version 2 as | |
11 | * published by the Free Software Foundation. | |
12 | */ | |
11383a9b | 13 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
cdd280b9 TN |
14 | |
15 | #include <linux/kernel.h> | |
16 | #include <linux/platform_device.h> | |
17 | #include <linux/gpio.h> | |
18 | #include <linux/delay.h> | |
19 | #include <linux/interrupt.h> | |
20 | #include <linux/io.h> | |
21 | #include <linux/smsc911x.h> | |
22 | ||
23 | #include <plat/board.h> | |
24 | #include <plat/gpmc.h> | |
25 | #include <plat/gpmc-smsc911x.h> | |
26 | ||
cdd280b9 TN |
27 | static struct resource gpmc_smsc911x_resources[] = { |
28 | [0] = { | |
29 | .flags = IORESOURCE_MEM, | |
30 | }, | |
31 | [1] = { | |
f0949f73 | 32 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, |
cdd280b9 TN |
33 | }, |
34 | }; | |
35 | ||
36 | static struct smsc911x_platform_config gpmc_smsc911x_config = { | |
37 | .phy_interface = PHY_INTERFACE_MODE_MII, | |
38 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | |
39 | .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, | |
cdd280b9 TN |
40 | }; |
41 | ||
cdd280b9 TN |
42 | /* |
43 | * Initialize smsc911x device connected to the GPMC. Note that we | |
44 | * assume that pin multiplexing is done in the board-*.c file, | |
45 | * or in the bootloader. | |
46 | */ | |
54da0784 | 47 | void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) |
cdd280b9 | 48 | { |
21b42731 | 49 | struct platform_device *pdev; |
cdd280b9 TN |
50 | unsigned long cs_mem_base; |
51 | int ret; | |
52 | ||
cdd280b9 | 53 | if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { |
11383a9b | 54 | pr_err("Failed to request GPMC mem region\n"); |
cdd280b9 TN |
55 | return; |
56 | } | |
57 | ||
58 | gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0; | |
59 | gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff; | |
60 | ||
bc593f5d | 61 | if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) { |
11383a9b | 62 | pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq); |
cdd280b9 TN |
63 | goto free1; |
64 | } | |
65 | ||
cdd280b9 | 66 | gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq); |
cdd280b9 TN |
67 | |
68 | if (gpio_is_valid(gpmc_cfg->gpio_reset)) { | |
bc593f5d IG |
69 | ret = gpio_request_one(gpmc_cfg->gpio_reset, |
70 | GPIOF_OUT_INIT_HIGH, "smsc911x reset"); | |
cdd280b9 | 71 | if (ret) { |
11383a9b IG |
72 | pr_err("Failed to request reset GPIO%d\n", |
73 | gpmc_cfg->gpio_reset); | |
cdd280b9 TN |
74 | goto free2; |
75 | } | |
76 | ||
cdd280b9 TN |
77 | gpio_set_value(gpmc_cfg->gpio_reset, 0); |
78 | msleep(100); | |
79 | gpio_set_value(gpmc_cfg->gpio_reset, 1); | |
80 | } | |
81 | ||
a0dbf2a7 | 82 | gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT; |
f0949f73 | 83 | |
21b42731 MR |
84 | pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id, |
85 | gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), | |
86 | &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config)); | |
87 | if (!pdev) { | |
11383a9b | 88 | pr_err("Unable to register platform device\n"); |
cdd280b9 TN |
89 | gpio_free(gpmc_cfg->gpio_reset); |
90 | goto free2; | |
91 | } | |
92 | ||
93 | return; | |
94 | ||
95 | free2: | |
96 | gpio_free(gpmc_cfg->gpio_irq); | |
97 | free1: | |
98 | gpmc_cs_free(gpmc_cfg->cs); | |
99 | ||
11383a9b | 100 | pr_err("Could not initialize smsc911x device\n"); |
cdd280b9 | 101 | } |