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 | ||
cdd280b9 | 23 | #include <plat/gpmc.h> |
ac839b3c | 24 | #include "gpmc-smsc911x.h" |
cdd280b9 | 25 | |
cdd280b9 TN |
26 | static struct resource gpmc_smsc911x_resources[] = { |
27 | [0] = { | |
28 | .flags = IORESOURCE_MEM, | |
29 | }, | |
30 | [1] = { | |
f0949f73 | 31 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, |
cdd280b9 TN |
32 | }, |
33 | }; | |
34 | ||
35 | static struct smsc911x_platform_config gpmc_smsc911x_config = { | |
36 | .phy_interface = PHY_INTERFACE_MODE_MII, | |
37 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | |
38 | .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, | |
cdd280b9 TN |
39 | }; |
40 | ||
cdd280b9 TN |
41 | /* |
42 | * Initialize smsc911x device connected to the GPMC. Note that we | |
43 | * assume that pin multiplexing is done in the board-*.c file, | |
44 | * or in the bootloader. | |
45 | */ | |
54da0784 | 46 | void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) |
cdd280b9 | 47 | { |
21b42731 | 48 | struct platform_device *pdev; |
cdd280b9 TN |
49 | unsigned long cs_mem_base; |
50 | int ret; | |
51 | ||
cdd280b9 | 52 | if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { |
11383a9b | 53 | pr_err("Failed to request GPMC mem region\n"); |
cdd280b9 TN |
54 | return; |
55 | } | |
56 | ||
57 | gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0; | |
58 | gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff; | |
59 | ||
bc593f5d | 60 | if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) { |
11383a9b | 61 | pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq); |
cdd280b9 TN |
62 | goto free1; |
63 | } | |
64 | ||
cdd280b9 | 65 | gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq); |
cdd280b9 TN |
66 | |
67 | if (gpio_is_valid(gpmc_cfg->gpio_reset)) { | |
bc593f5d IG |
68 | ret = gpio_request_one(gpmc_cfg->gpio_reset, |
69 | GPIOF_OUT_INIT_HIGH, "smsc911x reset"); | |
cdd280b9 | 70 | if (ret) { |
11383a9b IG |
71 | pr_err("Failed to request reset GPIO%d\n", |
72 | gpmc_cfg->gpio_reset); | |
cdd280b9 TN |
73 | goto free2; |
74 | } | |
75 | ||
cdd280b9 TN |
76 | gpio_set_value(gpmc_cfg->gpio_reset, 0); |
77 | msleep(100); | |
78 | gpio_set_value(gpmc_cfg->gpio_reset, 1); | |
79 | } | |
80 | ||
a0dbf2a7 | 81 | gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT; |
f0949f73 | 82 | |
21b42731 MR |
83 | pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id, |
84 | gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), | |
85 | &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config)); | |
86 | if (!pdev) { | |
11383a9b | 87 | pr_err("Unable to register platform device\n"); |
cdd280b9 TN |
88 | gpio_free(gpmc_cfg->gpio_reset); |
89 | goto free2; | |
90 | } | |
91 | ||
92 | return; | |
93 | ||
94 | free2: | |
95 | gpio_free(gpmc_cfg->gpio_irq); | |
96 | free1: | |
97 | gpmc_cs_free(gpmc_cfg->cs); | |
98 | ||
11383a9b | 99 | pr_err("Could not initialize smsc911x device\n"); |
cdd280b9 | 100 | } |